From 51021b1d421a7d055ff44f9b6afe11377b825c5c Mon Sep 17 00:00:00 2001 From: Tobias Thiel Date: Sat, 4 Jan 2020 18:04:30 -0800 Subject: [PATCH 0001/1250] rustc_session: allow overriding lint level of individual lints from a group --- src/librustc_session/config.rs | 13 ++++++++++--- .../ui-fulldeps/lint-group-denied-lint-allowed.rs | 7 +++++++ 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/test/ui-fulldeps/lint-group-denied-lint-allowed.rs diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index b6b22e298ca..fd4e47baad5 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -986,19 +986,26 @@ pub fn get_cmd_lint_options( matches: &getopts::Matches, error_format: ErrorOutputType, ) -> (Vec<(String, lint::Level)>, bool, Option) { - let mut lint_opts = vec![]; + let mut lint_opts_with_position = vec![]; let mut describe_lints = false; for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] { - for lint_name in matches.opt_strs(level.as_str()) { + for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { if lint_name == "help" { describe_lints = true; } else { - lint_opts.push((lint_name.replace("-", "_"), level)); + lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level)); } } } + lint_opts_with_position.sort_by_key(|x| x.0); + let lint_opts = lint_opts_with_position + .iter() + .cloned() + .map(|(_, lint_name, level)| (lint_name, level)) + .collect(); + let lint_cap = matches.opt_str("cap-lints").map(|cap| { lint::Level::from_str(&cap) .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap))) diff --git a/src/test/ui-fulldeps/lint-group-denied-lint-allowed.rs b/src/test/ui-fulldeps/lint-group-denied-lint-allowed.rs new file mode 100644 index 00000000000..7498745f206 --- /dev/null +++ b/src/test/ui-fulldeps/lint-group-denied-lint-allowed.rs @@ -0,0 +1,7 @@ +// aux-build:lint-group-plugin-test.rs +// check-pass +// compile-flags: -D unused -A unused-variables + +fn main() { + let x = 1; +} From 34417792deed6f0e570e9c7b01a24f1d05b70519 Mon Sep 17 00:00:00 2001 From: Tobias Thiel Date: Sat, 4 Jan 2020 23:35:43 -0800 Subject: [PATCH 0002/1250] tools/compiletest: fix argument ordering for allowing unused in ui & compile-fail tests --- src/tools/compiletest/src/runtest.rs | 42 ++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 226a12c6734..cfa4db69a6a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1478,11 +1478,7 @@ impl<'test> TestCx<'test> { WillExecute::No => TargetLocation::ThisDirectory(self.output_base_dir()), }; - let mut rustc = self.make_compile_args(&self.testpaths.file, output_file, emit_metadata); - - rustc.arg("-L").arg(&self.aux_output_dir_name()); - - match self.config.mode { + let allow_unused = match self.config.mode { CompileFail | Ui => { // compile-fail and ui tests tend to have tons of unused code as // it's just testing various pieces of the compile, but we don't @@ -1495,11 +1491,18 @@ impl<'test> TestCx<'test> { // via command line flags. && local_pm != Some(PassMode::Run) { - rustc.args(&["-A", "unused"]); + AllowUnused::Yes + } else { + AllowUnused::No } } - _ => {} - } + _ => AllowUnused::No, + }; + + let mut rustc = + self.make_compile_args(&self.testpaths.file, output_file, emit_metadata, allow_unused); + + rustc.arg("-L").arg(&self.aux_output_dir_name()); self.compose_and_run_compiler(rustc, None) } @@ -1710,7 +1713,8 @@ impl<'test> TestCx<'test> { // Create the directory for the stdout/stderr files. create_dir_all(aux_cx.output_base_dir()).unwrap(); let input_file = &aux_testpaths.file; - let mut aux_rustc = aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No); + let mut aux_rustc = + aux_cx.make_compile_args(input_file, aux_output, EmitMetadata::No, AllowUnused::No); let (dylib, crate_type) = if aux_props.no_prefer_dynamic { (true, None) @@ -1819,6 +1823,7 @@ impl<'test> TestCx<'test> { input_file: &Path, output_file: TargetLocation, emit_metadata: EmitMetadata, + allow_unused: AllowUnused, ) -> Command { let is_rustdoc = self.is_rustdoc(); let mut rustc = if !is_rustdoc { @@ -1951,6 +1956,13 @@ impl<'test> TestCx<'test> { rustc.arg("-Ctarget-feature=-crt-static"); } + match allow_unused { + AllowUnused::Yes => { + rustc.args(&["-A", "unused"]); + } + AllowUnused::No => {} + } + rustc.args(&self.props.compile_flags); rustc @@ -2134,7 +2146,8 @@ impl<'test> TestCx<'test> { let output_file = TargetLocation::ThisDirectory(self.output_base_dir()); let input_file = &self.testpaths.file; - let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No); + let mut rustc = + self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No); rustc.arg("-L").arg(aux_dir).arg("--emit=llvm-ir"); self.compose_and_run_compiler(rustc, None) @@ -2147,7 +2160,8 @@ impl<'test> TestCx<'test> { let output_file = TargetLocation::ThisFile(output_path.clone()); let input_file = &self.testpaths.file; - let mut rustc = self.make_compile_args(input_file, output_file, EmitMetadata::No); + let mut rustc = + self.make_compile_args(input_file, output_file, EmitMetadata::No, AllowUnused::No); rustc.arg("-L").arg(self.aux_output_dir_name()); @@ -2999,6 +3013,7 @@ impl<'test> TestCx<'test> { &self.testpaths.file.with_extension(UI_FIXED), TargetLocation::ThisFile(self.make_exe_name()), emit_metadata, + AllowUnused::No, ); rustc.arg("-L").arg(&self.aux_output_dir_name()); let res = self.compose_and_run_compiler(rustc, None); @@ -3486,6 +3501,11 @@ enum ExpectedLine> { Text(T), } +enum AllowUnused { + Yes, + No, +} + impl fmt::Debug for ExpectedLine where T: AsRef + fmt::Debug, From 35c4aae99ece980c7c594940724f0728fcccf226 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Fri, 10 Jan 2020 18:48:37 -0800 Subject: [PATCH 0003/1250] Added tvOS as a backend --- .../spec/aarch64_apple_tvos.rs | 25 ++++ src/librustc_target/spec/apple_tvos_base.rs | 123 ++++++++++++++++++ src/librustc_target/spec/mod.rs | 3 + src/librustc_target/spec/x86_64_apple_tvos.rs | 19 +++ 4 files changed, 170 insertions(+) create mode 100644 src/librustc_target/spec/aarch64_apple_tvos.rs create mode 100644 src/librustc_target/spec/apple_tvos_base.rs create mode 100644 src/librustc_target/spec/x86_64_apple_tvos.rs diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs new file mode 100644 index 00000000000..420e0d1c64c --- /dev/null +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -0,0 +1,25 @@ +use super::apple_tvos_base::{opts, Arch}; +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = opts(Arch::Arm64)?; + Ok(Target { + llvm_target: "arm64-apple-tvos".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-i128:128-n32:64-S128".to_string(), + arch: "aarch64".to_string(), + target_os: "tvos".to_string(), + target_env: String::new(), + target_vendor: "apple".to_string(), + linker_flavor: LinkerFlavor::Gcc, + options: TargetOptions { + features: "+neon,+fp-armv8,+cyclone".to_string(), + eliminate_frame_pointer: false, + max_atomic_width: Some(128), + abi_blacklist: super::arm_base::abi_blacklist(), + ..base + }, + }) +} diff --git a/src/librustc_target/spec/apple_tvos_base.rs b/src/librustc_target/spec/apple_tvos_base.rs new file mode 100644 index 00000000000..70dc8093f88 --- /dev/null +++ b/src/librustc_target/spec/apple_tvos_base.rs @@ -0,0 +1,123 @@ +use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; +use std::env; +use std::io; +use std::path::Path; +use std::process::Command; + +use Arch::*; + +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum Arch { + Arm64, + X86_64, +} + +impl Arch { + pub fn to_string(self) -> &'static str { + match self { + Arm64 => "arm64", + X86_64 => "x86_64", + } + } +} + +pub fn get_sdk_root(sdk_name: &str) -> Result { + // Following what clang does + // (https://github.com/llvm/llvm-project/blob/ + // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678) + // to allow the SDK path to be set. (For clang, xcrun sets + // SDKROOT; for rustc, the user or build system can set it, or we + // can fall back to checking for xcrun on PATH.) + if let Some(sdkroot) = env::var("SDKROOT").ok() { + let p = Path::new(&sdkroot); + match sdk_name { + // Ignore `SDKROOT` if it's clearly set for the wrong platform. + "appletvos" + if sdkroot.contains("TVSimulator.platform") + || sdkroot.contains("MacOSX.platform") => + { + () + } + "appletvsimulator" + if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => + { + () + } + // Ignore `SDKROOT` if it's not a valid path. + _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), + _ => return Ok(sdkroot), + } + } + let res = + Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then( + |output| { + if output.status.success() { + Ok(String::from_utf8(output.stdout).unwrap()) + } else { + let error = String::from_utf8(output.stderr); + let error = format!("process exit with error: {}", error.unwrap()); + Err(io::Error::new(io::ErrorKind::Other, &error[..])) + } + }, + ); + + match res { + Ok(output) => Ok(output.trim().to_string()), + Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)), + } +} + +fn build_pre_link_args(arch: Arch) -> Result { + let sdk_name = match arch { + Arm64 => "appletvos", + X86_64 => "appletvsimulator", + }; + + let arch_name = arch.to_string(); + + let sdk_root = get_sdk_root(sdk_name)?; + + let mut args = LinkArgs::new(); + args.insert( + LinkerFlavor::Gcc, + vec![ + "-arch".to_string(), + arch_name.to_string(), + "-isysroot".to_string(), + sdk_root.clone(), + "-Wl,-syslibroot".to_string(), + sdk_root, + ], + ); + + Ok(args) +} + +fn target_cpu(arch: Arch) -> String { + match arch { + Arm64 => "cyclone", + X86_64 => "core2", + } + .to_string() +} + +fn link_env_remove(arch: Arch) -> Vec { + match arch { + Arm64 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], + } +} + +pub fn opts(arch: Arch) -> Result { + let pre_link_args = build_pre_link_args(arch)?; + Ok(TargetOptions { + cpu: target_cpu(arch), + dynamic_linking: false, + executables: true, + pre_link_args, + link_env_remove: link_env_remove(arch), + has_elf_tls: false, + eliminate_frame_pointer: false, + ..super::apple_base::opts() + }) +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index f08634cc770..fddbcb90da1 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -48,6 +48,7 @@ pub mod abi; mod android_base; mod apple_base; mod apple_ios_base; +mod apple_tvos_base; mod arm_base; mod cloudabi_base; mod dragonfly_base; @@ -434,6 +435,8 @@ supported_targets! { ("armv7-apple-ios", armv7_apple_ios), ("armv7s-apple-ios", armv7s_apple_ios), ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi), + ("aarch64-apple-tvos", aarch64_apple_tvos), + ("x86_64-apple-tvos", x86_64_apple_tvos), ("armebv7r-none-eabi", armebv7r_none_eabi), ("armebv7r-none-eabihf", armebv7r_none_eabihf), diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs new file mode 100644 index 00000000000..e40d978e750 --- /dev/null +++ b/src/librustc_target/spec/x86_64_apple_tvos.rs @@ -0,0 +1,19 @@ +use super::apple_tvos_base::{opts, Arch}; +use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; + +pub fn target() -> TargetResult { + let base = opts(Arch::X86_64)?; + Ok(Target { + llvm_target: "x86_64-apple-tvos".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: "tvos".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 }, + }) +} From 21edd2ae2cc4c06d8ea98051c47d24dc3c4e2238 Mon Sep 17 00:00:00 2001 From: Tobias Thiel Date: Sun, 12 Jan 2020 22:11:27 -0800 Subject: [PATCH 0004/1250] convert match statement to if let --- src/tools/compiletest/src/runtest.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index cfa4db69a6a..84bae6cd27e 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1956,11 +1956,8 @@ impl<'test> TestCx<'test> { rustc.arg("-Ctarget-feature=-crt-static"); } - match allow_unused { - AllowUnused::Yes => { - rustc.args(&["-A", "unused"]); - } - AllowUnused::No => {} + if let AllowUnused::Yes = allow_unused { + rustc.args(&["-A", "unused"]); } rustc.args(&self.props.compile_flags); From 3fc9253a5a27771c72429a738d5379c34e1cd924 Mon Sep 17 00:00:00 2001 From: Tobias Thiel Date: Mon, 13 Jan 2020 20:03:28 -0800 Subject: [PATCH 0005/1250] rustc: add lint level cli ordering into the documentation --- src/doc/rustc/src/command-line-arguments.md | 8 ++++++++ src/doc/rustc/src/lints/levels.md | 12 ++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 577d03d1038..659f8f65e65 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -215,21 +215,29 @@ This controls which [target](targets/index.md) to produce. This flag will set which lints should be set to the [warn level](lints/levels.md#warn). +_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. + ## `-A`: set lint allowed This flag will set which lints should be set to the [allow level](lints/levels.md#allow). +_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. + ## `-D`: set lint denied This flag will set which lints should be set to the [deny level](lints/levels.md#deny). +_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. + ## `-F`: set lint forbidden This flag will set which lints should be set to the [forbid level](lints/levels.md#forbid). +_Note:_ The order of these lint level arguments is taken into account, see [lint level via compiler flag](lints/levels.md#via-compiler-flag) for more information. + ## `-Z`: set unstable options diff --git a/src/doc/rustc/src/lints/levels.md b/src/doc/rustc/src/lints/levels.md index 2944e865663..3cfe2f698f3 100644 --- a/src/doc/rustc/src/lints/levels.md +++ b/src/doc/rustc/src/lints/levels.md @@ -164,6 +164,18 @@ And of course, you can mix these four flags together: $ rustc lib.rs --crate-type=lib -D missing-docs -A unused-variables ``` +The order of these command line arguments is taken into account. The following allows the `unused-variables` lint, because it is the last argument for that lint: + +```bash +$ rustc lib.rs --crate-type=lib -D unused-variables -A unused-variables +``` + +You can make use of this behavior by overriding the level of one specific lint out of a group of lints. The following example denies all the lints in the `unused` group, but explicitly allows the `unused-variables` lint in that group: + +```bash +$ rustc lib.rs --crate-type=lib -D unused -A unused-variables +``` + ### Via an attribute You can also modify the lint level with a crate-wide attribute: From a859ca5c87ddfaa635fb4cacf8a41e04fd9b02e8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 14:51:37 +0100 Subject: [PATCH 0006/1250] Fix `binary_heap::DrainSorted` drop leak on panics --- src/liballoc/collections/binary_heap.rs | 16 ++++++++++-- src/liballoc/tests/binary_heap.rs | 33 +++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index c527b378f74..f38fe997b73 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -147,7 +147,7 @@ use core::fmt; use core::iter::{FromIterator, FusedIterator, TrustedLen}; -use core::mem::{size_of, swap, ManuallyDrop}; +use core::mem::{self, size_of, swap, ManuallyDrop}; use core::ops::{Deref, DerefMut}; use core::ptr; @@ -1239,7 +1239,19 @@ pub struct DrainSorted<'a, T: Ord> { impl<'a, T: Ord> Drop for DrainSorted<'a, T> { /// Removes heap elements in heap order. fn drop(&mut self) { - while let Some(_) = self.inner.pop() {} + struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>); + + impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + while let Some(_) = self.0.inner.pop() {} + } + } + + while let Some(item) = self.inner.pop() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } } } diff --git a/src/liballoc/tests/binary_heap.rs b/src/liballoc/tests/binary_heap.rs index f49ca713921..be5516f54f3 100644 --- a/src/liballoc/tests/binary_heap.rs +++ b/src/liballoc/tests/binary_heap.rs @@ -1,6 +1,8 @@ use std::collections::binary_heap::{Drain, PeekMut}; use std::collections::BinaryHeap; use std::iter::TrustedLen; +use std::panic::{catch_unwind, AssertUnwindSafe}; +use std::sync::atomic::{AtomicU32, Ordering}; #[test] fn test_iterator() { @@ -275,6 +277,37 @@ fn test_drain_sorted() { assert!(q.is_empty()); } +#[test] +fn test_drain_sorted_leak() { + static DROPS: AtomicU32 = AtomicU32::new(0); + + #[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + DROPS.fetch_add(1, Ordering::SeqCst); + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut q = BinaryHeap::from(vec![ + D(0, false), + D(1, false), + D(2, false), + D(3, true), + D(4, false), + D(5, false), + ]); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_sorted()))).ok(); + + assert_eq!(DROPS.load(Ordering::SeqCst), 6); +} + #[test] fn test_extend_ref() { let mut a = BinaryHeap::new(); From 3e5eb2634cbb356b626e028a4be1305d4a44a023 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 16:41:19 +0100 Subject: [PATCH 0007/1250] Fix `VecDeque::truncate` leak on drop panic --- src/liballoc/collections/vec_deque.rs | 17 ++++++++++++- src/liballoc/tests/vec_deque.rs | 35 ++++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 2cc450bb68a..7307aad8a9e 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -866,6 +866,18 @@ impl VecDeque { /// ``` #[stable(feature = "deque_extras", since = "1.16.0")] pub fn truncate(&mut self, len: usize) { + /// Runs the destructor for all items in the slice when it gets dropped (normally or + /// during unwinding). + struct Dropper<'a, T>(&'a mut [T]); + + impl<'a, T> Drop for Dropper<'a, T> { + fn drop(&mut self) { + unsafe { + ptr::drop_in_place(self.0); + } + } + } + // Safe because: // // * Any slice passed to `drop_in_place` is valid; the second case has @@ -888,8 +900,11 @@ impl VecDeque { let drop_back = back as *mut _; let drop_front = front.get_unchecked_mut(len..) as *mut _; self.head = self.wrap_sub(self.head, num_dropped); + + // Make sure the second half is dropped even when a destructor + // in the first one panics. + let _back_dropper = Dropper(&mut *drop_back); ptr::drop_in_place(drop_front); - ptr::drop_in_place(drop_back); } } } diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 1ab3694a3ca..2dc50d0c70e 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -2,7 +2,7 @@ use std::collections::TryReserveError::*; use std::collections::{vec_deque::Drain, VecDeque}; use std::fmt::Debug; use std::mem::size_of; -use std::panic::catch_unwind; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::{isize, usize}; use crate::hash; @@ -1573,3 +1573,36 @@ fn test_try_rfold_moves_iter() { assert_eq!(iter.try_rfold(0_i8, |acc, &x| acc.checked_add(x)), None); assert_eq!(iter.next_back(), Some(&70)); } + +#[test] +fn truncate_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = VecDeque::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| q.truncate(1))).ok(); + + assert_eq!(unsafe { DROPS }, 7); +} From 5d04790dd2e73f3faf08d528e3675e131585ec01 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 17:54:26 +0100 Subject: [PATCH 0008/1250] Avoid leak in `vec::Drain` when item drop panics --- src/liballoc/tests/vec.rs | 39 +++++++++++++++++++++++++++++++++++ src/liballoc/vec.rs | 43 +++++++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 13 deletions(-) diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 2a9bfefc713..80acba0a3a1 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -1,6 +1,7 @@ use std::borrow::Cow; use std::collections::TryReserveError::*; use std::mem::size_of; +use std::panic::{catch_unwind, AssertUnwindSafe}; use std::vec::{Drain, IntoIter}; use std::{isize, usize}; @@ -585,6 +586,44 @@ fn test_drain_inclusive_out_of_bounds() { v.drain(5..=5); } +#[test] +fn test_drain_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug, PartialEq)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut v = vec![ + D(0, false), + D(1, false), + D(2, false), + D(3, false), + D(4, true), + D(5, false), + D(6, false), + ]; + + catch_unwind(AssertUnwindSafe(|| { + v.drain(2..=5); + })) + .ok(); + + assert_eq!(unsafe { DROPS }, 4); + assert_eq!(v, vec![D(0, false), D(1, false), D(6, false),]); +} + #[test] fn test_splice() { let mut v = vec![1, 2, 3, 4, 5]; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index e9cbf627846..ba71e42090c 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2700,23 +2700,40 @@ impl DoubleEndedIterator for Drain<'_, T> { #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_, T> { fn drop(&mut self) { - // exhaust self first - self.for_each(drop); + /// Continues dropping the remaining elements when a destructor unwinds. + struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); - if self.tail_len > 0 { - unsafe { - let source_vec = self.vec.as_mut(); - // memmove back untouched tail, update to new length - let start = source_vec.len(); - let tail = self.tail_start; - if tail != start { - let src = source_vec.as_ptr().add(tail); - let dst = source_vec.as_mut_ptr().add(start); - ptr::copy(src, dst, self.tail_len); + impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + // Continue the same loop we do below. This only runs when a destructor has + // panicked. If another one panics this will abort. + self.0.for_each(drop); + + if self.0.tail_len > 0 { + unsafe { + let source_vec = self.0.vec.as_mut(); + // memmove back untouched tail, update to new length + let start = source_vec.len(); + let tail = self.0.tail_start; + if tail != start { + let src = source_vec.as_ptr().add(tail); + let dst = source_vec.as_mut_ptr().add(start); + ptr::copy(src, dst, self.0.tail_len); + } + source_vec.set_len(start + self.0.tail_len); + } } - source_vec.set_len(start + self.tail_len); } } + + // exhaust self first + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + DropGuard(self); } } From dc492452dae29d75b14afe3559f5fb59be7f2d3a Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 18:36:35 +0100 Subject: [PATCH 0009/1250] Fix leak in btree_map::IntoIter when drop panics --- src/liballoc/collections/btree/map.rs | 17 +++++++++++++++- src/liballoc/tests/btree/map.rs | 28 +++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 302c2bcd5e4..71ddfc4ef63 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1381,7 +1381,22 @@ impl IntoIterator for BTreeMap { #[stable(feature = "btree_drop", since = "1.7.0")] impl Drop for IntoIter { fn drop(&mut self) { - self.for_each(drop); + struct DropGuard<'a, K, V>(&'a mut IntoIter); + + impl<'a, K, V> Drop for DropGuard<'a, K, V> { + fn drop(&mut self) { + // Continue the same loop we perform below. This only runs when unwinding, so we + // don't have to care about panics this time (they'll abort). + while let Some(_) = self.0.next() {} + } + } + + while let Some(pair) = self.next() { + let guard = DropGuard(self); + drop(pair); + mem::forget(guard); + } + unsafe { let leaf_node = ptr::read(&self.front).into_node(); if leaf_node.is_shared_root() { diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index f5be72c39b2..0729f341d86 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -5,7 +5,9 @@ use std::fmt::Debug; use std::iter::FromIterator; use std::ops::Bound::{self, Excluded, Included, Unbounded}; use std::ops::RangeBounds; +use std::panic::catch_unwind; use std::rc::Rc; +use std::sync::atomic::{AtomicU32, Ordering}; use super::DeterministicRng; @@ -980,3 +982,29 @@ fn test_split_off_large_random_sorted() { assert!(map.into_iter().eq(data.clone().into_iter().filter(|x| x.0 < key))); assert!(right.into_iter().eq(data.into_iter().filter(|x| x.0 >= key))); } + +#[test] +fn test_into_iter_drop_leak() { + static DROPS: AtomicU32 = AtomicU32::new(0); + + struct D; + + impl Drop for D { + fn drop(&mut self) { + if DROPS.fetch_add(1, Ordering::SeqCst) == 3 { + panic!("panic in `drop`"); + } + } + } + + let mut map = BTreeMap::new(); + map.insert("a", D); + map.insert("b", D); + map.insert("c", D); + map.insert("d", D); + map.insert("e", D); + + catch_unwind(move || drop(map.into_iter())).ok(); + + assert_eq!(DROPS.load(Ordering::SeqCst), 5); +} From b04ca13873d5ef5e5b18195aaf8925562302e8e0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 19:32:16 +0100 Subject: [PATCH 0010/1250] Fix leak in VecDeque::drain when drop panics --- src/liballoc/collections/vec_deque.rs | 82 ++++++++++++++++----------- src/liballoc/tests/vec_deque.rs | 38 +++++++++++++ 2 files changed, 86 insertions(+), 34 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 7307aad8a9e..de92c4997e3 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2575,47 +2575,61 @@ unsafe impl Send for Drain<'_, T> {} #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_, T> { fn drop(&mut self) { - self.for_each(drop); + struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); - let source_deque = unsafe { self.deque.as_mut() }; + impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + self.0.for_each(drop); - // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head - // - // T t h H - // [. . . o o x x o o . . .] - // - let orig_tail = source_deque.tail; - let drain_tail = source_deque.head; - let drain_head = self.after_tail; - let orig_head = self.after_head; + let source_deque = unsafe { self.0.deque.as_mut() }; - let tail_len = count(orig_tail, drain_tail, source_deque.cap()); - let head_len = count(drain_head, orig_head, source_deque.cap()); + // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head + // + // T t h H + // [. . . o o x x o o . . .] + // + let orig_tail = source_deque.tail; + let drain_tail = source_deque.head; + let drain_head = self.0.after_tail; + let orig_head = self.0.after_head; - // Restore the original head value - source_deque.head = orig_head; + let tail_len = count(orig_tail, drain_tail, source_deque.cap()); + let head_len = count(drain_head, orig_head, source_deque.cap()); - match (tail_len, head_len) { - (0, 0) => { - source_deque.head = 0; - source_deque.tail = 0; - } - (0, _) => { - source_deque.tail = drain_head; - } - (_, 0) => { - source_deque.head = drain_tail; - } - _ => unsafe { - if tail_len <= head_len { - source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); - source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); - } else { - source_deque.head = source_deque.wrap_add(drain_tail, head_len); - source_deque.wrap_copy(drain_tail, drain_head, head_len); + // Restore the original head value + source_deque.head = orig_head; + + match (tail_len, head_len) { + (0, 0) => { + source_deque.head = 0; + source_deque.tail = 0; + } + (0, _) => { + source_deque.tail = drain_head; + } + (_, 0) => { + source_deque.head = drain_tail; + } + _ => unsafe { + if tail_len <= head_len { + source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); + source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); + } else { + source_deque.head = source_deque.wrap_add(drain_tail, head_len); + source_deque.wrap_copy(drain_tail, drain_head, head_len); + } + }, } - }, + } } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + DropGuard(self); } } diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 2dc50d0c70e..07f1f098954 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -1606,3 +1606,41 @@ fn truncate_leak() { assert_eq!(unsafe { DROPS }, 7); } + +#[test] +fn test_drain_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug, PartialEq)] + struct D(u32, bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.1 { + panic!("panic in `drop`"); + } + } + } + + let mut v = VecDeque::new(); + v.push_back(D(4, false)); + v.push_back(D(5, false)); + v.push_back(D(6, false)); + v.push_front(D(3, false)); + v.push_front(D(2, true)); + v.push_front(D(1, false)); + v.push_front(D(0, false)); + + catch_unwind(AssertUnwindSafe(|| { + v.drain(1..=4); + })).ok(); + + assert_eq!(unsafe { DROPS }, 4); + assert_eq!(v.len(), 3); + drop(v); + assert_eq!(unsafe { DROPS }, 7); +} From 163ed23f0081d7283ccaef39141bc29879260663 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 13 Dec 2019 21:34:30 +0100 Subject: [PATCH 0011/1250] Fix leak in vec::IntoIter when a destructor panics --- src/liballoc/tests/vec.rs | 29 +++++++++++++++++++++++++++++ src/liballoc/vec.rs | 4 +++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 80acba0a3a1..2a027fd5d2b 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -765,6 +765,35 @@ fn test_into_iter_clone() { assert_eq!(it.next(), None); } +#[test] +fn test_into_iter_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let v = vec![ + D(false), + D(true), + D(false), + ]; + + catch_unwind(move || drop(v.into_iter())).ok(); + + assert_eq!(unsafe { DROPS }, 3); +} + #[test] fn test_cow_from() { let borrowed: &[_] = &["borrowed", "(slice)"]; diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index ba71e42090c..6589cc5b1f6 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2620,7 +2620,9 @@ impl Clone for IntoIter { unsafe impl<#[may_dangle] T> Drop for IntoIter { fn drop(&mut self) { // destroy the remaining elements - for _x in self.by_ref() {} + unsafe { + ptr::drop_in_place(self.as_mut_slice()); + } // RawVec handles deallocation let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) }; From 0ae16b47ffee866ee49f909ea213a28d8068cf56 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 14 Dec 2019 00:55:06 +0100 Subject: [PATCH 0012/1250] Avoid leak in DrainFilter when a drop panics --- src/liballoc/collections/linked_list.rs | 16 ++++++++++- src/liballoc/tests/linked_list.rs | 36 ++++++++++++++++++++++++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index b88ca8a0fb0..463ec67d668 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1565,7 +1565,21 @@ where F: FnMut(&mut T) -> bool, { fn drop(&mut self) { - self.for_each(drop); + struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) + where F: FnMut(&mut T) -> bool; + + impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> + where F: FnMut(&mut T) -> bool { + fn drop(&mut self) { + self.0.for_each(drop); + } + } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } } } diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index b7736515b26..aa3f582a165 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -1,5 +1,5 @@ use std::collections::LinkedList; -use std::panic::catch_unwind; +use std::panic::{catch_unwind, AssertUnwindSafe}; #[test] fn test_basic() { @@ -531,6 +531,40 @@ fn drain_filter_complex() { } } +#[test] +fn drain_filter_drop_panic_leak() { + static mut DROPS: i32 = 0; + + struct D(bool); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + + if self.0 { + panic!("panic in `drop`"); + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_back(D(false)); + q.push_front(D(false)); + q.push_front(D(true)); + q.push_front(D(false)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|_| true)))).ok(); + + assert_eq!(unsafe { DROPS }, 8); + assert!(q.is_empty()); +} + #[test] fn test_drop() { static mut DROPS: i32 = 0; From 1f373f4aeb279c6bf98976aee419db967c4f56f6 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 14 Dec 2019 01:01:28 +0100 Subject: [PATCH 0013/1250] Add test for panic in LL DrainFilter predicate --- src/liballoc/tests/linked_list.rs | 35 +++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index aa3f582a165..c40f99ee906 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -565,6 +565,41 @@ fn drain_filter_drop_panic_leak() { assert!(q.is_empty()); } +#[test] +fn drain_filter_pred_panic_leak() { + static mut DROPS: i32 = 0; + + #[derive(Debug)] + struct D(u32); + + impl Drop for D { + fn drop(&mut self) { + unsafe { + DROPS += 1; + } + } + } + + let mut q = LinkedList::new(); + q.push_back(D(3)); + q.push_back(D(4)); + q.push_back(D(5)); + q.push_back(D(6)); + q.push_back(D(7)); + q.push_front(D(2)); + q.push_front(D(1)); + q.push_front(D(0)); + + catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|item| if item.0 >= 2 { + panic!() + } else { + true + })))).ok(); + + assert_eq!(unsafe { DROPS }, 2); // 0 and 1 + assert_eq!(q.len(), 6); +} + #[test] fn test_drop() { static mut DROPS: i32 = 0; From 75f721df97fd7895b31a1d8c9ed05a368fc95d6d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 14 Dec 2019 17:06:22 +0100 Subject: [PATCH 0014/1250] Move VecDeque Drain iterator to new file --- src/liballoc/collections/vec_deque.rs | 126 +------------------- src/liballoc/collections/vec_deque/drain.rs | 126 ++++++++++++++++++++ 2 files changed, 131 insertions(+), 121 deletions(-) create mode 100644 src/liballoc/collections/vec_deque/drain.rs diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index de92c4997e3..85d1d98b8a9 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -22,6 +22,11 @@ use crate::collections::TryReserveError; use crate::raw_vec::RawVec; use crate::vec::Vec; +#[stable(feature = "drain", since = "1.6.0")] +pub use self::drain::Drain; + +mod drain; + #[cfg(test)] mod tests; @@ -2541,127 +2546,6 @@ impl ExactSizeIterator for IntoIter { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} -/// A draining iterator over the elements of a `VecDeque`. -/// -/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its -/// documentation for more. -/// -/// [`drain`]: struct.VecDeque.html#method.drain -/// [`VecDeque`]: struct.VecDeque.html -#[stable(feature = "drain", since = "1.6.0")] -pub struct Drain<'a, T: 'a> { - after_tail: usize, - after_head: usize, - iter: Iter<'a, T>, - deque: NonNull>, -} - -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Drain<'_, T> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_tuple("Drain") - .field(&self.after_tail) - .field(&self.after_head) - .field(&self.iter) - .finish() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Sync for Drain<'_, T> {} -#[stable(feature = "drain", since = "1.6.0")] -unsafe impl Send for Drain<'_, T> {} - -#[stable(feature = "drain", since = "1.6.0")] -impl Drop for Drain<'_, T> { - fn drop(&mut self) { - struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); - - impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { - fn drop(&mut self) { - self.0.for_each(drop); - - let source_deque = unsafe { self.0.deque.as_mut() }; - - // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head - // - // T t h H - // [. . . o o x x o o . . .] - // - let orig_tail = source_deque.tail; - let drain_tail = source_deque.head; - let drain_head = self.0.after_tail; - let orig_head = self.0.after_head; - - let tail_len = count(orig_tail, drain_tail, source_deque.cap()); - let head_len = count(drain_head, orig_head, source_deque.cap()); - - // Restore the original head value - source_deque.head = orig_head; - - match (tail_len, head_len) { - (0, 0) => { - source_deque.head = 0; - source_deque.tail = 0; - } - (0, _) => { - source_deque.tail = drain_head; - } - (_, 0) => { - source_deque.head = drain_tail; - } - _ => unsafe { - if tail_len <= head_len { - source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); - source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); - } else { - source_deque.head = source_deque.wrap_add(drain_tail, head_len); - source_deque.wrap_copy(drain_tail, drain_head, head_len); - } - }, - } - } - } - - while let Some(item) = self.next() { - let guard = DropGuard(self); - drop(item); - mem::forget(guard); - } - - DropGuard(self); - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl Iterator for Drain<'_, T> { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.iter.next().map(|elt| unsafe { ptr::read(elt) }) - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - self.iter.size_hint() - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl DoubleEndedIterator for Drain<'_, T> { - #[inline] - fn next_back(&mut self) -> Option { - self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) - } -} - -#[stable(feature = "drain", since = "1.6.0")] -impl ExactSizeIterator for Drain<'_, T> {} - -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Drain<'_, T> {} - #[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for VecDeque { fn eq(&self, other: &VecDeque) -> bool { diff --git a/src/liballoc/collections/vec_deque/drain.rs b/src/liballoc/collections/vec_deque/drain.rs new file mode 100644 index 00000000000..1ae94de75ad --- /dev/null +++ b/src/liballoc/collections/vec_deque/drain.rs @@ -0,0 +1,126 @@ +use core::iter::FusedIterator; +use core::ptr::{self, NonNull}; +use core::{fmt, mem}; + +use super::{count, Iter, VecDeque}; + +/// A draining iterator over the elements of a `VecDeque`. +/// +/// This `struct` is created by the [`drain`] method on [`VecDeque`]. See its +/// documentation for more. +/// +/// [`drain`]: struct.VecDeque.html#method.drain +/// [`VecDeque`]: struct.VecDeque.html +#[stable(feature = "drain", since = "1.6.0")] +pub struct Drain<'a, T: 'a> { + pub(crate) after_tail: usize, + pub(crate) after_head: usize, + pub(crate) iter: Iter<'a, T>, + pub(crate) deque: NonNull>, +} + +#[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Drain<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_tuple("Drain") + .field(&self.after_tail) + .field(&self.after_head) + .field(&self.iter) + .finish() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Sync for Drain<'_, T> {} +#[stable(feature = "drain", since = "1.6.0")] +unsafe impl Send for Drain<'_, T> {} + +#[stable(feature = "drain", since = "1.6.0")] +impl Drop for Drain<'_, T> { + fn drop(&mut self) { + struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); + + impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { + fn drop(&mut self) { + self.0.for_each(drop); + + let source_deque = unsafe { self.0.deque.as_mut() }; + + // T = source_deque_tail; H = source_deque_head; t = drain_tail; h = drain_head + // + // T t h H + // [. . . o o x x o o . . .] + // + let orig_tail = source_deque.tail; + let drain_tail = source_deque.head; + let drain_head = self.0.after_tail; + let orig_head = self.0.after_head; + + let tail_len = count(orig_tail, drain_tail, source_deque.cap()); + let head_len = count(drain_head, orig_head, source_deque.cap()); + + // Restore the original head value + source_deque.head = orig_head; + + match (tail_len, head_len) { + (0, 0) => { + source_deque.head = 0; + source_deque.tail = 0; + } + (0, _) => { + source_deque.tail = drain_head; + } + (_, 0) => { + source_deque.head = drain_tail; + } + _ => unsafe { + if tail_len <= head_len { + source_deque.tail = source_deque.wrap_sub(drain_head, tail_len); + source_deque.wrap_copy(source_deque.tail, orig_tail, tail_len); + } else { + source_deque.head = source_deque.wrap_add(drain_tail, head_len); + source_deque.wrap_copy(drain_tail, drain_head, head_len); + } + }, + } + } + } + + while let Some(item) = self.next() { + let guard = DropGuard(self); + drop(item); + mem::forget(guard); + } + + DropGuard(self); + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl Iterator for Drain<'_, T> { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.iter.next().map(|elt| unsafe { ptr::read(elt) }) + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + self.iter.size_hint() + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl DoubleEndedIterator for Drain<'_, T> { + #[inline] + fn next_back(&mut self) -> Option { + self.iter.next_back().map(|elt| unsafe { ptr::read(elt) }) + } +} + +#[stable(feature = "drain", since = "1.6.0")] +impl ExactSizeIterator for Drain<'_, T> {} + +#[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Drain<'_, T> {} From 52d6c90488abdd12a24c66f5e3490ae3136bb295 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 16 Dec 2019 21:42:46 +0100 Subject: [PATCH 0015/1250] Update comments in `Drain`s `Drop` impl --- src/liballoc/vec.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 6589cc5b1f6..4fa60846e22 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2702,13 +2702,14 @@ impl DoubleEndedIterator for Drain<'_, T> { #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_, T> { fn drop(&mut self) { - /// Continues dropping the remaining elements when a destructor unwinds. + /// Continues dropping the remaining elements in the `Drain`, then moves back the + /// un-`Drain`ed elements to restore the original `Vec`. struct DropGuard<'r, 'a, T>(&'r mut Drain<'a, T>); impl<'r, 'a, T> Drop for DropGuard<'r, 'a, T> { fn drop(&mut self) { - // Continue the same loop we do below. This only runs when a destructor has - // panicked. If another one panics this will abort. + // Continue the same loop we have below. If the loop already finished, this does + // nothing. self.0.for_each(drop); if self.0.tail_len > 0 { @@ -2735,6 +2736,7 @@ impl Drop for Drain<'_, T> { mem::forget(guard); } + // Drop a `DropGuard` to move back the non-drained tail of `self`. DropGuard(self); } } From e5987a062f487321bdfcbbdac4b0b30548258631 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 19 Jan 2020 20:50:00 +0100 Subject: [PATCH 0016/1250] Format --- src/liballoc/collections/linked_list.rs | 7 +++++-- src/liballoc/tests/linked_list.rs | 11 +++++------ src/liballoc/tests/vec.rs | 6 +----- src/liballoc/tests/vec_deque.rs | 5 +++-- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index 463ec67d668..399dbe5e4bf 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -1566,10 +1566,13 @@ where { fn drop(&mut self) { struct DropGuard<'r, 'a, T, F>(&'r mut DrainFilter<'a, T, F>) - where F: FnMut(&mut T) -> bool; + where + F: FnMut(&mut T) -> bool; impl<'r, 'a, T, F> Drop for DropGuard<'r, 'a, T, F> - where F: FnMut(&mut T) -> bool { + where + F: FnMut(&mut T) -> bool, + { fn drop(&mut self) { self.0.for_each(drop); } diff --git a/src/liballoc/tests/linked_list.rs b/src/liballoc/tests/linked_list.rs index c40f99ee906..afcb9e03fd0 100644 --- a/src/liballoc/tests/linked_list.rs +++ b/src/liballoc/tests/linked_list.rs @@ -590,13 +590,12 @@ fn drain_filter_pred_panic_leak() { q.push_front(D(1)); q.push_front(D(0)); - catch_unwind(AssertUnwindSafe(|| drop(q.drain_filter(|item| if item.0 >= 2 { - panic!() - } else { - true - })))).ok(); + catch_unwind(AssertUnwindSafe(|| { + drop(q.drain_filter(|item| if item.0 >= 2 { panic!() } else { true })) + })) + .ok(); - assert_eq!(unsafe { DROPS }, 2); // 0 and 1 + assert_eq!(unsafe { DROPS }, 2); // 0 and 1 assert_eq!(q.len(), 6); } diff --git a/src/liballoc/tests/vec.rs b/src/liballoc/tests/vec.rs index 2a027fd5d2b..9c4ac52acac 100644 --- a/src/liballoc/tests/vec.rs +++ b/src/liballoc/tests/vec.rs @@ -783,11 +783,7 @@ fn test_into_iter_leak() { } } - let v = vec![ - D(false), - D(true), - D(false), - ]; + let v = vec![D(false), D(true), D(false)]; catch_unwind(move || drop(v.into_iter())).ok(); diff --git a/src/liballoc/tests/vec_deque.rs b/src/liballoc/tests/vec_deque.rs index 07f1f098954..101dd67d97a 100644 --- a/src/liballoc/tests/vec_deque.rs +++ b/src/liballoc/tests/vec_deque.rs @@ -2,7 +2,7 @@ use std::collections::TryReserveError::*; use std::collections::{vec_deque::Drain, VecDeque}; use std::fmt::Debug; use std::mem::size_of; -use std::panic::{AssertUnwindSafe, catch_unwind}; +use std::panic::{catch_unwind, AssertUnwindSafe}; use std::{isize, usize}; use crate::hash; @@ -1637,7 +1637,8 @@ fn test_drain_leak() { catch_unwind(AssertUnwindSafe(|| { v.drain(1..=4); - })).ok(); + })) + .ok(); assert_eq!(unsafe { DROPS }, 4); assert_eq!(v.len(), 3); From 90afc0765e5e536af6307b63e1655a38df06e235 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 22 Jan 2020 19:23:37 -0500 Subject: [PATCH 0017/1250] Use a `ParamEnvAnd` for caching in `ObligationForest` Previously, we used a plain `Predicate` to cache results (e.g. successes and failures) in ObligationForest. However, fulfillment depends on the precise `ParamEnv` used, so this is unsound in general. This commit changes the impl of `ForestObligation` for `PendingPredicateObligation` to use `ParamEnvAnd` instead of `Predicate` for the associated type. The associated type and method are renamed from 'predicate' to 'cache_key' to reflect the fact that type is no longer just a predicate. --- src/librustc/traits/fulfill.rs | 9 ++++-- .../obligation_forest/graphviz.rs | 2 +- .../obligation_forest/mod.rs | 29 +++++++++++-------- .../obligation_forest/tests.rs | 4 +-- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 0aac6fb81e4..07352a3f947 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -18,10 +18,13 @@ use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { - type Predicate = ty::Predicate<'tcx>; + /// Note that we include both the `ParamEnv` and the `Predicate`, + /// as the `ParamEnv` can influence whether fulfillment succeeds + /// or fails. + type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>; - fn as_predicate(&self) -> &Self::Predicate { - &self.obligation.predicate + fn as_cache_key(&self) -> Self::CacheKey { + self.obligation.param_env.and(self.obligation.predicate) } } diff --git a/src/librustc_data_structures/obligation_forest/graphviz.rs b/src/librustc_data_structures/obligation_forest/graphviz.rs index ddf89d99621..96ee72d187b 100644 --- a/src/librustc_data_structures/obligation_forest/graphviz.rs +++ b/src/librustc_data_structures/obligation_forest/graphviz.rs @@ -51,7 +51,7 @@ impl<'a, O: ForestObligation + 'a> dot::Labeller<'a> for &'a ObligationForest fn node_label(&self, index: &Self::Node) -> dot::LabelText<'_> { let node = &self.nodes[*index]; - let label = format!("{:?} ({:?})", node.obligation.as_predicate(), node.state.get()); + let label = format!("{:?} ({:?})", node.obligation.as_cache_key(), node.state.get()); dot::LabelText::LabelStr(label.into()) } diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 974d9dcfae4..500ce5c71f3 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -86,9 +86,13 @@ mod graphviz; mod tests; pub trait ForestObligation: Clone + Debug { - type Predicate: Clone + hash::Hash + Eq + Debug; + type CacheKey: Clone + hash::Hash + Eq + Debug; - fn as_predicate(&self) -> &Self::Predicate; + /// Converts this `ForestObligation` suitable for use as a cache key. + /// If two distinct `ForestObligations`s return the same cache key, + /// then it must be sound to use the result of processing one obligation + /// (e.g. success for error) for the other obligation + fn as_cache_key(&self) -> Self::CacheKey; } pub trait ObligationProcessor { @@ -138,12 +142,12 @@ pub struct ObligationForest { nodes: Vec>, /// A cache of predicates that have been successfully completed. - done_cache: FxHashSet, + done_cache: FxHashSet, /// A cache of the nodes in `nodes`, indexed by predicate. Unfortunately, /// its contents are not guaranteed to match those of `nodes`. See the /// comments in `process_obligation` for details. - active_cache: FxHashMap, + active_cache: FxHashMap, /// A vector reused in compress(), to avoid allocating new vectors. node_rewrites: RefCell>, @@ -157,7 +161,7 @@ pub struct ObligationForest { /// See [this][details] for details. /// /// [details]: https://github.com/rust-lang/rust/pull/53255#issuecomment-421184780 - error_cache: FxHashMap>, + error_cache: FxHashMap>, } #[derive(Debug)] @@ -305,11 +309,12 @@ impl ObligationForest { // Returns Err(()) if we already know this obligation failed. fn register_obligation_at(&mut self, obligation: O, parent: Option) -> Result<(), ()> { - if self.done_cache.contains(obligation.as_predicate()) { + if self.done_cache.contains(&obligation.as_cache_key()) { + debug!("register_obligation_at: ignoring already done obligation: {:?}", obligation); return Ok(()); } - match self.active_cache.entry(obligation.as_predicate().clone()) { + match self.active_cache.entry(obligation.as_cache_key().clone()) { Entry::Occupied(o) => { let node = &mut self.nodes[*o.get()]; if let Some(parent_index) = parent { @@ -333,7 +338,7 @@ impl ObligationForest { && self .error_cache .get(&obligation_tree_id) - .map(|errors| errors.contains(obligation.as_predicate())) + .map(|errors| errors.contains(&obligation.as_cache_key())) .unwrap_or(false); if already_failed { @@ -380,7 +385,7 @@ impl ObligationForest { self.error_cache .entry(node.obligation_tree_id) .or_default() - .insert(node.obligation.as_predicate().clone()); + .insert(node.obligation.as_cache_key().clone()); } /// Performs a pass through the obligation list. This must @@ -618,11 +623,11 @@ impl ObligationForest { // `self.nodes`. See the comment in `process_obligation` // for more details. if let Some((predicate, _)) = - self.active_cache.remove_entry(node.obligation.as_predicate()) + self.active_cache.remove_entry(&node.obligation.as_cache_key()) { self.done_cache.insert(predicate); } else { - self.done_cache.insert(node.obligation.as_predicate().clone()); + self.done_cache.insert(node.obligation.as_cache_key().clone()); } if do_completed == DoCompleted::Yes { // Extract the success stories. @@ -635,7 +640,7 @@ impl ObligationForest { // We *intentionally* remove the node from the cache at this point. Otherwise // tests must come up with a different type on every type error they // check against. - self.active_cache.remove(node.obligation.as_predicate()); + self.active_cache.remove(&node.obligation.as_cache_key()); self.insert_into_error_cache(index); node_rewrites[index] = orig_nodes_len; dead_nodes += 1; diff --git a/src/librustc_data_structures/obligation_forest/tests.rs b/src/librustc_data_structures/obligation_forest/tests.rs index e29335aab28..01652465eea 100644 --- a/src/librustc_data_structures/obligation_forest/tests.rs +++ b/src/librustc_data_structures/obligation_forest/tests.rs @@ -4,9 +4,9 @@ use std::fmt; use std::marker::PhantomData; impl<'a> super::ForestObligation for &'a str { - type Predicate = &'a str; + type CacheKey = &'a str; - fn as_predicate(&self) -> &Self::Predicate { + fn as_cache_key(&self) -> Self::CacheKey { self } } From ac19dffd1eaea34c3861324c2588f9cb1f1489f5 Mon Sep 17 00:00:00 2001 From: Steven Degutis Date: Thu, 23 Jan 2020 15:25:10 -0600 Subject: [PATCH 0018/1250] Updating str.chars docs to mention crates.io. This might spare someone else a little time searching the stdlib for unicode/grapheme support. --- src/libcore/str/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 5a7cddd4041..89d5ba577c6 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2658,7 +2658,8 @@ impl str { /// /// It's important to remember that [`char`] represents a Unicode Scalar /// Value, and may not match your idea of what a 'character' is. Iteration - /// over grapheme clusters may be what you actually want. + /// over grapheme clusters may be what you actually want. This functionality + /// is not provided by Rust's standard library, check crates.io instead. /// /// # Examples /// From 84f3356e0dffc36f57d9be7902822db5d362e24f Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Tue, 28 Jan 2020 12:39:18 +0000 Subject: [PATCH 0019/1250] Simplify `Skip::nth` and `Skip::last` implementations The main improvement is to make `last` no longer recursive. --- src/libcore/iter/adapters/mod.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 5787b9174ed..df824dd493e 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1801,17 +1801,15 @@ where #[inline] fn nth(&mut self, n: usize) -> Option { // Can't just add n + self.n due to overflow. - if self.n == 0 { - self.iter.nth(n) - } else { + if self.n > 0 { let to_skip = self.n; self.n = 0; // nth(n) skips n+1 if self.iter.nth(to_skip - 1).is_none() { return None; } - self.iter.nth(n) } + self.iter.nth(n) } #[inline] @@ -1827,17 +1825,13 @@ where #[inline] fn last(mut self) -> Option { - if self.n == 0 { - self.iter.last() - } else { - let next = self.next(); - if next.is_some() { - // recurse. n should be 0. - self.last().or(next) - } else { - None + if self.n > 0 { + // nth(n) skips n+1 + if self.iter.nth(self.n - 1).is_none() { + return None; } } + self.iter.last() } #[inline] From b60f08bd6d3fbe784eb47a57e0c41954454af3dd Mon Sep 17 00:00:00 2001 From: Tom Jakubowski Date: Mon, 23 Sep 2019 18:39:55 -0700 Subject: [PATCH 0020/1250] rustdoc: NodeId is now DefId --- src/librustdoc/html/render/cache.rs | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index f1f83acdda5..3acfb82fe78 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -43,7 +43,7 @@ crate struct Cache { /// found on that implementation. pub impls: FxHashMap>, - /// Maintains a mapping of local crate `NodeId`s to the fully qualified name + /// Maintains a mapping of local crate `DefId`s to the fully qualified name /// and "short type description" of that node. This is used when generating /// URLs when a type is being linked to. External paths are not located in /// this map because the `External` type itself has all the information @@ -358,6 +358,7 @@ impl DocFolder for Cache { | clean::ForeignTypeItem | clean::MacroItem(..) | clean::ProcMacroItem(..) + | clean::VariantItem(..) if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice @@ -373,13 +374,6 @@ impl DocFolder for Cache { } self.add_aliases(&item); } - // Link variants to their parent enum because pages aren't emitted - // for each variant. - clean::VariantItem(..) if !self.stripped_mod => { - let mut stack = self.stack.clone(); - stack.pop(); - self.paths.insert(item.def_id, (stack, ItemType::Enum)); - } clean::PrimitiveItem(..) => { self.add_aliases(&item); @@ -396,7 +390,8 @@ impl DocFolder for Cache { | clean::EnumItem(..) | clean::ForeignTypeItem | clean::StructItem(..) - | clean::UnionItem(..) => { + | clean::UnionItem(..) + | clean::VariantItem(..) => { self.parent_stack.push(item.def_id); self.parent_is_trait_impl = false; true @@ -564,7 +559,7 @@ fn extern_location( /// Builds the search index from the collected metadata fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { - let mut nodeid_to_pathid = FxHashMap::default(); + let mut defid_to_pathid = FxHashMap::default(); let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_paths = vec![]; @@ -586,21 +581,21 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { } } - // Reduce `NodeId` in paths into smaller sequential numbers, + // Reduce `DefId` in paths into smaller sequential numbers, // and prune the paths that do not appear in the index. let mut lastpath = String::new(); let mut lastpathid = 0usize; for item in search_index { - item.parent_idx = item.parent.map(|nodeid| { - if nodeid_to_pathid.contains_key(&nodeid) { - *nodeid_to_pathid.get(&nodeid).expect("no pathid") + item.parent_idx = item.parent.map(|defid| { + if defid_to_pathid.contains_key(&defid) { + *defid_to_pathid.get(&defid).expect("no pathid") } else { let pathid = lastpathid; - nodeid_to_pathid.insert(nodeid, pathid); + defid_to_pathid.insert(defid, pathid); lastpathid += 1; - let &(ref fqp, short) = paths.get(&nodeid).unwrap(); + let &(ref fqp, short) = paths.get(&defid).unwrap(); crate_paths.push((short, fqp.last().unwrap().clone())); pathid } From 05c6f329e785c9b53a50217de0f21df906ae7ba0 Mon Sep 17 00:00:00 2001 From: Tom Jakubowski Date: Mon, 23 Sep 2019 18:37:20 -0700 Subject: [PATCH 0021/1250] rustdoc: emit JS paths for struct-like variants On the backend, rustdoc now emits `paths` entries to a crate's search index for struct-like enum variants, and index items of type structfield which belong to such variants point to their variant parents in the `paths` table, rather than their enum grandparents. The path entry for a variant is the fully qualified module path plus the enum name. On the frontend, the search code recognizes structfields belonging to structlike variants in the `paths` table and re-constructs the URL to the field's anchor on the enum documentation page. closes #16017 --- src/librustdoc/html/static/main.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index ec881d25dd2..069139ec691 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1364,14 +1364,15 @@ function getSearchElement() { var href; var type = itemTypes[item.ty]; var name = item.name; + var path = item.path; if (type === "mod") { - displayPath = item.path + "::"; - href = rootPath + item.path.replace(/::/g, "/") + "/" + + displayPath = path + "::"; + href = rootPath + path.replace(/::/g, "/") + "/" + name + "/index.html"; } else if (type === "primitive" || type === "keyword") { displayPath = ""; - href = rootPath + item.path.replace(/::/g, "/") + + href = rootPath + path.replace(/::/g, "/") + "/" + type + "." + name + ".html"; } else if (type === "externcrate") { displayPath = ""; @@ -1380,14 +1381,27 @@ function getSearchElement() { var myparent = item.parent; var anchor = "#" + type + "." + name; var parentType = itemTypes[myparent.ty]; + var pageType = parentType; + var pageName = myparent.name; + if (parentType === "primitive") { displayPath = myparent.name + "::"; + } else if (type === "structfield" && parentType === "variant") { + // Structfields belonging to variants are special: the + // final path element is the enum name. + var splitPath = item.path.split("::"); + var enumName = splitPath.pop(); + path = splitPath.join("::"); + displayPath = path + "::" + enumName + "::" + myparent.name + "::"; + anchor = "#variant." + myparent.name + ".field." + name; + pageType = "enum"; + pageName = enumName; } else { - displayPath = item.path + "::" + myparent.name + "::"; + displayPath = path + "::" + myparent.name + "::"; } - href = rootPath + item.path.replace(/::/g, "/") + - "/" + parentType + - "." + myparent.name + + href = rootPath + path.replace(/::/g, "/") + + "/" + pageType + + "." + pageName + ".html" + anchor; } else { displayPath = item.path + "::"; @@ -1668,7 +1682,7 @@ function getSearchElement() { // (String) name] var paths = rawSearchIndex[crate].p; - // convert `paths` into an object form + // convert `rawPaths` entries into object form var len = paths.length; for (i = 0; i < len; ++i) { paths[i] = {ty: paths[i][0], name: paths[i][1]}; From 14999dd74b38ca79b80772f4f33425574faff89a Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Wed, 29 Jan 2020 21:26:16 +0100 Subject: [PATCH 0022/1250] Add methods to leak RefCell borrows to references Usually, references to the interior are only created by the `Deref` and `DerefMut` impl of the guards `Ref` and `RefMut`. Note that `RefCell` already has to cope with leaks of such guards which, when it occurs, effectively makes it impossible to ever acquire a mutable guard or any guard for `Ref` and `RefMut` respectively. It is already safe to use this to create a reference to the inner of the ref cell that lives as long as the reference to the `RefCell` itself, e.g. ```rust fn leak(r: &RefCell) -> Option<&usize> { let guard = r.try_borrow().ok()?; let leaked = Box::leak(Box::new(guard)); Some(&*leaked) } ``` The newly added methods allow the same reference conversion without an indirection over a leaked allocation and composing with both borrow and try_borrow without additional method combinations. --- src/libcore/cell.rs | 63 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index e7eecf7540a..b1d799953e7 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1245,6 +1245,38 @@ impl<'b, T: ?Sized> Ref<'b, T> { let borrow = orig.borrow.clone(); (Ref { value: a, borrow }, Ref { value: b, borrow: orig.borrow }) } + + /// Convert into a reference to the underlying data. + /// + /// The underlying `RefCell` can never be mutably borrowed from again and will always appear + /// already immutably borrowed. It can still be immutably borrowed until more than `isize::MAX` + /// `Ref`s of this `RefCell` have been leaked, through this function or another leak, in total. + /// + /// This is an associated function that needs to be used as + /// `Ref::leak(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::{RefCell, Ref}; + /// let cell = RefCell::new(0); + /// + /// let value = Ref::leak(cell.borrow()); + /// assert_eq!(*value, 0); + /// + /// assert!(cell.try_borrow().is_ok()); + /// assert!(cell.try_borrow_mut().is_err()); + /// ``` + #[unstable(feature = "cell_leak", issue = "none")] + pub fn leak(orig: Ref<'b, T>) -> &'b T { + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never + // goes back to UNUSED again. No further references can be created from the original cell, + // making the current borrow the only reference for the remaining lifetime. + mem::forget(orig.borrow); + orig.value + } } #[unstable(feature = "coerce_unsized", issue = "27732")] @@ -1330,6 +1362,37 @@ impl<'b, T: ?Sized> RefMut<'b, T> { let borrow = orig.borrow.clone(); (RefMut { value: a, borrow }, RefMut { value: b, borrow: orig.borrow }) } + + /// Convert into a mutable reference to the underlying data. + /// + /// The underlying `RefCell` can not be borrowed from again and will always appear already + /// mutably borrowed, making the returned reference the only to the interior. + /// + /// This is an associated function that needs to be used as + /// `RefMut::leak(...)`. A method would interfere with methods of the + /// same name on the contents of a `RefCell` used through `Deref`. + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::{RefCell, RefMut}; + /// let cell = RefCell::new(0); + /// + /// let value = RefMut::leak(cell.borrow_mut()); + /// assert_eq!(*value, 0); + /// *value = 1; + /// + /// assert!(cell.try_borrow_mut().is_err()); + /// ``` + #[unstable(feature = "cell_leak", issue = "none")] + pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never + // goes back to UNUSED again. No further references can be created from the original cell, + // making the current borrow the only reference for the remaining lifetime. + mem::forget(orig.borrow); + orig.value + } } struct BorrowRefMut<'b> { From 8ee30dbc1b07ad7fc842ceee6d6729a1377f7a36 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Jan 2020 13:43:54 +0100 Subject: [PATCH 0023/1250] Add tests for struct variant field in search --- src/test/rustdoc-js/struct-like-variant.js | 7 +++++++ src/test/rustdoc-js/struct-like-variant.rs | 8 ++++++++ 2 files changed, 15 insertions(+) create mode 100644 src/test/rustdoc-js/struct-like-variant.js create mode 100644 src/test/rustdoc-js/struct-like-variant.rs diff --git a/src/test/rustdoc-js/struct-like-variant.js b/src/test/rustdoc-js/struct-like-variant.js new file mode 100644 index 00000000000..f6deea51e7d --- /dev/null +++ b/src/test/rustdoc-js/struct-like-variant.js @@ -0,0 +1,7 @@ +const QUERY = 'name'; + +const EXPECTED = { + 'others': [ + { 'path': 'struct_like_variant::Enum::Bar', 'name': 'name', 'desc': 'This is a name.' }, + ], +}; diff --git a/src/test/rustdoc-js/struct-like-variant.rs b/src/test/rustdoc-js/struct-like-variant.rs new file mode 100644 index 00000000000..2f52a319ab9 --- /dev/null +++ b/src/test/rustdoc-js/struct-like-variant.rs @@ -0,0 +1,8 @@ +#![crate_name = "struct_like_variant"] + +pub enum Enum { + Bar { + /// This is a name. + name: String + } +} From 60274a95fef57a18113f7c48be68be31ece860eb Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Sun, 1 Sep 2019 17:23:20 +0200 Subject: [PATCH 0024/1250] Added From> for CString Updated tracking issue number Added safeguards for transmute_vec potentially being factored out elsewhere Clarified comment about avoiding mem::forget Removed unneeded unstable guard Added back a stability annotation for CI Minor documentation improvements Thanks to @Centril's code review Co-Authored-By: Mazdak Farrokhzad Improved layout checks, type annotations and removed unaccurate comment Removed unnecessary check on array layout Adapt the stability annotation to the new 1.41 milestone Co-Authored-By: Mazdak Farrokhzad Simplify the implementation. Use `Vec::into_raw_parts` instead of a manual implementation of `Vec::transmute`. If `Vec::into_raw_parts` uses `NonNull` instead, then the code here will need to be adjusted to take it into account (issue #65816) Reduce the whitespace of safety comments --- src/libstd/ffi/c_str.rs | 27 +++++++++++++++++++++++++++ src/libstd/lib.rs | 1 + 2 files changed, 28 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index d2ee65f0a74..217672ea292 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -6,6 +6,7 @@ use crate::fmt::{self, Write}; use crate::io; use crate::mem; use crate::memchr; +use crate::num::NonZeroU8; use crate::ops; use crate::os::raw::c_char; use crate::ptr; @@ -741,6 +742,32 @@ impl From> for CString { } } +#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")] +impl From> for CString { + /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without + /// copying nor checking for inner null bytes. + /// + /// [`CString`]: ../ffi/struct.CString.html + /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html + /// [`Vec`]: ../vec/struct.Vec.html + #[inline] + fn from(v: Vec) -> CString { + unsafe { + // Transmute `Vec` to `Vec`. + let v: Vec = { + // Safety: + // - transmuting between `NonZeroU8` and `u8` is sound; + // - `alloc::Layout == alloc::Layout`. + let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v); + Vec::from_raw_parts(ptr.cast::(), len, cap) + }; + // Safety: `v` cannot contain null bytes, given the type-level + // invariant of `NonZeroU8`. + CString::from_vec_unchecked(v) + } + } +} + #[stable(feature = "more_box_slice_clone", since = "1.29.0")] impl Clone for Box { #[inline] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 9e9df5ab9b6..c05ebc7349d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -310,6 +310,7 @@ #![feature(unboxed_closures)] #![feature(untagged_unions)] #![feature(unwind_attributes)] +#![feature(vec_into_raw_parts)] // NB: the above list is sorted to minimize merge conflicts. #![default_lib_allocator] From 6509db844315882db7ec0b624ca1e7b04d72568d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 5 Feb 2020 05:03:37 +0100 Subject: [PATCH 0025/1250] or_patterns: harden bindings test --- .../ui/or-patterns/or-pattern-mismatch.rs | 70 ++++++- .../ui/or-patterns/or-pattern-mismatch.stderr | 182 +++++++++++++++++- 2 files changed, 245 insertions(+), 7 deletions(-) diff --git a/src/test/ui/or-patterns/or-pattern-mismatch.rs b/src/test/ui/or-patterns/or-pattern-mismatch.rs index 973954bca5a..5ec7dc6962c 100644 --- a/src/test/ui/or-patterns/or-pattern-mismatch.rs +++ b/src/test/ui/or-patterns/or-pattern-mismatch.rs @@ -1,4 +1,68 @@ -enum Blah { A(isize, isize, usize), B(isize, isize) } +// Here we test type checking of bindings when combined with or-patterns. +// Specifically, we ensure that introducing bindings of different types result in type errors. -fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } } -//~^ ERROR mismatched types +#![feature(or_patterns)] + +fn main() { + enum Blah { + A(isize, isize, usize), + B(isize, isize), + } + + match Blah::A(1, 1, 2) { + Blah::A(_, x, y) | Blah::B(x, y) => {} //~ ERROR mismatched types + } + + match Some(Blah::A(1, 1, 2)) { + Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} //~ ERROR mismatched types + } + + match (0u8, 1u16) { + (x, y) | (y, x) => {} //~ ERROR mismatched types + //~^ ERROR mismatched types + } + + match Some((0u8, Some((1u16, 2u32)))) { + Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + _ => {} + } + + if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { + //~^ ERROR mismatched types + } + + if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { + //~^ ERROR mismatched types + } + + if let (x, y) | (y, x) = (0u8, 1u16) { + //~^ ERROR mismatched types + //~| ERROR mismatched types + } + + if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + //~^ ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + //~| ERROR mismatched types + = Some((0u8, Some((1u16, 2u32)))) + {} + + let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); + //~^ ERROR mismatched types + + let (x, y) | (y, x) = (0u8, 1u16); + //~^ ERROR mismatched types + //~| ERROR mismatched types + + fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} + //~^ ERROR mismatched types + + fn f2(((x, y) | (y, x)): (u8, u16)) {} + //~^ ERROR mismatched types + //~| ERROR mismatched types +} diff --git a/src/test/ui/or-patterns/or-pattern-mismatch.stderr b/src/test/ui/or-patterns/or-pattern-mismatch.stderr index bc288e06250..84c38e3be90 100644 --- a/src/test/ui/or-patterns/or-pattern-mismatch.stderr +++ b/src/test/ui/or-patterns/or-pattern-mismatch.stderr @@ -1,9 +1,183 @@ error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:3:68 + --> $DIR/or-pattern-mismatch.rs:13:39 | -LL | fn main() { match Blah::A(1, 1, 2) { Blah::A(_, x, y) | Blah::B(x, y) => { } } } - | ---------------- this expression has type `Blah` ^ expected `usize`, found `isize` +LL | match Blah::A(1, 1, 2) { + | ---------------- this expression has type `main::Blah` +LL | Blah::A(_, x, y) | Blah::B(x, y) => {} + | ^ expected `usize`, found `isize` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:17:44 + | +LL | match Some(Blah::A(1, 1, 2)) { + | ---------------------- this expression has type `std::option::Option` +LL | Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} + | ^ expected `usize`, found `isize` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:21:19 + | +LL | match (0u8, 1u16) { + | ----------- this expression has type `(u8, u16)` +LL | (x, y) | (y, x) => {} + | ^ expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:21:22 + | +LL | match (0u8, 1u16) { + | ----------- this expression has type `(u8, u16)` +LL | (x, y) | (y, x) => {} + | ^ expected `u8`, found `u16` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:26:41 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | ^ expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:26:50 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | ^ expected `u8`, found `u16` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:26:59 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | ^ expected `u32`, found `u16` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:26:62 + | +LL | match Some((0u8, Some((1u16, 2u32)))) { + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` +LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} + | ^ expected `u8`, found `u32` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:34:42 + | +LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { + | ^ ---------------- this expression has type `main::Blah` + | | + | expected `usize`, found `isize` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:38:47 + | +LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { + | ^ ---------------------- this expression has type `std::option::Option` + | | + | expected `usize`, found `isize` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:42:22 + | +LL | if let (x, y) | (y, x) = (0u8, 1u16) { + | ^ ----------- this expression has type `(u8, u16)` + | | + | expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:42:25 + | +LL | if let (x, y) | (y, x) = (0u8, 1u16) { + | ^ ----------- this expression has type `(u8, u16)` + | | + | expected `u8`, found `u16` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:47:44 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | ^ expected `u16`, found `u8` +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:47:53 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | ^ expected `u8`, found `u16` +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:47:62 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | ^ expected `u32`, found `u16` +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:47:65 + | +LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) + | ^ expected `u8`, found `u32` +... +LL | = Some((0u8, Some((1u16, 2u32)))) + | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:55:39 + | +LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); + | ^ ---------------- this expression has type `main::Blah` + | | + | expected `usize`, found `isize` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:58:19 + | +LL | let (x, y) | (y, x) = (0u8, 1u16); + | ^ ----------- this expression has type `(u8, u16)` + | | + | expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:58:22 + | +LL | let (x, y) | (y, x) = (0u8, 1u16); + | ^ ----------- this expression has type `(u8, u16)` + | | + | expected `u8`, found `u16` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:62:42 + | +LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} + | ^ ---- expected due to this + | | + | expected `usize`, found `isize` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:65:22 + | +LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} + | ^ --------- expected due to this + | | + | expected `u16`, found `u8` + +error[E0308]: mismatched types + --> $DIR/or-pattern-mismatch.rs:65:25 + | +LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} + | ^ --------- expected due to this + | | + | expected `u8`, found `u16` + +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0308`. From 29437e55a56c1c1251ae5f7276f3e95dac4b609a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 5 Feb 2020 05:05:29 +0100 Subject: [PATCH 0026/1250] or_patterns: rename previous test --- ...s => or-patterns-binding-type-mismatch.rs} | 0 ... or-patterns-binding-type-mismatch.stderr} | 44 +++++++++---------- 2 files changed, 22 insertions(+), 22 deletions(-) rename src/test/ui/or-patterns/{or-pattern-mismatch.rs => or-patterns-binding-type-mismatch.rs} (100%) rename src/test/ui/or-patterns/{or-pattern-mismatch.stderr => or-patterns-binding-type-mismatch.stderr} (85%) diff --git a/src/test/ui/or-patterns/or-pattern-mismatch.rs b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs similarity index 100% rename from src/test/ui/or-patterns/or-pattern-mismatch.rs rename to src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs diff --git a/src/test/ui/or-patterns/or-pattern-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr similarity index 85% rename from src/test/ui/or-patterns/or-pattern-mismatch.stderr rename to src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index 84c38e3be90..5094f04b920 100644 --- a/src/test/ui/or-patterns/or-pattern-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:13:39 + --> $DIR/or-patterns-binding-type-mismatch.rs:13:39 | LL | match Blah::A(1, 1, 2) { | ---------------- this expression has type `main::Blah` @@ -7,7 +7,7 @@ LL | Blah::A(_, x, y) | Blah::B(x, y) => {} | ^ expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:17:44 + --> $DIR/or-patterns-binding-type-mismatch.rs:17:44 | LL | match Some(Blah::A(1, 1, 2)) { | ---------------------- this expression has type `std::option::Option` @@ -15,7 +15,7 @@ LL | Some(Blah::A(_, x, y) | Blah::B(x, y)) => {} | ^ expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:21:19 + --> $DIR/or-patterns-binding-type-mismatch.rs:21:19 | LL | match (0u8, 1u16) { | ----------- this expression has type `(u8, u16)` @@ -23,7 +23,7 @@ LL | (x, y) | (y, x) => {} | ^ expected `u16`, found `u8` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:21:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:21:22 | LL | match (0u8, 1u16) { | ----------- this expression has type `(u8, u16)` @@ -31,7 +31,7 @@ LL | (x, y) | (y, x) => {} | ^ expected `u8`, found `u16` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:26:41 + --> $DIR/or-patterns-binding-type-mismatch.rs:26:41 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` @@ -39,7 +39,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} | ^ expected `u16`, found `u8` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:26:50 + --> $DIR/or-patterns-binding-type-mismatch.rs:26:50 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` @@ -47,7 +47,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} | ^ expected `u8`, found `u16` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:26:59 + --> $DIR/or-patterns-binding-type-mismatch.rs:26:59 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` @@ -55,7 +55,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} | ^ expected `u32`, found `u16` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:26:62 + --> $DIR/or-patterns-binding-type-mismatch.rs:26:62 | LL | match Some((0u8, Some((1u16, 2u32)))) { | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` @@ -63,7 +63,7 @@ LL | Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) => {} | ^ expected `u8`, found `u32` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:34:42 + --> $DIR/or-patterns-binding-type-mismatch.rs:34:42 | LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { | ^ ---------------- this expression has type `main::Blah` @@ -71,7 +71,7 @@ LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { | expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:38:47 + --> $DIR/or-patterns-binding-type-mismatch.rs:38:47 | LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) { | ^ ---------------------- this expression has type `std::option::Option` @@ -79,7 +79,7 @@ LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) | expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:42:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:42:22 | LL | if let (x, y) | (y, x) = (0u8, 1u16) { | ^ ----------- this expression has type `(u8, u16)` @@ -87,7 +87,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | expected `u16`, found `u8` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:42:25 + --> $DIR/or-patterns-binding-type-mismatch.rs:42:25 | LL | if let (x, y) | (y, x) = (0u8, 1u16) { | ^ ----------- this expression has type `(u8, u16)` @@ -95,7 +95,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | expected `u8`, found `u16` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:47:44 + --> $DIR/or-patterns-binding-type-mismatch.rs:47:44 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | ^ expected `u16`, found `u8` @@ -104,7 +104,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:47:53 + --> $DIR/or-patterns-binding-type-mismatch.rs:47:53 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | ^ expected `u8`, found `u16` @@ -113,7 +113,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:47:62 + --> $DIR/or-patterns-binding-type-mismatch.rs:47:62 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | ^ expected `u32`, found `u16` @@ -122,7 +122,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:47:65 + --> $DIR/or-patterns-binding-type-mismatch.rs:47:65 | LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) | ^ expected `u8`, found `u32` @@ -131,7 +131,7 @@ LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:55:39 + --> $DIR/or-patterns-binding-type-mismatch.rs:55:39 | LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); | ^ ---------------- this expression has type `main::Blah` @@ -139,7 +139,7 @@ LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); | expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:58:19 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:19 | LL | let (x, y) | (y, x) = (0u8, 1u16); | ^ ----------- this expression has type `(u8, u16)` @@ -147,7 +147,7 @@ LL | let (x, y) | (y, x) = (0u8, 1u16); | expected `u16`, found `u8` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:58:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:22 | LL | let (x, y) | (y, x) = (0u8, 1u16); | ^ ----------- this expression has type `(u8, u16)` @@ -155,7 +155,7 @@ LL | let (x, y) | (y, x) = (0u8, 1u16); | expected `u8`, found `u16` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:62:42 + --> $DIR/or-patterns-binding-type-mismatch.rs:62:42 | LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} | ^ ---- expected due to this @@ -163,7 +163,7 @@ LL | fn f1((Blah::A(_, x, y) | Blah::B(x, y)): Blah) {} | expected `usize`, found `isize` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:65:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:65:22 | LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} | ^ --------- expected due to this @@ -171,7 +171,7 @@ LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} | expected `u16`, found `u8` error[E0308]: mismatched types - --> $DIR/or-pattern-mismatch.rs:65:25 + --> $DIR/or-patterns-binding-type-mismatch.rs:65:25 | LL | fn f2(((x, y) | (y, x)): (u8, u16)) {} | ^ --------- expected due to this From 17e632d382dfae46e9dfa684db9bddec3e8951a7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 5 Feb 2020 10:32:54 +0100 Subject: [PATCH 0027/1250] or_patterns: test default binding modes --- .../or-patterns-default-binding-modes.rs | 132 ++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/test/ui/or-patterns/or-patterns-default-binding-modes.rs diff --git a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs new file mode 100644 index 00000000000..3b6047c7be4 --- /dev/null +++ b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs @@ -0,0 +1,132 @@ +// Test that or-patterns are pass-through with respect to default binding modes. + +// check-pass + +#![feature(or_patterns)] +#![allow(irrefutable_let_patterns)] + +fn main() { + // A regression test for a mistake we made at one point: + match &1 { + e @ &(1..=2) | e @ &(3..=4) => {} + _ => {} + } + + match &0 { + 0 | &1 => {} + _ => {} + } + + type R<'a> = &'a Result; + + let res: R<'_> = &Ok(0); + + match res { + // Alternatives propagate expected type / binding mode independently. + Ok(mut x) | &Err(mut x) => drop::(x), + } + match res { + &(Ok(x) | Err(x)) => drop::(x), + } + match res { + Ok(x) | Err(x) => drop::<&u8>(x), + } + if let Ok(mut x) | &Err(mut x) = res { + drop::(x); + } + if let &(Ok(x) | Err(x)) = res { + drop::(x); + } + let Ok(mut x) | &Err(mut x) = res; + drop::(x); + let &(Ok(x) | Err(x)) = res; + drop::(x); + let Ok(x) | Err(x) = res; + drop::<&u8>(x); + for Ok(mut x) | &Err(mut x) in std::iter::once(res) { + drop::(x); + } + for &(Ok(x) | Err(x)) in std::iter::once(res) { + drop::(x); + } + for Ok(x) | Err(x) in std::iter::once(res) { + drop::<&u8>(x); + } + fn f1((Ok(mut x) | &Err(mut x)): R<'_>) { + drop::(x); + } + fn f2(&(Ok(x) | Err(x)): R<'_>) { + drop::(x); + } + fn f3((Ok(x) | Err(x)): R<'_>) { + drop::<&u8>(x); + } + + // Wrap inside another type (a product for a simplity with irrefutable contexts). + #[derive(Copy, Clone)] + struct Wrap(T); + let wres = Wrap(res); + + match wres { + Wrap(Ok(mut x) | &Err(mut x)) => drop::(x), + } + match wres { + Wrap(&(Ok(x) | Err(x))) => drop::(x), + } + match wres { + Wrap(Ok(x) | Err(x)) => drop::<&u8>(x), + } + if let Wrap(Ok(mut x) | &Err(mut x)) = wres { + drop::(x); + } + if let Wrap(&(Ok(x) | Err(x))) = wres { + drop::(x); + } + if let Wrap(Ok(x) | Err(x)) = wres { + drop::<&u8>(x); + } + let Wrap(Ok(mut x) | &Err(mut x)) = wres; + drop::(x); + let Wrap(&(Ok(x) | Err(x))) = wres; + drop::(x); + let Wrap(Ok(x) | Err(x)) = wres; + drop::<&u8>(x); + for Wrap(Ok(mut x) | &Err(mut x)) in std::iter::once(wres) { + drop::(x); + } + for Wrap(&(Ok(x) | Err(x))) in std::iter::once(wres) { + drop::(x); + } + for Wrap(Ok(x) | Err(x)) in std::iter::once(wres) { + drop::<&u8>(x); + } + fn fw1(Wrap(Ok(mut x) | &Err(mut x)): Wrap>) { + drop::(x); + } + fn fw2(Wrap(&(Ok(x) | Err(x))): Wrap>) { + drop::(x); + } + fn fw3(Wrap(Ok(x) | Err(x)): Wrap>) { + drop::<&u8>(x); + } + + // Nest some more: + + enum Tri

{ + A(P), + B(P), + C(P), + } + + let tri = &Tri::A(&Ok(0)); + let Tri::A(Ok(mut x) | Err(mut x)) + | Tri::B(&Ok(mut x) | Err(mut x)) + | &Tri::C(Ok(mut x) | Err(mut x)) = tri; + drop::(x); + + match tri { + Tri::A(Ok(mut x) | Err(mut x)) + | Tri::B(&Ok(mut x) | Err(mut x)) + | &Tri::C(Ok(mut x) | Err(mut x)) => drop::(x), + } +} From b5aca3128d5c0ee2441ec9ca9a9c3ae4f391ef16 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 5 Feb 2020 04:45:13 +0100 Subject: [PATCH 0028/1250] typeck: refactor default binding mode logic & improve docs --- src/librustc_typeck/check/pat.rs | 113 +++++++++++++++++-------------- 1 file changed, 64 insertions(+), 49 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index f9dee0e477f..81e10e7a540 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -89,6 +89,18 @@ impl<'tcx> FnCtxt<'_, 'tcx> { } } +const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not); + +/// Mode for adjusting the expected type and binding mode. +enum AdjustMode { + /// Peel off all immediate reference types. + Peel, + /// Reset binding mode to the inital mode. + Reset, + /// Pass on the input binding mode and expected type. + Pass, +} + impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Type check the given top level pattern against the `expected` type. /// @@ -105,8 +117,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Option, origin_expr: bool, ) { - let def_bm = BindingMode::BindByValue(hir::Mutability::Not); - self.check_pat(pat, expected, def_bm, TopInfo { expected, origin_expr, span }); + self.check_pat(pat, expected, INITIAL_BM, TopInfo { expected, origin_expr, span }); } /// Type check the given `pat` against the `expected` type @@ -123,12 +134,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) { debug!("check_pat(pat={:?},expected={:?},def_bm={:?})", pat, expected, def_bm); - let path_resolution = match &pat.kind { + let path_res = match &pat.kind { PatKind::Path(qpath) => Some(self.resolve_ty_and_res_ufcs(qpath, pat.hir_id, pat.span)), _ => None, }; - let is_nrp = self.is_non_ref_pat(pat, path_resolution.map(|(res, ..)| res)); - let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, is_nrp); + let adjust_mode = self.calc_adjust_mode(pat, path_res.map(|(res, ..)| res)); + let (expected, def_bm) = self.calc_default_binding_mode(pat, expected, def_bm, adjust_mode); let ty = match pat.kind { PatKind::Wild => expected, @@ -141,7 +152,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, def_bm, ti) } PatKind::Path(ref qpath) => { - self.check_pat_path(pat, path_resolution.unwrap(), qpath, expected) + self.check_pat_path(pat, path_res.unwrap(), qpath, expected) } PatKind::Struct(ref qpath, fields, etc) => { self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti) @@ -223,64 +234,68 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, def_bm: BindingMode, - is_non_ref_pat: bool, + adjust_mode: AdjustMode, ) -> (Ty<'tcx>, BindingMode) { - if is_non_ref_pat { - debug!("pattern is non reference pattern"); - self.peel_off_references(pat, expected, def_bm) - } else { - // When you encounter a `&pat` pattern, reset to "by - // value". This is so that `x` and `y` here are by value, - // as they appear to be: - // - // ``` - // match &(&22, &44) { - // (&x, &y) => ... - // } - // ``` - // - // See issue #46688. - let def_bm = match pat.kind { - PatKind::Ref(..) => ty::BindByValue(hir::Mutability::Not), - _ => def_bm, - }; - (expected, def_bm) + match adjust_mode { + AdjustMode::Pass => (expected, def_bm), + AdjustMode::Reset => (expected, INITIAL_BM), + AdjustMode::Peel => self.peel_off_references(pat, expected, def_bm), } } - /// Is the pattern a "non reference pattern"? + /// How should the binding mode and expected type be adjusted? + /// /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`. - fn is_non_ref_pat(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> bool { - match pat.kind { + fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> AdjustMode { + match &pat.kind { + // Type checking these product-like types successfully always require + // that the expected type be of those types and not reference types. PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Tuple(..) | PatKind::Box(_) | PatKind::Range(..) - | PatKind::Slice(..) => true, - PatKind::Lit(ref lt) => { - let ty = self.check_expr(lt); - match ty.kind { - ty::Ref(..) => false, - _ => true, - } - } + | PatKind::Slice(..) => AdjustMode::Peel, + // String and byte-string literals result in types `&str` and `&[u8]` respectively. + // All other literals result in non-reference types. + // As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo {}`. + PatKind::Lit(lt) => match self.check_expr(lt).kind { + ty::Ref(..) => AdjustMode::Pass, + _ => AdjustMode::Peel, + }, PatKind::Path(_) => match opt_path_res.unwrap() { - Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => false, - _ => true, + // These constants can be of a reference type, e.g. `const X: &u8 = &0;`. + // Peeling the reference types too early will cause type checking failures. + // Although it would be possible to *also* peel the types of the constants too. + Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => AdjustMode::Pass, + // In the `ValueNS`, we have `SelfCtor(..) | Ctor(_, Const), _)` remaining which + // could successfully compile. The former being `Self` requires a unit struct. + // In either case, and unlike constants, the pattern itself cannot be + // a reference type wherefore peeling doesn't give up any expressivity. + _ => AdjustMode::Peel, }, - // FIXME(or_patterns; Centril | dlrobertson): To keep things compiling - // for or-patterns at the top level, we need to make `p_0 | ... | p_n` - // a "non reference pattern". For example the following currently compiles: + // When encountering a `& mut? pat` pattern, reset to "by value". + // This is so that `x` and `y` here are by value, as they appear to be: + // // ``` - // match &1 { - // e @ &(1...2) | e @ &(3...4) => {} - // _ => {} + // match &(&22, &44) { + // (&x, &y) => ... // } // ``` // - // We should consider whether we should do something special in nested or-patterns. - PatKind::Or(_) | PatKind::Wild | PatKind::Binding(..) | PatKind::Ref(..) => false, + // See issue #46688. + PatKind::Ref(..) => AdjustMode::Reset, + // A `_` pattern works with any expected type, so there's no need to do anything. + PatKind::Wild + // Bindings also work with whatever the expected type is, + // and moreover if we peel references off, that will give us the wrong binding type. + // Also, we can have a subpattern `binding @ pat`. + // Each side of the `@` should be treated independently (like with OR-patterns). + | PatKind::Binding(..) + // An OR-pattern just propagates to each individual alternative. + // This is maximally flexible, allowing e.g., `Some(mut x) | &Some(mut x)`. + // In that example, `Some(mut x)` results in `Peel` whereas `&Some(mut x)` in `Reset`. + | PatKind::Or(_) => AdjustMode::Pass, } } @@ -508,7 +523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let local_ty = self.local_ty(pat.span, pat.hir_id).decl_ty; let eq_ty = match bm { ty::BindByReference(mutbl) => { - // If the binding is like `ref x | ref const x | ref mut x` + // If the binding is like `ref x | ref mut x`, // then `x` is assigned a value of type `&M T` where M is the // mutability and T is the expected type. // From 178de46116b4fc8c1d9b30007f5e5ed24c809881 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 26 Dec 2019 12:55:13 -0500 Subject: [PATCH 0029/1250] Add primitive module to libcore/std This re-exports the primitive types from libcore at `core::primitive` to allow macro authors to have a reliable location to use them from. --- src/libcore/lib.rs | 3 + src/libcore/primitive.rs | 67 +++++++++++++++++++ src/libstd/lib.rs | 5 +- .../resolve/resolve-primitive-fallback.stderr | 5 ++ src/test/ui/shadow-bool.rs | 18 +++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/libcore/primitive.rs create mode 100644 src/test/ui/shadow-bool.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1fd70e1a1b0..257a6d371b7 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -262,6 +262,9 @@ mod bool; mod tuple; mod unit; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub mod primitive; + // Pull in the `core_arch` crate directly into libcore. The contents of // `core_arch` are in a different repository: rust-lang/stdarch. // diff --git a/src/libcore/primitive.rs b/src/libcore/primitive.rs new file mode 100644 index 00000000000..d37bbfaf5df --- /dev/null +++ b/src/libcore/primitive.rs @@ -0,0 +1,67 @@ +//! This module reexports the primitive types to allow usage that is not +//! possibly shadowed by other declared types. +//! +//! This is normally only useful in macro generated code. +//! +//! An example of this is when generating a new struct and an impl for it: +//! +//! ```rust,compile_fail +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } +//! ``` +//! +//! Note that the `SOME_PROPERTY` associated constant would not compile, as its +//! type `bool` refers to the struct, rather than to the primitive bool type. +//! +//! A correct implementation could look like: +//! +//! ```rust +//! # #[allow(non_camel_case_types)] +//! pub struct bool; +//! +//! impl QueryId for bool { +//! const SOME_PROPERTY: core::primitive::bool = true; +//! } +//! +//! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } +//! ``` + +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use bool; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use char; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use f32; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use f64; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use i128; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use i16; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use i32; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use i64; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use i8; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use isize; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use str; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use u128; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use u16; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use u32; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use u64; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use u8; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use usize; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f9c9f224730..2b54481ab56 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -233,12 +233,12 @@ #![feature(allocator_internals)] #![feature(allow_internal_unsafe)] #![feature(allow_internal_unstable)] -#![feature(atomic_mut_ptr)] #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] #![feature(assoc_int_consts)] #![feature(associated_type_bounds)] +#![feature(atomic_mut_ptr)] #![feature(box_syntax)] #![feature(c_variadic)] #![feature(cfg_target_has_atomic)] @@ -550,6 +550,9 @@ pub use core::{ trace_macros, }; +#[stable(feature = "core_primitive", since = "1.42.0")] +pub use core::primitive; + // Include a number of private modules that exist solely to provide // the rustdoc documentation for primitive types. Using `include!` // because rustdoc only looks for these modules at the crate level. diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr index 92c2a032983..72a854346fa 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.stderr +++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr @@ -9,6 +9,11 @@ error[E0412]: cannot find type `u8` in the crate root | LL | let _: ::u8; | ^^ not found in the crate root + | +help: possible candidate is found in another module, you can import it into scope + | +LL | use std::primitive::u8; + | error[E0061]: this function takes 0 parameters but 1 parameter was supplied --> $DIR/resolve-primitive-fallback.rs:3:5 diff --git a/src/test/ui/shadow-bool.rs b/src/test/ui/shadow-bool.rs new file mode 100644 index 00000000000..f290a329eaa --- /dev/null +++ b/src/test/ui/shadow-bool.rs @@ -0,0 +1,18 @@ +// check-pass + +mod bar { + pub trait QueryId { + const SOME_PROPERTY: bool; + } +} + +use bar::QueryId; + +#[allow(non_camel_case_types)] +pub struct bool; + +impl QueryId for bool { + const SOME_PROPERTY: core::primitive::bool = true; +} + +fn main() {} From 953f6ecb6adc37b4f8e52102c1e7ca86cc5bc92c Mon Sep 17 00:00:00 2001 From: Mikhail Babenko Date: Fri, 7 Feb 2020 23:38:13 +0300 Subject: [PATCH 0030/1250] fix lifetime shadowing check in GATs --- src/librustc_resolve/lifetimes.rs | 6 ++++-- .../ui/generic-associated-types/shadowing.rs | 4 ++-- .../generic-associated-types/shadowing.stderr | 21 +++++++++++++++++-- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index 0ba9b4f1706..c527d6050ca 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -747,7 +747,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, }; - self.with(scope, |_old_scope, this| { + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &generics.params); this.visit_generics(generics); for bound in bounds { this.visit_param_bound(bound); @@ -804,7 +805,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { track_lifetime_uses: true, opaque_type_parent: true, }; - self.with(scope, |_old_scope, this| { + self.with(scope, |old_scope, this| { + this.check_lifetime_params(old_scope, &generics.params); this.visit_generics(generics); this.visit_ty(ty); }); diff --git a/src/test/ui/generic-associated-types/shadowing.rs b/src/test/ui/generic-associated-types/shadowing.rs index 7277c0d87c6..5c308948bd3 100644 --- a/src/test/ui/generic-associated-types/shadowing.rs +++ b/src/test/ui/generic-associated-types/shadowing.rs @@ -2,8 +2,8 @@ #![feature(generic_associated_types)] trait Shadow<'a> { - //FIXME(#44265): The lifetime parameter shadowing should cause an error. type Bar<'a>; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope } trait NoShadow<'a> { @@ -11,8 +11,8 @@ trait NoShadow<'a> { } impl<'a> NoShadow<'a> for &'a u32 { - //FIXME(#44265): The lifetime parameter shadowing should cause an error. type Bar<'a> = i32; + //~^ ERROR lifetime name `'a` shadows a lifetime name that is already in scope } trait ShadowT { diff --git a/src/test/ui/generic-associated-types/shadowing.stderr b/src/test/ui/generic-associated-types/shadowing.stderr index 50c12e822e7..1cb6f071f3a 100644 --- a/src/test/ui/generic-associated-types/shadowing.stderr +++ b/src/test/ui/generic-associated-types/shadowing.stderr @@ -14,6 +14,22 @@ LL | impl NoShadowT for Option { LL | type Bar = i32; | ^ already used +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:5:14 + | +LL | trait Shadow<'a> { + | -- first declared here +LL | type Bar<'a>; + | ^^ lifetime 'a already in scope + +error[E0496]: lifetime name `'a` shadows a lifetime name that is already in scope + --> $DIR/shadowing.rs:14:14 + | +LL | impl<'a> NoShadow<'a> for &'a u32 { + | -- first declared here +LL | type Bar<'a> = i32; + | ^^ lifetime 'a already in scope + error: type-generic associated types are not yet implemented --> $DIR/shadowing.rs:19:5 | @@ -30,6 +46,7 @@ LL | type Bar; // OK | = note: for more information, see https://github.com/rust-lang/rust/issues/44265 -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0403`. +Some errors have detailed explanations: E0403, E0496. +For more information about an error, try `rustc --explain E0403`. From b23d910d570b392b1740ef1bb888f04194fe82c1 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 28 Jan 2020 23:20:27 -0800 Subject: [PATCH 0031/1250] Skip `Drop` terminators for enum variants without drop glue When doing drop elaboration for an `enum` that may or may not be moved out of (an open drop), we check the discriminant of the `enum` to see whether the live variant has any drop flags and then check the drop flags to see whether we need to drop each field. Sometimes, however, the live variant has no move paths. In this case, we still emit a drop terminator for the entire enum after checking the enum discriminant. This commit skips emitting the drop terminator when the "otherwise" variants, those without move paths, have no drop glue. This was frequently the case with `Option`, as the `None` variant has no drop glue and no move path. --- src/librustc_mir/util/elaborate_drops.rs | 45 ++++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 1be3da4b3d8..67679dd12e9 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -153,9 +153,9 @@ where // FIXME: I think we should just control the flags externally, // and then we do not need this machinery. pub fn elaborate_drop(&mut self, bb: BasicBlock) { - debug!("elaborate_drop({:?})", self); + debug!("elaborate_drop({:?}, {:?})", bb, self); let style = self.elaborator.drop_style(self.path, DropFlagMode::Deep); - debug!("elaborate_drop({:?}): live - {:?}", self, style); + debug!("elaborate_drop({:?}, {:?}): live - {:?}", bb, self, style); match style { DropStyle::Dead => { self.elaborator @@ -426,25 +426,21 @@ where let mut unwind_blocks = if unwind.is_cleanup() { None } else { Some(Vec::with_capacity(adt.variants.len())) }; + let mut have_otherwise_with_drop_glue = false; let mut have_otherwise = false; let tcx = self.tcx(); for (variant_index, discr) in adt.discriminants(tcx) { + let variant = &adt.variants[variant_index]; let subpath = self.elaborator.downcast_subpath(self.path, variant_index); + if let Some(variant_path) = subpath { let base_place = tcx.mk_place_elem( self.place.clone(), - ProjectionElem::Downcast( - Some(adt.variants[variant_index].ident.name), - variant_index, - ), - ); - let fields = self.move_paths_for_fields( - &base_place, - variant_path, - &adt.variants[variant_index], - substs, + ProjectionElem::Downcast(Some(variant.ident.name), variant_index), ); + let fields = + self.move_paths_for_fields(&base_place, variant_path, &variant, substs); values.push(discr.val); if let Unwind::To(unwind) = unwind { // We can't use the half-ladder from the original @@ -474,16 +470,30 @@ where normal_blocks.push(normal); } else { have_otherwise = true; + + let param_env = self.elaborator.param_env(); + let have_field_with_drop_glue = variant + .fields + .iter() + .any(|field| field.ty(tcx, substs).needs_drop(tcx, param_env)); + if have_field_with_drop_glue { + have_otherwise_with_drop_glue = true; + } } } - if have_otherwise { + if !have_otherwise { + values.pop(); + } else if !have_otherwise_with_drop_glue { + normal_blocks.push(self.goto_block(succ, unwind)); + if let Unwind::To(unwind) = unwind { + unwind_blocks.as_mut().unwrap().push(self.goto_block(unwind, Unwind::InCleanup)); + } + } else { normal_blocks.push(self.drop_block(succ, unwind)); if let Unwind::To(unwind) = unwind { unwind_blocks.as_mut().unwrap().push(self.drop_block(unwind, Unwind::InCleanup)); } - } else { - values.pop(); } ( @@ -929,6 +939,11 @@ where self.new_block(unwind, block) } + fn goto_block(&mut self, target: BasicBlock, unwind: Unwind) -> BasicBlock { + let block = TerminatorKind::Goto { target }; + self.new_block(unwind, block) + } + fn drop_flag_test_block( &mut self, on_set: BasicBlock, From 348278a7fd5fd459f555dd763e71e12c23c1661a Mon Sep 17 00:00:00 2001 From: Michael Bradshaw Date: Fri, 7 Feb 2020 21:53:22 -0800 Subject: [PATCH 0032/1250] Stabilize Once::is_completed --- src/libstd/sync/once.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index 61c4d0c2dbf..b99b4d8d9fd 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -331,14 +331,14 @@ impl Once { /// * `call_once` was called, but has not yet completed, /// * the `Once` instance is poisoned /// - /// It is also possible that immediately after `is_completed` - /// returns false, some other thread finishes executing - /// `call_once`. + /// This function returning `false` does not mean that `Once` has not been + /// executed. For example, it may have been executed in the time between + /// when `is_completed` starts executing and when it returns, in which case + /// the `false` return value would be stale (but still permissible). /// /// # Examples /// /// ``` - /// #![feature(once_is_completed)] /// use std::sync::Once; /// /// static INIT: Once = Once::new(); @@ -351,7 +351,6 @@ impl Once { /// ``` /// /// ``` - /// #![feature(once_is_completed)] /// use std::sync::Once; /// use std::thread; /// @@ -364,7 +363,7 @@ impl Once { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[unstable(feature = "once_is_completed", issue = "54890")] + #[stable(feature = "once_is_completed", since = "1.44.0")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization From b685985ea40ab1faa8cb888bf001779e44a8c716 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Mon, 3 Feb 2020 12:50:49 +0100 Subject: [PATCH 0033/1250] Refine and extend benchmarks of mutable BTreeSet methods --- src/liballoc/benches/btree/set.rs | 101 +++++++++++++++++++++++++----- 1 file changed, 85 insertions(+), 16 deletions(-) diff --git a/src/liballoc/benches/btree/set.rs b/src/liballoc/benches/btree/set.rs index d7c1d95a452..d9e75ab7fa4 100644 --- a/src/liballoc/benches/btree/set.rs +++ b/src/liballoc/benches/btree/set.rs @@ -50,43 +50,112 @@ macro_rules! set_bench { }; } -const BUILD_SET_SIZE: usize = 100; +#[bench] +pub fn clone_100(b: &mut Bencher) { + let src = pos(100); + b.iter(|| src.clone()) +} #[bench] -pub fn build_and_clear(b: &mut Bencher) { - b.iter(|| pos(BUILD_SET_SIZE).clear()) +pub fn clone_100_and_clear(b: &mut Bencher) { + let src = pos(100); + b.iter(|| src.clone().clear()) } #[bench] -pub fn build_and_drop(b: &mut Bencher) { - b.iter(|| pos(BUILD_SET_SIZE)) +pub fn clone_100_and_into_iter(b: &mut Bencher) { + let src = pos(100); + b.iter(|| src.clone().into_iter().count()) } #[bench] -pub fn build_and_into_iter(b: &mut Bencher) { - b.iter(|| pos(BUILD_SET_SIZE).into_iter().count()) +pub fn clone_100_and_pop_all(b: &mut Bencher) { + let src = pos(100); + b.iter(|| { + let mut set = src.clone(); + while set.pop_first().is_some() {} + set + }); } #[bench] -pub fn build_and_pop_all(b: &mut Bencher) { +pub fn clone_100_and_remove_all(b: &mut Bencher) { + let src = pos(100); b.iter(|| { - let mut s = pos(BUILD_SET_SIZE); - while s.pop_first().is_some() {} - s + let mut set = src.clone(); + while let Some(elt) = set.iter().copied().next() { + set.remove(&elt); + } + set }); } #[bench] -pub fn build_and_remove_all(b: &mut Bencher) { +pub fn clone_100_and_remove_half(b: &mut Bencher) { + let src = pos(100); b.iter(|| { - let mut s = pos(BUILD_SET_SIZE); - while let Some(elt) = s.iter().copied().next() { - s.remove(&elt); + let mut set = src.clone(); + for i in (2..=100 as i32).step_by(2) { + set.remove(&i); } - s + assert_eq!(set.len(), 100 / 2); + set + }) +} + +#[bench] +pub fn clone_10k(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| src.clone()) +} + +#[bench] +pub fn clone_10k_and_clear(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| src.clone().clear()) +} + +#[bench] +pub fn clone_10k_and_into_iter(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| src.clone().into_iter().count()) +} + +#[bench] +pub fn clone_10k_and_pop_all(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| { + let mut set = src.clone(); + while set.pop_first().is_some() {} + set + }); +} + +#[bench] +pub fn clone_10k_and_remove_all(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| { + let mut set = src.clone(); + while let Some(elt) = set.iter().copied().next() { + set.remove(&elt); + } + set }); } +#[bench] +pub fn clone_10k_and_remove_half(b: &mut Bencher) { + let src = pos(10_000); + b.iter(|| { + let mut set = src.clone(); + for i in (2..=10_000 as i32).step_by(2) { + set.remove(&i); + } + assert_eq!(set.len(), 10_000 / 2); + set + }) +} + set_bench! {intersection_100_neg_vs_100_pos, intersection, count, [neg(100), pos(100)]} set_bench! {intersection_100_neg_vs_10k_pos, intersection, count, [neg(100), pos(10_000)]} set_bench! {intersection_100_pos_vs_100_neg, intersection, count, [pos(100), neg(100)]} From 38060567e89bb142e8a060d91bf53f7e82eaaae6 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 11 Jan 2020 14:30:02 +0000 Subject: [PATCH 0034/1250] Correct inference of primitive operand type behind binary operation --- src/librustc_typeck/check/op.rs | 41 ++++++++++++++----- .../infer-binary-operand-behind-reference.rs | 13 ++++++ 2 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/inference/infer-binary-operand-behind-reference.rs diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 028c39b80e4..0c1557a59c2 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -25,7 +25,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = if !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { - self.enforce_builtin_binop_types(lhs, lhs_ty, rhs, rhs_ty, op); + self.enforce_builtin_binop_types(&lhs.span, lhs_ty, &rhs.span, rhs_ty, op); self.tcx.mk_unit() } else { return_ty @@ -86,8 +86,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && !rhs_ty.is_ty_var() && is_builtin_binop(lhs_ty, rhs_ty, op) { - let builtin_return_ty = - self.enforce_builtin_binop_types(lhs_expr, lhs_ty, rhs_expr, rhs_ty, op); + let builtin_return_ty = self.enforce_builtin_binop_types( + &lhs_expr.span, + lhs_ty, + &rhs_expr.span, + rhs_ty, + op, + ); self.demand_suptype(expr.span, builtin_return_ty, return_ty); } @@ -98,19 +103,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn enforce_builtin_binop_types( &self, - lhs_expr: &'tcx hir::Expr<'tcx>, + lhs_span: &Span, lhs_ty: Ty<'tcx>, - rhs_expr: &'tcx hir::Expr<'tcx>, + rhs_span: &Span, rhs_ty: Ty<'tcx>, op: hir::BinOp, ) -> Ty<'tcx> { debug_assert!(is_builtin_binop(lhs_ty, rhs_ty, op)); + // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. + // (See https://github.com/rust-lang/rust/issues/57447.) + let (lhs_ty, rhs_ty) = (deref_ty_if_possible(lhs_ty), deref_ty_if_possible(rhs_ty)); + let tcx = self.tcx; match BinOpCategory::from(op) { BinOpCategory::Shortcircuit => { - self.demand_suptype(lhs_expr.span, tcx.mk_bool(), lhs_ty); - self.demand_suptype(rhs_expr.span, tcx.mk_bool(), rhs_ty); + self.demand_suptype(*lhs_span, tcx.mk_bool(), lhs_ty); + self.demand_suptype(*rhs_span, tcx.mk_bool(), rhs_ty); tcx.mk_bool() } @@ -121,13 +130,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { BinOpCategory::Math | BinOpCategory::Bitwise => { // both LHS and RHS and result will have the same type - self.demand_suptype(rhs_expr.span, lhs_ty, rhs_ty); + self.demand_suptype(*rhs_span, lhs_ty, rhs_ty); lhs_ty } BinOpCategory::Comparison => { // both LHS and RHS and result will have the same type - self.demand_suptype(rhs_expr.span, lhs_ty, rhs_ty); + self.demand_suptype(*rhs_span, lhs_ty, rhs_ty); tcx.mk_bool() } } @@ -862,6 +871,14 @@ enum Op { Unary(hir::UnOp, Span), } +/// Dereferences a single level of immutable referencing. +fn deref_ty_if_possible<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { + match ty.kind { + ty::Ref(_, ty, hir::Mutability::Not) => ty, + _ => ty, + } +} + /// Returns `true` if this is a built-in arithmetic operation (e.g., u32 /// + u32, i16x4 == i16x4) and false if these types would have to be /// overloaded to be legal. There are two reasons that we distinguish @@ -878,7 +895,11 @@ enum Op { /// Reason #2 is the killer. I tried for a while to always use /// overloaded logic and just check the types in constants/codegen after /// the fact, and it worked fine, except for SIMD types. -nmatsakis -fn is_builtin_binop(lhs: Ty<'_>, rhs: Ty<'_>, op: hir::BinOp) -> bool { +fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool { + // Special-case a single layer of referencing, so that things like `5.0 + &6.0f32` work. + // (See https://github.com/rust-lang/rust/issues/57447.) + let (lhs, rhs) = (deref_ty_if_possible(lhs), deref_ty_if_possible(rhs)); + match BinOpCategory::from(op) { BinOpCategory::Shortcircuit => true, diff --git a/src/test/ui/inference/infer-binary-operand-behind-reference.rs b/src/test/ui/inference/infer-binary-operand-behind-reference.rs new file mode 100644 index 00000000000..4e41077ba34 --- /dev/null +++ b/src/test/ui/inference/infer-binary-operand-behind-reference.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() { + let _: u8 = 0 + 0; + let _: u8 = 0 + &0; + let _: u8 = &0 + 0; + let _: u8 = &0 + &0; + + let _: f32 = 0.0 + 0.0; + let _: f32 = 0.0 + &0.0; + let _: f32 = &0.0 + 0.0; + let _: f32 = &0.0 + &0.0; +} From c981d67b509f1ba16c97683ad6dc430429899e49 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 16:30:45 -0800 Subject: [PATCH 0035/1250] [!] Use `rustc_inherit_overflow_checks` in `next_power_of_two` I believe the previous code was calling `ops::Add::add` instead of the `+` operator to get this behavior. --- src/libcore/num/mod.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ed37b48b3e8..f86376cac88 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -8,7 +8,6 @@ use crate::convert::Infallible; use crate::fmt; use crate::intrinsics; use crate::mem; -use crate::ops; use crate::str::FromStr; macro_rules! impl_nonzero_fmt { @@ -4042,9 +4041,9 @@ assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[inline] + #[rustc_inherit_overflow_checks] pub fn next_power_of_two(self) -> Self { - // Call the trait to get overflow checks - ops::Add::add(self.one_less_than_next_power_of_two(), 1) + self.one_less_than_next_power_of_two() + 1 } } From 2afa99379d9623e50efd290e609447bdc5059af8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 16:31:59 -0800 Subject: [PATCH 0036/1250] Use bespoke macro instead of `?` inside const fns --- src/libcore/num/mod.rs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index f86376cac88..c38f51a0f55 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -10,6 +10,16 @@ use crate::intrinsics; use crate::mem; use crate::str::FromStr; +// Used because the `?` operator is not allowed in a const context. +macro_rules! try_opt { + ($e:expr) => { + match $e { + Some(x) => x, + None => return None, + } + }; +} + macro_rules! impl_nonzero_fmt { ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => { $( @@ -1000,17 +1010,17 @@ $EndFeature, " while exp > 1 { if (exp & 1) == 1 { - acc = acc.checked_mul(base)?; + acc = try_opt!(acc.checked_mul(base)); } exp /= 2; - base = base.checked_mul(base)?; + base = try_opt!(base.checked_mul(base)); } // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. if exp == 1 { - acc = acc.checked_mul(base)?; + acc = try_opt!(acc.checked_mul(base)); } Some(acc) @@ -3126,17 +3136,17 @@ assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFe while exp > 1 { if (exp & 1) == 1 { - acc = acc.checked_mul(base)?; + acc = try_opt!(acc.checked_mul(base)); } exp /= 2; - base = base.checked_mul(base)?; + base = try_opt!(base.checked_mul(base)); } // Deal with the final bit of the exponent separately, since // squaring the base afterwards is not necessary and may cause a // needless overflow. if exp == 1 { - acc = acc.checked_mul(base)?; + acc = try_opt!(acc.checked_mul(base)); } Some(acc) From 269bf89865536964546242589bb186a8a7e3c566 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 16:32:30 -0800 Subject: [PATCH 0037/1250] Make integer power methods const --- src/libcore/lib.rs | 3 +++ src/libcore/num/mod.rs | 42 ++++++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 1fd70e1a1b0..56117a54062 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,11 +72,14 @@ #![feature(concat_idents)] #![feature(const_alloc_layout)] #![feature(const_if_match)] +#![feature(const_loop)] #![feature(const_checked_int_methods)] #![feature(const_euclidean_int_methods)] #![feature(const_overflowing_int_methods)] #![feature(const_saturating_int_methods)] #![feature(const_int_unchecked_arith)] +#![feature(const_int_pow)] +#![feature(constctlz)] #![feature(const_panic)] #![feature(const_fn_union)] #![feature(const_generics)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index c38f51a0f55..a8c71fc208a 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1001,10 +1001,11 @@ $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_pow(self, mut exp: u32) -> Option { + pub const fn checked_pow(self, mut exp: u32) -> Option { let mut base = self; let mut acc: Self = 1; @@ -1188,10 +1189,11 @@ assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn saturating_pow(self, exp: u32) -> Self { + pub const fn saturating_pow(self, exp: u32) -> Self { match self.checked_pow(exp) { Some(x) => x, None if self < 0 && exp % 2 == 1 => Self::min_value(), @@ -1531,10 +1533,11 @@ assert_eq!(3i8.wrapping_pow(6), -39);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_pow(self, mut exp: u32) -> Self { + pub const fn wrapping_pow(self, mut exp: u32) -> Self { let mut base = self; let mut acc: Self = 1; @@ -1908,10 +1911,11 @@ assert_eq!(3i8.overflowing_pow(5), (-13, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -1957,11 +1961,12 @@ assert_eq!(x.pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn pow(self, mut exp: u32) -> Self { + pub const fn pow(self, mut exp: u32) -> Self { let mut base = self; let mut acc = 1; @@ -3127,10 +3132,11 @@ Basic usage: assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn checked_pow(self, mut exp: u32) -> Option { + pub const fn checked_pow(self, mut exp: u32) -> Option { let mut base = self; let mut acc: Self = 1; @@ -3242,10 +3248,11 @@ assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn saturating_pow(self, exp: u32) -> Self { + pub const fn saturating_pow(self, exp: u32) -> Self { match self.checked_pow(exp) { Some(x) => x, None => Self::max_value(), @@ -3535,10 +3542,11 @@ Basic usage: assert_eq!(3u8.wrapping_pow(6), 217);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn wrapping_pow(self, mut exp: u32) -> Self { + pub const fn wrapping_pow(self, mut exp: u32) -> Self { let mut base = self; let mut acc: Self = 1; @@ -3861,10 +3869,11 @@ Basic usage: assert_eq!(3u8.overflowing_pow(6), (217, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] - pub fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { + pub const fn overflowing_pow(self, mut exp: u32) -> (Self, bool) { let mut base = self; let mut acc: Self = 1; let mut overflown = false; @@ -3907,11 +3916,12 @@ Basic usage: ", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] #[rustc_inherit_overflow_checks] - pub fn pow(self, mut exp: u32) -> Self { + pub const fn pow(self, mut exp: u32) -> Self { let mut base = self; let mut acc = 1; @@ -4022,7 +4032,8 @@ assert!(!10", stringify!($SelfT), ".is_power_of_two());", $EndFeature, " // overflow cases it instead ends up returning the maximum value // of the type, and can return 0 for 0. #[inline] - fn one_less_than_next_power_of_two(self) -> Self { + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + const fn one_less_than_next_power_of_two(self) -> Self { if self <= 1 { return 0; } let p = self - 1; @@ -4050,9 +4061,10 @@ Basic usage: assert_eq!(3", stringify!($SelfT), ".next_power_of_two(), 4);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] #[inline] #[rustc_inherit_overflow_checks] - pub fn next_power_of_two(self) -> Self { + pub const fn next_power_of_two(self) -> Self { self.one_less_than_next_power_of_two() + 1 } } @@ -4075,7 +4087,8 @@ $EndFeature, " ```"), #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn checked_next_power_of_two(self) -> Option { + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + pub const fn checked_next_power_of_two(self) -> Option { self.one_less_than_next_power_of_two().checked_add(1) } } @@ -4099,7 +4112,8 @@ $EndFeature, " ```"), #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - pub fn wrapping_next_power_of_two(self) -> Self { + #[rustc_const_unstable(feature = "const_int_pow", issue = "53718")] + pub const fn wrapping_next_power_of_two(self) -> Self { self.one_less_than_next_power_of_two().wrapping_add(1) } } From 0276d7a32e1c83abc3106f7b36b711faf1f74dff Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 9 Feb 2020 01:51:13 +0000 Subject: [PATCH 0038/1250] Add more tests --- .../infer-binary-operand-behind-reference.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/test/ui/inference/infer-binary-operand-behind-reference.rs b/src/test/ui/inference/infer-binary-operand-behind-reference.rs index 4e41077ba34..0c0a3171ee9 100644 --- a/src/test/ui/inference/infer-binary-operand-behind-reference.rs +++ b/src/test/ui/inference/infer-binary-operand-behind-reference.rs @@ -1,6 +1,8 @@ // check-pass fn main() { + // Test that we can infer the type of binary operands when + // references are involved, on various types and operators. let _: u8 = 0 + 0; let _: u8 = 0 + &0; let _: u8 = &0 + 0; @@ -10,4 +12,19 @@ fn main() { let _: f32 = 0.0 + &0.0; let _: f32 = &0.0 + 0.0; let _: f32 = &0.0 + &0.0; + + let _: u8 = 0 << 0; + let _: u8 = 0 << &0; + let _: u8 = &0 << 0; + let _: u8 = &0 << &0; + + // Test type inference when variable types are indirectly inferred. + let a = 22; + let _: usize = a + &44; + + // When we have no expected type, the types of the operands is the default type. + let _ = 0 + 0; + let _ = 0 + &0; + let _ = &0 + 0; + let _ = &0 + &0; } From 7fe5eaf7d8cb23ceb71d8e509be13d20ef836114 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 16:50:00 -0800 Subject: [PATCH 0039/1250] Test integer exponentiation in a const context --- src/test/ui/consts/const-int-pow-rpass.rs | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/test/ui/consts/const-int-pow-rpass.rs b/src/test/ui/consts/const-int-pow-rpass.rs index 8e84a900605..b0fba19455b 100644 --- a/src/test/ui/consts/const-int-pow-rpass.rs +++ b/src/test/ui/consts/const-int-pow-rpass.rs @@ -1,11 +1,48 @@ // run-pass +#![feature(const_int_pow)] +#![feature(wrapping_next_power_of_two)] + const IS_POWER_OF_TWO_A: bool = 0u32.is_power_of_two(); const IS_POWER_OF_TWO_B: bool = 32u32.is_power_of_two(); const IS_POWER_OF_TWO_C: bool = 33u32.is_power_of_two(); +const POW: u8 = 3u8.pow(5); + +const CHECKED_POW_OK: Option = 3u8.checked_pow(5); +const CHECKED_POW_OVERFLOW: Option = 3u8.checked_pow(6); + +const WRAPPING_POW: u8 = 3u8.wrapping_pow(6); +const OVERFLOWING_POW: (u8, bool) = 3u8.overflowing_pow(6); +const SATURATING_POW: u8 = 3u8.saturating_pow(6); + +const NEXT_POWER_OF_TWO: u32 = 3u32.next_power_of_two(); + +const CHECKED_NEXT_POWER_OF_TWO_OK: Option = 3u32.checked_next_power_of_two(); +const CHECKED_NEXT_POWER_OF_TWO_OVERFLOW: Option = + u32::max_value().checked_next_power_of_two(); + +const WRAPPING_NEXT_POWER_OF_TWO: u32 = + u32::max_value().wrapping_next_power_of_two(); + fn main() { assert!(!IS_POWER_OF_TWO_A); assert!(IS_POWER_OF_TWO_B); assert!(!IS_POWER_OF_TWO_C); + + assert_eq!(POW, 243); + + assert_eq!(CHECKED_POW_OK, Some(243)); + assert_eq!(CHECKED_POW_OVERFLOW, None); + + assert_eq!(WRAPPING_POW, 217); + assert_eq!(OVERFLOWING_POW, (217, true)); + assert_eq!(SATURATING_POW, u8::max_value()); + + assert_eq!(NEXT_POWER_OF_TWO, 4); + + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OK, Some(4)); + assert_eq!(CHECKED_NEXT_POWER_OF_TWO_OVERFLOW, None); + + assert_eq!(WRAPPING_NEXT_POWER_OF_TWO, 0); } From f6d4720f26c92e9905c98b4ee2db832927e30a8a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 21:27:13 -0800 Subject: [PATCH 0040/1250] Make `u8::is_ascii` a stable `const fn` `char::is_ascii` is already a stable `const fn`, so there is no reason for `u8::is_ascii` to be unstable. --- src/libcore/num/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index ed37b48b3e8..81ef99e5b1c 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -4300,8 +4300,9 @@ impl u8 { /// assert!(!non_ascii.is_ascii()); /// ``` #[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")] + #[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")] #[inline] - pub fn is_ascii(&self) -> bool { + pub const fn is_ascii(&self) -> bool { *self & 128 == 0 } From bf732a11ecc319e0c0a840196bde1b5daccbdc85 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 8 Feb 2020 21:36:56 -0800 Subject: [PATCH 0041/1250] Test `u8::is_ascii` alongside `char::is_ascii` --- src/test/ui/consts/{std/char.rs => is_ascii.rs} | 6 ++++++ 1 file changed, 6 insertions(+) rename src/test/ui/consts/{std/char.rs => is_ascii.rs} (54%) diff --git a/src/test/ui/consts/std/char.rs b/src/test/ui/consts/is_ascii.rs similarity index 54% rename from src/test/ui/consts/std/char.rs rename to src/test/ui/consts/is_ascii.rs index fe79059a2e4..d8424549f93 100644 --- a/src/test/ui/consts/std/char.rs +++ b/src/test/ui/consts/is_ascii.rs @@ -3,7 +3,13 @@ static X: bool = 'a'.is_ascii(); static Y: bool = 'ä'.is_ascii(); +static BX: bool = b'a'.is_ascii(); +static BY: bool = 192u8.is_ascii(); + fn main() { assert!(X); assert!(!Y); + + assert!(BX); + assert!(!BY); } From 81e40278bd0ad707a3be2396a076f151d1ff1072 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Sun, 9 Feb 2020 10:39:48 +0100 Subject: [PATCH 0042/1250] Update RELEASES.md for 1.42.0 --- RELEASES.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 10e485c1a40..715c6b5eaaa 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,80 @@ +Version 1.42.0 (2020-03-12) +========================== + +Language +-------- +- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning + that you can create an enum that has the exact layout and ABI of the type + it contains. +- [You can now use the slice pattern syntax with subslices.][67712] e.g. + ```rust + fn foo(words: &[&str]) { + match words { + ["Hello", "World", "!", ..] => println!("Hello World!"), + ["Foo", "Bar", ..] => println!("Baz"), + rest => println!("{}", rest), + } + } + ``` + +- [Merge `TraitItem` & `ImplItem into `AssocItem`][67131] + +Compiler +-------- +- [Added tier 3\* support for `armv7a-none-eabi`.][68253] +- [Added tier 3 support for `riscv64gc-unknown-linux-gnu`.][68037] +- [`Option::{expect,unwrap}` and + `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages + pointing to the location where they were called, rather than + `core`'s internals. ][67887] + +Libraries +--------- +- [`iter::Empty` now implements Send and Sync for any `T`.][68348] +- [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type + to implement `Sized`.][67935] +- [`io::Cursor` now derives `PartialEq` and `Eq`.][67233] +- [`Layout::new` is now `const`.][66254] +- [Added Standard Library support for `riscv64gc-unknown-linux-gnu`.][66899] + + +Stabilized APIs +--------------- +- [`DebugMap::key`] +- [`DebugMap::value`] +- [`ManuallyDrop::take`] +- [`matches!`] +- [`ptr::slice_from_raw_parts_mut`] +- [`ptr::slice_from_raw_parts`] +- [`wait_timeout_while`] +- [`wait_while`] + +Compatibility Notes +------------------- +- [`Error::description` has been deprecated, and its use will now produce a + warning.][66919] It's recommended to use `Display`/`to_string` instead. + +[68253]: https://github.com/rust-lang/rust/pull/68253/ +[68348]: https://github.com/rust-lang/rust/pull/68348/ +[67935]: https://github.com/rust-lang/rust/pull/67935/ +[68037]: https://github.com/rust-lang/rust/pull/68037/ +[68122]: https://github.com/rust-lang/rust/pull/68122/ +[67712]: https://github.com/rust-lang/rust/pull/67712/ +[67887]: https://github.com/rust-lang/rust/pull/67887/ +[67131]: https://github.com/rust-lang/rust/pull/67131/ +[67233]: https://github.com/rust-lang/rust/pull/67233/ +[66899]: https://github.com/rust-lang/rust/pull/66899/ +[66919]: https://github.com/rust-lang/rust/pull/66919/ +[66254]: https://github.com/rust-lang/rust/pull/66254/ +[`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key +[`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value +[`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take +[`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html +[`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html +[`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html +[`wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while + + Version 1.41.0 (2020-01-30) =========================== From 26fdcbbc2810474770bb7f87d410a1e34b142b87 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Sun, 9 Feb 2020 14:35:08 +0100 Subject: [PATCH 0043/1250] Update RELEASES.md --- RELEASES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 715c6b5eaaa..ddd2a0a0e3b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -49,6 +49,11 @@ Stabilized APIs - [`wait_timeout_while`] - [`wait_while`] +Cargo +----- +- [You no longer need to include `extern crate proc_macro;` to be able to + `use proc_macro;` in the `2018` edition.][cargo/7700] + Compatibility Notes ------------------- - [`Error::description` has been deprecated, and its use will now produce a @@ -66,6 +71,7 @@ Compatibility Notes [66899]: https://github.com/rust-lang/rust/pull/66899/ [66919]: https://github.com/rust-lang/rust/pull/66919/ [66254]: https://github.com/rust-lang/rust/pull/66254/ +[cargo/7700]: https://github.com/rust-lang/cargo/pull/7700 [`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key [`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value [`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take From 86bf96291d8222dbec9e07461404ecb189be0a98 Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Mon, 16 Dec 2019 04:05:25 +0900 Subject: [PATCH 0044/1250] Implement split_inclusive for slice and str, an splitting iterator that includes the matched part in the iterated substrings as a terminator. --- src/liballoc/tests/lib.rs | 1 + src/liballoc/tests/slice.rs | 20 +++ src/liballoc/tests/str.rs | 18 +++ src/libcore/slice/mod.rs | 261 +++++++++++++++++++++++++++++++++++- src/libcore/str/mod.rs | 123 +++++++++++++++++ 5 files changed, 422 insertions(+), 1 deletion(-) diff --git a/src/liballoc/tests/lib.rs b/src/liballoc/tests/lib.rs index c1ae67a1a33..ea75f8903c3 100644 --- a/src/liballoc/tests/lib.rs +++ b/src/liballoc/tests/lib.rs @@ -12,6 +12,7 @@ #![feature(binary_heap_into_iter_sorted)] #![feature(binary_heap_drain_sorted)] #![feature(vec_remove_item)] +#![feature(split_inclusive)] use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 51ddb5e7a4e..9e903b16a26 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -851,6 +851,26 @@ fn test_splitator() { assert_eq!(xs.split(|x| *x == 5).collect::>(), splits); } +#[test] +fn test_splitator_inclusive() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; + assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5], &[]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 10).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5], &[]]; + assert_eq!(xs.split_inclusive(|_| true).collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); +} + #[test] fn test_splitnator() { let xs = &[1, 2, 3, 4, 5]; diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index d3c72615696..fc2fcb6e569 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1247,6 +1247,24 @@ fn test_split_char_iterator_no_trailing() { assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]); } +#[test] +fn test_split_char_iterator_inclusive() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split_inclusive('\n').collect(); + assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n", ""]); + + let uppercase_separated = "SheePSharKTurtlECaT"; + let mut first_char = true; + let split: Vec<&str> = uppercase_separated.split_inclusive(|c: char| { + let split = !first_char && c.is_uppercase(); + first_char = split; + split + }).collect(); + assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT", ""]); +} + + #[test] fn test_rsplit() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 9b4d2015732..202ffc390e4 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1155,6 +1155,72 @@ impl [T] { SplitMut { v: self, pred, finished: false } } + /// Returns an iterator over subslices separated by elements that match + /// `pred`. The matched element is contained in the end of the previous + /// subslice as a terminator. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_inclusive)] + /// let slice = [10, 40, 33, 20]; + /// let mut iter = slice.split_inclusive(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]); + /// assert_eq!(iter.next().unwrap(), &[20]); + /// assert!(iter.next().is_none()); + /// ``` + /// + /// If the first element is matched, an empty slice will be the first item + /// returned by the iterator. Similarly, if the last element in the slice + /// is matched, an empty slice will be the last item returned by the + /// iterator: + /// + /// ``` + /// #![feature(split_inclusive)] + /// let slice = [10, 40, 33]; + /// let mut iter = slice.split_inclusive(|num| num % 3 == 0); + /// + /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]); + /// assert_eq!(iter.next().unwrap(), &[]); + /// assert!(iter.next().is_none()); + /// ``` + #[unstable(feature = "split_inclusive", issue = "0")] + #[inline] + pub fn split_inclusive(&self, pred: F) -> SplitInclusive<'_, T, F> + where F: FnMut(&T) -> bool + { + SplitInclusive { + v: self, + pred, + finished: false + } + } + + /// Returns an iterator over mutable subslices separated by elements that + /// match `pred`. The matched element is contained in the previous + /// subslice as a terminator. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_inclusive)] + /// let mut v = [10, 40, 30, 20, 60, 50]; + /// + /// for group in v.split_inclusive_mut(|num| *num % 3 == 0) { + /// let terminator_idx = group.len()-1; + /// group[terminator_idx] = 1; + /// } + /// assert_eq!(v, [10, 40, 1, 20, 1, 1]); + /// ``` + #[unstable(feature = "split_inclusive", issue = "0")] + #[inline] + pub fn split_inclusive_mut(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F> + where F: FnMut(&T) -> bool + { + SplitInclusiveMut { v: self, pred, finished: false } + } + /// Returns an iterator over subslices separated by elements that match /// `pred`, starting at the end of the slice and working backwards. /// The matched element is not contained in the subslices. @@ -3675,7 +3741,100 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {} -/// An iterator over the subslices of the vector which are separated +/// An iterator over subslices separated by elements that match a predicate +/// function. Unlike `Split`, it contains the matched part as a terminator +/// of the subslice. +/// +/// This struct is created by the [`split_inclusive`] method on [slices]. +/// +/// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "split_inclusive", issue = "0")] +pub struct SplitInclusive<'a, T:'a, P> where P: FnMut(&T) -> bool { + v: &'a [T], + pred: P, + finished: bool +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl fmt::Debug for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusive") + .field("v", &self.v) + .field("finished", &self.finished) + .finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[unstable(feature = "split_inclusive", issue = "0")] +impl Clone for SplitInclusive<'_, T, P> where P: Clone + FnMut(&T) -> bool { + fn clone(&self) -> Self { + SplitInclusive { + v: self.v, + pred: self.pred.clone(), + finished: self.finished, + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> Iterator for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { + type Item = &'a [T]; + + #[inline] + fn next(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().position(|x| (self.pred)(x)) { + None => self.finish(), + Some(idx) => { + let ret = Some(&self.v[..idx + 1]); + self.v = &self.v[idx + 1..]; + ret + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + (1, Some(self.v.len() + 1)) + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn next_back(&mut self) -> Option<&'a [T]> { + if self.finished { return None; } + + match self.v.iter().rposition(|x| (self.pred)(x)) { + None => self.finish(), + Some(idx) => { + let ret = Some(&self.v[idx + 1..]); + self.v = &self.v[..idx]; + ret + } + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> SplitIter for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn finish(&mut self) -> Option<&'a [T]> { + if self.finished { None } else { self.finished = true; Some(self.v) } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {} + +/// An iterator over the mutable subslices of the vector which are separated /// by elements that match `pred`. /// /// This struct is created by the [`split_mut`] method on [slices]. @@ -3789,6 +3948,106 @@ where #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {} +/// An iterator over the mutable subslices of the vector which are separated +/// by elements that match `pred`. Unlike `SplitMut`, it contains the matched +/// parts in the ends of the subslices. +/// +/// This struct is created by the [`split_inclusive_mut`] method on [slices]. +/// +/// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut +/// [slices]: ../../std/primitive.slice.html +#[unstable(feature = "split_inclusive", issue = "0")] +pub struct SplitInclusiveMut<'a, T:'a, P> where P: FnMut(&T) -> bool { + v: &'a mut [T], + pred: P, + finished: bool +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl fmt::Debug for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusiveMut") + .field("v", &self.v) + .field("finished", &self.finished) + .finish() + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> SplitIter for SplitInclusiveMut<'a, T, P> where P: FnMut(&T) -> bool { + #[inline] + fn finish(&mut self) -> Option<&'a mut [T]> { + if self.finished { + None + } else { + self.finished = true; + Some(mem::replace(&mut self.v, &mut [])) + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P> where P: FnMut(&T) -> bool { + type Item = &'a mut [T]; + + #[inline] + fn next(&mut self) -> Option<&'a mut [T]> { + if self.finished { return None; } + + let idx_opt = { // work around borrowck limitations + let pred = &mut self.pred; + self.v.iter().position(|x| (*pred)(x)) + }; + match idx_opt { + None => self.finish(), + Some(idx) => { + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.split_at_mut(idx+1); + self.v = tail; + Some(head) + } + } + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + if self.finished { + (0, Some(0)) + } else { + // if the predicate doesn't match anything, we yield one slice + // if it matches every element, we yield len+1 empty slices. + (1, Some(self.v.len() + 1)) + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P> where + P: FnMut(&T) -> bool, +{ + #[inline] + fn next_back(&mut self) -> Option<&'a mut [T]> { + if self.finished { return None; } + + let idx_opt = { // work around borrowck limitations + let pred = &mut self.pred; + self.v.iter().rposition(|x| (*pred)(x)) + }; + match idx_opt { + None => self.finish(), + Some(idx) => { + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.split_at_mut(idx+1); + self.v = head; + Some(tail) + } + } + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {} + /// An iterator over subslices separated by elements that match a predicate /// function, starting from the end of the slice. /// diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 5a7cddd4041..3f7defa912b 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1132,6 +1132,21 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { } } + #[inline] + fn next_inclusive(&mut self) -> Option<&'a str> { + if self.finished { return None } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match() { + Some((_, b)) => unsafe { + let elt = haystack.get_unchecked(self.start..b); + self.start = b; + Some(elt) + }, + None => self.get_end(), + } + } + #[inline] fn next_back(&mut self) -> Option<&'a str> where @@ -1168,6 +1183,34 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { }, } } + + #[inline] + fn next_back_inclusive(&mut self) -> Option<&'a str> + where P::Searcher: ReverseSearcher<'a> + { + if self.finished { return None } + + if !self.allow_trailing_empty { + self.allow_trailing_empty = true; + match self.next_back() { + Some(elt) if !elt.is_empty() => return Some(elt), + _ => if self.finished { return None } + } + } + + let haystack = self.matcher.haystack(); + match self.matcher.next_match_back() { + Some((_, b)) => unsafe { + let elt = haystack.get_unchecked(b..self.end); + self.end = b; + Some(elt) + }, + None => unsafe { + self.finished = true; + Some(haystack.get_unchecked(self.start..self.end)) + }, + } + } } generate_pattern_iterators! { @@ -3212,6 +3255,31 @@ impl str { }) } + /// An iterator over substrings of this string slice, separated by + /// characters matched by a pattern. Differs from the iterator produced by + /// `split` in that `split_inclusive` leaves the matched part as the + /// terminator of the substring. + /// + /// # Examples + /// + /// ``` + /// #![feature(split_inclusive)] + /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb." + /// .split_inclusive('\n').collect(); + /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]); + /// ``` + #[unstable(feature = "split_inclusive", issue = "0")] + #[inline] + pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'a, P> { + SplitInclusive(SplitInternal { + start: 0, + end: self.len(), + matcher: pat.into_searcher(self), + allow_trailing_empty: true, + finished: false, + }) + } + /// An iterator over substrings of the given string slice, separated by /// characters matched by a pattern and yielded in reverse order. /// @@ -4405,6 +4473,19 @@ pub struct SplitAsciiWhitespace<'a> { inner: Map, BytesIsNotEmpty>, UnsafeBytesToStr>, } +/// An iterator over the substrings of a string, +/// terminated by a substring matching to a predicate function +/// Unlike `Split`, it contains the matched part as a terminator +/// of the subslice. +/// +/// This struct is created by the [`split_inclusive`] method on [`str`]. +/// See its documentation for more. +/// +/// [`split_inclusive`]: ../../std/primitive.str.html#method.split_inclusive +/// [`str`]: ../../std/primitive.str.html +#[unstable(feature = "split_inclusive", issue = "0")] +pub struct SplitInclusive<'a, P: Pattern<'a>>(SplitInternal<'a, P>); + impl_fn_for_zst! { #[derive(Clone)] struct IsWhitespace impl Fn = |c: char| -> bool { @@ -4433,6 +4514,8 @@ impl_fn_for_zst! { }; } + + #[stable(feature = "split_whitespace", since = "1.1.0")] impl<'a> Iterator for SplitWhitespace<'a> { type Item = &'a str; @@ -4495,6 +4578,46 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] impl FusedIterator for SplitAsciiWhitespace<'_> {} +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { + type Item = &'a str; + + #[inline] + fn next(&mut self) -> Option<&'a str> { + self.0.next_inclusive() + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitInclusive") + .field("0", &self.0) + .finish() + } +} + +// FIXME(#26925) Remove in favor of `#[derive(Clone)]` +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> { + fn clone(&self) -> Self { + SplitInclusive(self.0.clone()) + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator + for SplitInclusive<'a, P> +{ + #[inline] + fn next_back(&mut self) -> Option<&'a str> { + self.0.next_back_inclusive() + } +} + +#[unstable(feature = "split_inclusive", issue = "0")] +impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} + /// An iterator of [`u16`] over the string encoded as UTF-16. /// /// [`u16`]: ../../std/primitive.u16.html From 5c9dc57cb587761561e85574c821a6f9c0c7cc67 Mon Sep 17 00:00:00 2001 From: Pyry Kontio Date: Sat, 25 Jan 2020 17:47:46 +0900 Subject: [PATCH 0045/1250] Don't return empty slice on last iteration with matched terminator. Test reverse iteration. --- src/liballoc/tests/slice.rs | 64 ++++++++++- src/liballoc/tests/str.rs | 39 +++++-- src/libcore/slice/mod.rs | 221 +++++++++++++++++++----------------- src/libcore/str/mod.rs | 63 +++++++--- 4 files changed, 255 insertions(+), 132 deletions(-) diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 9e903b16a26..3d6b4bff5e0 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -859,11 +859,11 @@ fn test_splitator_inclusive() { assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).collect::>(), splits); let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; assert_eq!(xs.split_inclusive(|x| *x == 1).collect::>(), splits); - let splits: &[&[_]] = &[&[1, 2, 3, 4, 5], &[]]; + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; assert_eq!(xs.split_inclusive(|x| *x == 10).collect::>(), splits); - let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5], &[]]; + let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; assert_eq!(xs.split_inclusive(|_| true).collect::>(), splits); let xs: &[i32] = &[]; @@ -871,6 +871,66 @@ fn test_splitator_inclusive() { assert_eq!(xs.split_inclusive(|x| *x == 5).collect::>(), splits); } +#[test] +fn test_splitator_inclusive_reverse() { + let xs = &[1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; + assert_eq!(xs.split_inclusive(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; + assert_eq!(xs.split_inclusive(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive(|x| *x == 10).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; + assert_eq!(xs.split_inclusive(|_| true).rev().collect::>(), splits); + + let xs: &[i32] = &[]; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive(|x| *x == 5).rev().collect::>(), splits); +} + +#[test] +fn test_splitator_mut_inclusive() { + let xs = &mut [1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[1, 2], &[3, 4], &[5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 1).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 10).collect::>(), splits); + let splits: &[&[_]] = &[&[1], &[2], &[3], &[4], &[5]]; + assert_eq!(xs.split_inclusive_mut(|_| true).collect::>(), splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).collect::>(), splits); +} + +#[test] +fn test_splitator_mut_inclusive_reverse() { + let xs = &mut [1, 2, 3, 4, 5]; + + let splits: &[&[_]] = &[&[5], &[3, 4], &[1, 2]]; + assert_eq!(xs.split_inclusive_mut(|x| *x % 2 == 0).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[2, 3, 4, 5], &[1]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 1).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[1, 2, 3, 4, 5]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 10).rev().collect::>(), splits); + let splits: &[&[_]] = &[&[5], &[4], &[3], &[2], &[1]]; + assert_eq!(xs.split_inclusive_mut(|_| true).rev().collect::>(), splits); + + let xs: &mut [i32] = &mut []; + let splits: &[&[i32]] = &[&[]]; + assert_eq!(xs.split_inclusive_mut(|x| *x == 5).rev().collect::>(), splits); +} + #[test] fn test_splitnator() { let xs = &[1, 2, 3, 4, 5]; diff --git a/src/liballoc/tests/str.rs b/src/liballoc/tests/str.rs index fc2fcb6e569..b703df6f3cb 100644 --- a/src/liballoc/tests/str.rs +++ b/src/liballoc/tests/str.rs @@ -1252,18 +1252,43 @@ fn test_split_char_iterator_inclusive() { let data = "\nMäry häd ä little lämb\nLittle lämb\n"; let split: Vec<&str> = data.split_inclusive('\n').collect(); - assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n", ""]); + assert_eq!(split, ["\n", "Märy häd ä little lämb\n", "Little lämb\n"]); let uppercase_separated = "SheePSharKTurtlECaT"; let mut first_char = true; - let split: Vec<&str> = uppercase_separated.split_inclusive(|c: char| { - let split = !first_char && c.is_uppercase(); - first_char = split; - split - }).collect(); - assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT", ""]); + let split: Vec<&str> = uppercase_separated + .split_inclusive(|c: char| { + let split = !first_char && c.is_uppercase(); + first_char = split; + split + }) + .collect(); + assert_eq!(split, ["SheeP", "SharK", "TurtlE", "CaT"]); } +#[test] +fn test_split_char_iterator_inclusive_rev() { + let data = "\nMäry häd ä little lämb\nLittle lämb\n"; + + let split: Vec<&str> = data.split_inclusive('\n').rev().collect(); + assert_eq!(split, ["Little lämb\n", "Märy häd ä little lämb\n", "\n"]); + + // Note that the predicate is stateful and thus dependent + // on the iteration order. + // (A different predicate is needed for reverse iterator vs normal iterator.) + // Not sure if anything can be done though. + let uppercase_separated = "SheePSharKTurtlECaT"; + let mut term_char = true; + let split: Vec<&str> = uppercase_separated + .split_inclusive(|c: char| { + let split = term_char && c.is_uppercase(); + term_char = c.is_uppercase(); + split + }) + .rev() + .collect(); + assert_eq!(split, ["CaT", "TurtlE", "SharK", "SheeP"]); +} #[test] fn test_rsplit() { diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 202ffc390e4..2f70dcff2f3 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1171,30 +1171,26 @@ impl [T] { /// assert!(iter.next().is_none()); /// ``` /// - /// If the first element is matched, an empty slice will be the first item - /// returned by the iterator. Similarly, if the last element in the slice - /// is matched, an empty slice will be the last item returned by the - /// iterator: + /// If the last element of the slice is matched, + /// that element will be considered the terminator of the preceding slice. + /// That slice will be the last item returned by the iterator. /// /// ``` /// #![feature(split_inclusive)] - /// let slice = [10, 40, 33]; + /// let slice = [3, 10, 40, 33]; /// let mut iter = slice.split_inclusive(|num| num % 3 == 0); /// + /// assert_eq!(iter.next().unwrap(), &[3]); /// assert_eq!(iter.next().unwrap(), &[10, 40, 33]); - /// assert_eq!(iter.next().unwrap(), &[]); /// assert!(iter.next().is_none()); /// ``` - #[unstable(feature = "split_inclusive", issue = "0")] + #[unstable(feature = "split_inclusive", issue = "none")] #[inline] pub fn split_inclusive(&self, pred: F) -> SplitInclusive<'_, T, F> - where F: FnMut(&T) -> bool + where + F: FnMut(&T) -> bool, { - SplitInclusive { - v: self, - pred, - finished: false - } + SplitInclusive { v: self, pred, finished: false } } /// Returns an iterator over mutable subslices separated by elements that @@ -1213,10 +1209,11 @@ impl [T] { /// } /// assert_eq!(v, [10, 40, 1, 20, 1, 1]); /// ``` - #[unstable(feature = "split_inclusive", issue = "0")] + #[unstable(feature = "split_inclusive", issue = "none")] #[inline] pub fn split_inclusive_mut(&mut self, pred: F) -> SplitInclusiveMut<'_, T, F> - where F: FnMut(&T) -> bool + where + F: FnMut(&T) -> bool, { SplitInclusiveMut { v: self, pred, finished: false } } @@ -3749,15 +3746,21 @@ impl FusedIterator for Split<'_, T, P> where P: FnMut(&T) -> bool {} /// /// [`split_inclusive`]: ../../std/primitive.slice.html#method.split_inclusive /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "split_inclusive", issue = "0")] -pub struct SplitInclusive<'a, T:'a, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +pub struct SplitInclusive<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ v: &'a [T], pred: P, - finished: bool + finished: bool, } -#[unstable(feature = "split_inclusive", issue = "0")] -impl fmt::Debug for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl fmt::Debug for SplitInclusive<'_, T, P> +where + P: FnMut(&T) -> bool, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitInclusive") .field("v", &self.v) @@ -3767,71 +3770,71 @@ impl fmt::Debug for SplitInclusive<'_, T, P> where P: FnMut(&T } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "split_inclusive", issue = "0")] -impl Clone for SplitInclusive<'_, T, P> where P: Clone + FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl Clone for SplitInclusive<'_, T, P> +where + P: Clone + FnMut(&T) -> bool, +{ fn clone(&self) -> Self { - SplitInclusive { - v: self.v, - pred: self.pred.clone(), - finished: self.finished, - } + SplitInclusive { v: self.v, pred: self.pred.clone(), finished: self.finished } } } -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> Iterator for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl<'a, T, P> Iterator for SplitInclusive<'a, T, P> +where + P: FnMut(&T) -> bool, +{ type Item = &'a [T]; #[inline] fn next(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } + if self.finished { + return None; + } - match self.v.iter().position(|x| (self.pred)(x)) { - None => self.finish(), - Some(idx) => { - let ret = Some(&self.v[..idx + 1]); - self.v = &self.v[idx + 1..]; - ret - } + let idx = + self.v.iter().position(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(self.v.len()); + if idx == self.v.len() { + self.finished = true; } + let ret = Some(&self.v[..idx]); + self.v = &self.v[idx..]; + ret } #[inline] fn size_hint(&self) -> (usize, Option) { - if self.finished { - (0, Some(0)) - } else { - (1, Some(self.v.len() + 1)) - } + if self.finished { (0, Some(0)) } else { (1, Some(self.v.len() + 1)) } } } -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusive<'a, T, P> +where + P: FnMut(&T) -> bool, +{ #[inline] fn next_back(&mut self) -> Option<&'a [T]> { - if self.finished { return None; } - - match self.v.iter().rposition(|x| (self.pred)(x)) { - None => self.finish(), - Some(idx) => { - let ret = Some(&self.v[idx + 1..]); - self.v = &self.v[..idx]; - ret - } + if self.finished { + return None; } - } -} -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> SplitIter for SplitInclusive<'a, T, P> where P: FnMut(&T) -> bool { - #[inline] - fn finish(&mut self) -> Option<&'a [T]> { - if self.finished { None } else { self.finished = true; Some(self.v) } + // The last index of self.v is already checked and found to match + // by the last iteration, so we start searching a new match + // one index to the left. + let remainder = if self.v.len() == 0 { &[] } else { &self.v[..(self.v.len() - 1)] }; + let idx = remainder.iter().rposition(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(0); + if idx == 0 { + self.finished = true; + } + let ret = Some(&self.v[idx..]); + self.v = &self.v[..idx]; + ret } } -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl FusedIterator for SplitInclusive<'_, T, P> where P: FnMut(&T) -> bool {} /// An iterator over the mutable subslices of the vector which are separated @@ -3956,15 +3959,21 @@ impl FusedIterator for SplitMut<'_, T, P> where P: FnMut(&T) -> bool {} /// /// [`split_inclusive_mut`]: ../../std/primitive.slice.html#method.split_inclusive_mut /// [slices]: ../../std/primitive.slice.html -#[unstable(feature = "split_inclusive", issue = "0")] -pub struct SplitInclusiveMut<'a, T:'a, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +pub struct SplitInclusiveMut<'a, T: 'a, P> +where + P: FnMut(&T) -> bool, +{ v: &'a mut [T], pred: P, - finished: bool + finished: bool, } -#[unstable(feature = "split_inclusive", issue = "0")] -impl fmt::Debug for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl fmt::Debug for SplitInclusiveMut<'_, T, P> +where + P: FnMut(&T) -> bool, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("SplitInclusiveMut") .field("v", &self.v) @@ -3973,40 +3982,32 @@ impl fmt::Debug for SplitInclusiveMut<'_, T, P> where P: FnMut } } -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> SplitIter for SplitInclusiveMut<'a, T, P> where P: FnMut(&T) -> bool { - #[inline] - fn finish(&mut self) -> Option<&'a mut [T]> { - if self.finished { - None - } else { - self.finished = true; - Some(mem::replace(&mut self.v, &mut [])) - } - } -} - -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P> where P: FnMut(&T) -> bool { +#[unstable(feature = "split_inclusive", issue = "none")] +impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P> +where + P: FnMut(&T) -> bool, +{ type Item = &'a mut [T]; #[inline] fn next(&mut self) -> Option<&'a mut [T]> { - if self.finished { return None; } + if self.finished { + return None; + } - let idx_opt = { // work around borrowck limitations + let idx_opt = { + // work around borrowck limitations let pred = &mut self.pred; self.v.iter().position(|x| (*pred)(x)) }; - match idx_opt { - None => self.finish(), - Some(idx) => { - let tmp = mem::replace(&mut self.v, &mut []); - let (head, tail) = tmp.split_at_mut(idx+1); - self.v = tail; - Some(head) - } + let idx = idx_opt.map(|idx| idx + 1).unwrap_or(self.v.len()); + if idx == self.v.len() { + self.finished = true; } + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.split_at_mut(idx); + self.v = tail; + Some(head) } #[inline] @@ -4021,31 +4022,41 @@ impl<'a, T, P> Iterator for SplitInclusiveMut<'a, T, P> where P: FnMut(&T) -> bo } } -#[unstable(feature = "split_inclusive", issue = "0")] -impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P> where +#[unstable(feature = "split_inclusive", issue = "none")] +impl<'a, T, P> DoubleEndedIterator for SplitInclusiveMut<'a, T, P> +where P: FnMut(&T) -> bool, { #[inline] fn next_back(&mut self) -> Option<&'a mut [T]> { - if self.finished { return None; } + if self.finished { + return None; + } - let idx_opt = { // work around borrowck limitations + let idx_opt = if self.v.len() == 0 { + None + } else { + // work around borrowck limitations let pred = &mut self.pred; - self.v.iter().rposition(|x| (*pred)(x)) + + // The last index of self.v is already checked and found to match + // by the last iteration, so we start searching a new match + // one index to the left. + let remainder = &self.v[..(self.v.len() - 1)]; + remainder.iter().rposition(|x| (*pred)(x)) }; - match idx_opt { - None => self.finish(), - Some(idx) => { - let tmp = mem::replace(&mut self.v, &mut []); - let (head, tail) = tmp.split_at_mut(idx+1); - self.v = head; - Some(tail) - } + let idx = idx_opt.map(|idx| idx + 1).unwrap_or(0); + if idx == 0 { + self.finished = true; } + let tmp = mem::replace(&mut self.v, &mut []); + let (head, tail) = tmp.split_at_mut(idx); + self.v = head; + Some(tail) } } -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl FusedIterator for SplitInclusiveMut<'_, T, P> where P: FnMut(&T) -> bool {} /// An iterator over subslices separated by elements that match a predicate diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 3f7defa912b..efe6d885662 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1134,10 +1134,15 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { #[inline] fn next_inclusive(&mut self) -> Option<&'a str> { - if self.finished { return None } + if self.finished { + return None; + } let haystack = self.matcher.haystack(); match self.matcher.next_match() { + // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, + // and self.start is either the start of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. Some((_, b)) => unsafe { let elt = haystack.get_unchecked(self.start..b); self.start = b; @@ -1186,25 +1191,40 @@ impl<'a, P: Pattern<'a>> SplitInternal<'a, P> { #[inline] fn next_back_inclusive(&mut self) -> Option<&'a str> - where P::Searcher: ReverseSearcher<'a> + where + P::Searcher: ReverseSearcher<'a>, { - if self.finished { return None } + if self.finished { + return None; + } if !self.allow_trailing_empty { self.allow_trailing_empty = true; - match self.next_back() { + match self.next_back_inclusive() { Some(elt) if !elt.is_empty() => return Some(elt), - _ => if self.finished { return None } + _ => { + if self.finished { + return None; + } + } } } let haystack = self.matcher.haystack(); match self.matcher.next_match_back() { + // SAFETY: `Searcher` guarantees that `b` lies on unicode boundary, + // and self.end is either the end of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. Some((_, b)) => unsafe { let elt = haystack.get_unchecked(b..self.end); self.end = b; Some(elt) }, + // SAFETY: self.start is either the start of the original string, + // or start of a substring that represents the part of the string that hasn't + // iterated yet. Either way, it is guaranteed to lie on unicode boundary. + // self.end is either the end of the original string, + // or `b` was assigned to it, so it also lies on unicode boundary. None => unsafe { self.finished = true; Some(haystack.get_unchecked(self.start..self.end)) @@ -3268,14 +3288,25 @@ impl str { /// .split_inclusive('\n').collect(); /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb."]); /// ``` - #[unstable(feature = "split_inclusive", issue = "0")] + /// + /// If the last element of the string is matched, + /// that element will be considered the terminator of the preceding substring. + /// That substring will be the last item returned by the iterator. + /// + /// ``` + /// #![feature(split_inclusive)] + /// let v: Vec<&str> = "Mary had a little lamb\nlittle lamb\nlittle lamb.\n" + /// .split_inclusive('\n').collect(); + /// assert_eq!(v, ["Mary had a little lamb\n", "little lamb\n", "little lamb.\n"]); + /// ``` + #[unstable(feature = "split_inclusive", issue = "none")] #[inline] pub fn split_inclusive<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitInclusive<'a, P> { SplitInclusive(SplitInternal { start: 0, end: self.len(), matcher: pat.into_searcher(self), - allow_trailing_empty: true, + allow_trailing_empty: false, finished: false, }) } @@ -4483,7 +4514,7 @@ pub struct SplitAsciiWhitespace<'a> { /// /// [`split_inclusive`]: ../../std/primitive.str.html#method.split_inclusive /// [`str`]: ../../std/primitive.str.html -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] pub struct SplitInclusive<'a, P: Pattern<'a>>(SplitInternal<'a, P>); impl_fn_for_zst! { @@ -4514,8 +4545,6 @@ impl_fn_for_zst! { }; } - - #[stable(feature = "split_whitespace", since = "1.1.0")] impl<'a> Iterator for SplitWhitespace<'a> { type Item = &'a str; @@ -4578,7 +4607,7 @@ impl<'a> DoubleEndedIterator for SplitAsciiWhitespace<'a> { #[stable(feature = "split_ascii_whitespace", since = "1.34.0")] impl FusedIterator for SplitAsciiWhitespace<'_> {} -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { type Item = &'a str; @@ -4588,24 +4617,22 @@ impl<'a, P: Pattern<'a>> Iterator for SplitInclusive<'a, P> { } } -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl<'a, P: Pattern<'a, Searcher: fmt::Debug>> fmt::Debug for SplitInclusive<'a, P> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("SplitInclusive") - .field("0", &self.0) - .finish() + f.debug_struct("SplitInclusive").field("0", &self.0).finish() } } // FIXME(#26925) Remove in favor of `#[derive(Clone)]` -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl<'a, P: Pattern<'a, Searcher: Clone>> Clone for SplitInclusive<'a, P> { fn clone(&self) -> Self { SplitInclusive(self.0.clone()) } } -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator for SplitInclusive<'a, P> { @@ -4615,7 +4642,7 @@ impl<'a, P: Pattern<'a, Searcher: ReverseSearcher<'a>>> DoubleEndedIterator } } -#[unstable(feature = "split_inclusive", issue = "0")] +#[unstable(feature = "split_inclusive", issue = "none")] impl<'a, P: Pattern<'a>> FusedIterator for SplitInclusive<'a, P> {} /// An iterator of [`u16`] over the string encoded as UTF-16. From 7ab01b24674b88ff4927b0eb445a582fb9e12aba Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Mon, 10 Feb 2020 05:07:39 +0100 Subject: [PATCH 0046/1250] Update RELEASES.md Co-Authored-By: Mazdak Farrokhzad --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index ddd2a0a0e3b..f97d902d332 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -30,7 +30,7 @@ Compiler Libraries --------- -- [`iter::Empty` now implements Send and Sync for any `T`.][68348] +- [`iter::Empty` now implements `Send` and `Sync` for any `T`.][68348] - [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type to implement `Sized`.][67935] - [`io::Cursor` now derives `PartialEq` and `Eq`.][67233] From 14bcf0aaa51138afdd95190d814f4b46013f990e Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Wed, 5 Feb 2020 00:08:22 +0100 Subject: [PATCH 0047/1250] Fix Peekable::next_back --- src/libcore/iter/adapters/mod.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 7d10ef3d282..67a68cfea08 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1468,7 +1468,11 @@ where { #[inline] fn next_back(&mut self) -> Option { - self.iter.next_back().or_else(|| self.peeked.take().and_then(|x| x)) + match self.peeked.as_mut() { + Some(v @ Some(_)) => self.iter.next_back().or_else(|| v.take()), + Some(None) => None, + None => self.iter.next_back(), + } } #[inline] From 16a23e72d05b0e3cb48f0a5442e651725bf27ae8 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Wed, 5 Feb 2020 00:09:02 +0100 Subject: [PATCH 0048/1250] Fuse FlattenCompat's inner iterator --- src/libcore/iter/adapters/flatten.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index 0a7a9f26f89..6000214af43 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -1,7 +1,7 @@ use crate::fmt; use crate::ops::Try; -use super::super::{DoubleEndedIterator, FusedIterator, Iterator}; +use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator}; use super::Map; /// An iterator that maps each element to an iterator, and yields the elements @@ -239,14 +239,17 @@ where /// this type. #[derive(Clone, Debug)] struct FlattenCompat { - iter: I, + iter: Fuse, frontiter: Option, backiter: Option, } -impl FlattenCompat { +impl FlattenCompat +where + I: Iterator, +{ /// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`. fn new(iter: I) -> FlattenCompat { - FlattenCompat { iter, frontiter: None, backiter: None } + FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None } } } From 32daa2aa38fafd731ddc27374dece22f38069bc8 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:29:14 +0100 Subject: [PATCH 0049/1250] Update RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f97d902d332..5d10e658f90 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -12,7 +12,7 @@ Language match words { ["Hello", "World", "!", ..] => println!("Hello World!"), ["Foo", "Bar", ..] => println!("Baz"), - rest => println!("{}", rest), + rest => println!("{:?}", rest), } } ``` From ebbaf4611a9605412d2aa31c8ebaf0745557fff0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 11 Feb 2020 10:14:50 +0100 Subject: [PATCH 0050/1250] simplify_try: address some of eddyb's comments --- src/librustc_mir/transform/simplify_try.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index bd661195a48..3f28f033047 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -52,6 +52,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { Some(x) => x, }; if local_tmp_s0 != local_tmp_s1 + // Avoid moving into ourselves. + || local_0 == local_1 // The field-and-variant information match up. || vf_s0 != vf_s1 // Source and target locals have the same type. @@ -64,6 +66,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { } // Right shape; transform! + s0.source_info = s2.source_info; match &mut s0.kind { StatementKind::Assign(box (place, rvalue)) => { *place = local_0.into(); From 683ebc2dec0a5b88eb3eaf146e6855ea299d17b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 5 Feb 2020 21:08:07 -0800 Subject: [PATCH 0051/1250] On mismatched argument count point at arguments --- src/librustc_typeck/check/mod.rs | 54 ++++++++++++++++--- src/test/ui/arg-count-mismatch.rs | 2 +- src/test/ui/arg-count-mismatch.stderr | 6 ++- src/test/ui/c-variadic/variadic-ffi-1.rs | 4 +- src/test/ui/c-variadic/variadic-ffi-1.stderr | 12 +++-- src/test/ui/error-codes/E0057.stderr | 12 +++-- src/test/ui/error-codes/E0060.rs | 2 +- src/test/ui/error-codes/E0060.stderr | 6 ++- src/test/ui/error-codes/E0061.rs | 4 +- src/test/ui/error-codes/E0061.stderr | 12 +++-- src/test/ui/hrtb/issue-58451.rs | 2 +- src/test/ui/hrtb/issue-58451.stderr | 6 ++- src/test/ui/issues/issue-16939.stderr | 6 ++- src/test/ui/issues/issue-18819.stderr | 6 ++- src/test/ui/issues/issue-26094.rs | 8 +-- src/test/ui/issues/issue-26094.stderr | 10 ++-- src/test/ui/issues/issue-3044.rs | 2 +- src/test/ui/issues/issue-3044.stderr | 10 ++-- src/test/ui/issues/issue-4935.rs | 2 +- src/test/ui/issues/issue-4935.stderr | 6 ++- src/test/ui/methods/method-call-err-msg.rs | 8 +-- .../ui/methods/method-call-err-msg.stderr | 39 ++++++++++---- .../mismatched_types/overloaded-calls-bad.rs | 4 +- .../overloaded-calls-bad.stderr | 12 +++-- src/test/ui/not-enough-arguments.rs | 2 +- src/test/ui/not-enough-arguments.stderr | 6 ++- .../ui/resolve/resolve-primitive-fallback.rs | 2 +- .../resolve/resolve-primitive-fallback.stderr | 6 ++- src/test/ui/span/E0057.stderr | 12 +++-- src/test/ui/span/issue-34264.stderr | 12 +++-- src/test/ui/span/missing-unit-argument.stderr | 28 +++++----- ...ant-priority-higher-than-other-inherent.rs | 2 +- ...priority-higher-than-other-inherent.stderr | 6 ++- .../type-ascription-instead-of-initializer.rs | 2 +- ...e-ascription-instead-of-initializer.stderr | 6 ++- 35 files changed, 214 insertions(+), 105 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7e5d27d93b3..d2bef80ac36 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -3761,17 +3761,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { error_code: &str, c_variadic: bool, sugg_unit: bool| { + let (span, start_span, args) = match &expr.kind { + hir::ExprKind::Call(hir::Expr { span, .. }, args) => (*span, *span, &args[..]), + hir::ExprKind::MethodCall(path_segment, span, args) => ( + *span, + // `sp` doesn't point at the whole `foo.bar()`, only at `bar`. + path_segment + .args + .and_then(|args| args.args.iter().last()) + // Account for `foo.bar::()`. + .map(|arg| { + // Skip the closing `>`. + tcx.sess + .source_map() + .next_point(tcx.sess.source_map().next_point(arg.span())) + }) + .unwrap_or(*span), + &args[1..], // Skip the receiver. + ), + k => span_bug!(sp, "checking argument types on a non-call: `{:?}`", k), + }; + let arg_spans = if args.is_empty() { + // foo() + // ^^^-- supplied 0 arguments + // | + // expected 2 arguments + vec![tcx.sess.source_map().next_point(start_span).with_hi(sp.hi())] + } else { + // foo(1, 2, 3) + // ^^^ - - - supplied 3 arguments + // | + // expected 2 arguments + args.iter().map(|arg| arg.span).collect::>() + }; + let mut err = tcx.sess.struct_span_err_with_code( - sp, + span, &format!( "this function takes {}{} but {} {} supplied", if c_variadic { "at least " } else { "" }, - potentially_plural_count(expected_count, "parameter"), - potentially_plural_count(arg_count, "parameter"), + potentially_plural_count(expected_count, "argument"), + potentially_plural_count(arg_count, "argument"), if arg_count == 1 { "was" } else { "were" } ), DiagnosticId::Error(error_code.to_owned()), ); + let label = format!("supplied {}", potentially_plural_count(arg_count, "argument")); + for (i, span) in arg_spans.into_iter().enumerate() { + err.span_label( + span, + if arg_count == 0 || i + 1 == arg_count { &label } else { "" }, + ); + } if let Some(def_s) = def_span.map(|sp| tcx.sess.source_map().def_span(sp)) { err.span_label(def_s, "defined here"); @@ -3788,11 +3829,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } else { err.span_label( - sp, + span, format!( "expected {}{}", if c_variadic { "at least " } else { "" }, - potentially_plural_count(expected_count, "parameter") + potentially_plural_count(expected_count, "argument") ), ); } @@ -5494,8 +5535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.sess.span_err( span, - "this function can only be invoked \ - directly, not through a function pointer", + "this function can only be invoked directly, not through a function pointer", ); } diff --git a/src/test/ui/arg-count-mismatch.rs b/src/test/ui/arg-count-mismatch.rs index cf7487069c1..18926f5daf7 100644 --- a/src/test/ui/arg-count-mismatch.rs +++ b/src/test/ui/arg-count-mismatch.rs @@ -1,4 +1,4 @@ -// error-pattern: parameters were supplied +// error-pattern: arguments were supplied fn f(x: isize) { } diff --git a/src/test/ui/arg-count-mismatch.stderr b/src/test/ui/arg-count-mismatch.stderr index 44f16041363..7bc06134a69 100644 --- a/src/test/ui/arg-count-mismatch.stderr +++ b/src/test/ui/arg-count-mismatch.stderr @@ -1,11 +1,13 @@ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/arg-count-mismatch.rs:5:28 | LL | fn f(x: isize) { } | -------------- defined here LL | LL | fn main() { let i: (); i = f(); } - | ^^^ expected 1 parameter + | ^-- supplied 0 arguments + | | + | expected 1 argument error: aborting due to previous error diff --git a/src/test/ui/c-variadic/variadic-ffi-1.rs b/src/test/ui/c-variadic/variadic-ffi-1.rs index 6a3ff24b674..e7197a9d168 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.rs +++ b/src/test/ui/c-variadic/variadic-ffi-1.rs @@ -13,8 +13,8 @@ extern "C" fn bar(f: isize, x: u8) {} fn main() { unsafe { - foo(); //~ ERROR this function takes at least 2 parameters but 0 parameters were supplied - foo(1); //~ ERROR this function takes at least 2 parameters but 1 parameter was supplied + foo(); //~ ERROR this function takes at least 2 arguments but 0 arguments were supplied + foo(1); //~ ERROR this function takes at least 2 arguments but 1 argument was supplied let x: unsafe extern "C" fn(f: isize, x: u8) = foo; //~ ERROR mismatched types let y: extern "C" fn(f: isize, x: u8, ...) = bar; //~ ERROR mismatched types diff --git a/src/test/ui/c-variadic/variadic-ffi-1.stderr b/src/test/ui/c-variadic/variadic-ffi-1.stderr index 05d839a0c55..318b8aabafb 100644 --- a/src/test/ui/c-variadic/variadic-ffi-1.stderr +++ b/src/test/ui/c-variadic/variadic-ffi-1.stderr @@ -4,23 +4,27 @@ error[E0045]: C-variadic function must have C or cdecl calling convention LL | fn printf(_: *const u8, ...); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadics require C or cdecl calling convention -error[E0060]: this function takes at least 2 parameters but 0 parameters were supplied +error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied --> $DIR/variadic-ffi-1.rs:16:9 | LL | fn foo(f: isize, x: u8, ...); | ----------------------------- defined here ... LL | foo(); - | ^^^^^ expected at least 2 parameters + | ^^^-- supplied 0 arguments + | | + | expected at least 2 arguments -error[E0060]: this function takes at least 2 parameters but 1 parameter was supplied +error[E0060]: this function takes at least 2 arguments but 1 argument was supplied --> $DIR/variadic-ffi-1.rs:17:9 | LL | fn foo(f: isize, x: u8, ...); | ----------------------------- defined here ... LL | foo(1); - | ^^^^^^ expected at least 2 parameters + | ^^^ - supplied 1 argument + | | + | expected at least 2 arguments error[E0308]: mismatched types --> $DIR/variadic-ffi-1.rs:19:56 diff --git a/src/test/ui/error-codes/E0057.stderr b/src/test/ui/error-codes/E0057.stderr index 6b5890cac36..31579e28289 100644 --- a/src/test/ui/error-codes/E0057.stderr +++ b/src/test/ui/error-codes/E0057.stderr @@ -1,14 +1,18 @@ -error[E0057]: this function takes 1 parameter but 0 parameters were supplied +error[E0057]: this function takes 1 argument but 0 arguments were supplied --> $DIR/E0057.rs:3:13 | LL | let a = f(); - | ^^^ expected 1 parameter + | ^-- supplied 0 arguments + | | + | expected 1 argument -error[E0057]: this function takes 1 parameter but 2 parameters were supplied +error[E0057]: this function takes 1 argument but 2 arguments were supplied --> $DIR/E0057.rs:5:13 | LL | let c = f(2, 3); - | ^^^^^^^ expected 1 parameter + | ^ - - supplied 2 arguments + | | + | expected 1 argument error: aborting due to 2 previous errors diff --git a/src/test/ui/error-codes/E0060.rs b/src/test/ui/error-codes/E0060.rs index 2bb490fb3ea..941eb2a210b 100644 --- a/src/test/ui/error-codes/E0060.rs +++ b/src/test/ui/error-codes/E0060.rs @@ -5,5 +5,5 @@ extern "C" { fn main() { unsafe { printf(); } //~^ ERROR E0060 - //~| expected at least 1 parameter + //~| expected at least 1 argument } diff --git a/src/test/ui/error-codes/E0060.stderr b/src/test/ui/error-codes/E0060.stderr index 8a2e7d1a72c..a600592c6c2 100644 --- a/src/test/ui/error-codes/E0060.stderr +++ b/src/test/ui/error-codes/E0060.stderr @@ -1,11 +1,13 @@ -error[E0060]: this function takes at least 1 parameter but 0 parameters were supplied +error[E0060]: this function takes at least 1 argument but 0 arguments were supplied --> $DIR/E0060.rs:6:14 | LL | fn printf(_: *const u8, ...) -> u32; | ------------------------------------ defined here ... LL | unsafe { printf(); } - | ^^^^^^^^ expected at least 1 parameter + | ^^^^^^-- supplied 0 arguments + | | + | expected at least 1 argument error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0061.rs b/src/test/ui/error-codes/E0061.rs index e64ea36ac92..c7b5fe4310e 100644 --- a/src/test/ui/error-codes/E0061.rs +++ b/src/test/ui/error-codes/E0061.rs @@ -5,9 +5,9 @@ fn f2(a: u16) {} fn main() { f(0); //~^ ERROR E0061 - //~| expected 2 parameters + //~| expected 2 arguments f2(); //~^ ERROR E0061 - //~| expected 1 parameter + //~| expected 1 argument } diff --git a/src/test/ui/error-codes/E0061.stderr b/src/test/ui/error-codes/E0061.stderr index 73103241f7a..dfefa0df313 100644 --- a/src/test/ui/error-codes/E0061.stderr +++ b/src/test/ui/error-codes/E0061.stderr @@ -1,20 +1,24 @@ -error[E0061]: this function takes 2 parameters but 1 parameter was supplied +error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/E0061.rs:6:5 | LL | fn f(a: u16, b: &str) {} | --------------------- defined here ... LL | f(0); - | ^^^^ expected 2 parameters + | ^ - supplied 1 argument + | | + | expected 2 arguments -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/E0061.rs:10:5 | LL | fn f2(a: u16) {} | ------------- defined here ... LL | f2(); - | ^^^^ expected 1 parameter + | ^^-- supplied 0 arguments + | | + | expected 1 argument error: aborting due to 2 previous errors diff --git a/src/test/ui/hrtb/issue-58451.rs b/src/test/ui/hrtb/issue-58451.rs index 229e5057678..f36d549e476 100644 --- a/src/test/ui/hrtb/issue-58451.rs +++ b/src/test/ui/hrtb/issue-58451.rs @@ -9,5 +9,5 @@ where {} fn main() { - f(&[f()]); //~ ERROR this function takes 1 parameter + f(&[f()]); //~ ERROR this function takes 1 argument } diff --git a/src/test/ui/hrtb/issue-58451.stderr b/src/test/ui/hrtb/issue-58451.stderr index 4648c0182b9..c0915808bf5 100644 --- a/src/test/ui/hrtb/issue-58451.stderr +++ b/src/test/ui/hrtb/issue-58451.stderr @@ -1,4 +1,4 @@ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/issue-58451.rs:12:9 | LL | / fn f(i: I) @@ -9,7 +9,9 @@ LL | | {} | |__- defined here ... LL | f(&[f()]); - | ^^^ expected 1 parameter + | ^-- supplied 0 arguments + | | + | expected 1 argument error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16939.stderr b/src/test/ui/issues/issue-16939.stderr index 5df2119c141..103f56fa04d 100644 --- a/src/test/ui/issues/issue-16939.stderr +++ b/src/test/ui/issues/issue-16939.stderr @@ -1,8 +1,10 @@ -error[E0057]: this function takes 0 parameters but 1 parameter was supplied +error[E0057]: this function takes 0 arguments but 1 argument was supplied --> $DIR/issue-16939.rs:5:9 | LL | |t| f(t); - | ^^^^ expected 0 parameters + | ^ - supplied 1 argument + | | + | expected 0 arguments error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18819.stderr b/src/test/ui/issues/issue-18819.stderr index 41e8470ecd0..a952c9b46c9 100644 --- a/src/test/ui/issues/issue-18819.stderr +++ b/src/test/ui/issues/issue-18819.stderr @@ -1,11 +1,13 @@ -error[E0061]: this function takes 2 parameters but 1 parameter was supplied +error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/issue-18819.rs:16:5 | LL | fn print_x(_: &dyn Foo, extra: &str) { | ----------------------------------------------- defined here ... LL | print_x(X); - | ^^^^^^^^^^ expected 2 parameters + | ^^^^^^^ - supplied 1 argument + | | + | expected 2 arguments error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26094.rs b/src/test/ui/issues/issue-26094.rs index b9433849853..78fb0491d82 100644 --- a/src/test/ui/issues/issue-26094.rs +++ b/src/test/ui/issues/issue-26094.rs @@ -1,13 +1,13 @@ macro_rules! some_macro { ($other: expr) => ({ - $other(None) - //~^ this function takes 0 parameters but 1 parameter was supplied + $other(None) //~ NOTE supplied 1 argument }) } -fn some_function() {} +fn some_function() {} //~ NOTE defined here fn main() { some_macro!(some_function); - //~^ in this expansion of some_macro! + //~^ ERROR this function takes 0 arguments but 1 argument was supplied + //~| NOTE expected 0 arguments } diff --git a/src/test/ui/issues/issue-26094.stderr b/src/test/ui/issues/issue-26094.stderr index 0b5b6d5a750..2038d88bf46 100644 --- a/src/test/ui/issues/issue-26094.stderr +++ b/src/test/ui/issues/issue-26094.stderr @@ -1,16 +1,14 @@ -error[E0061]: this function takes 0 parameters but 1 parameter was supplied - --> $DIR/issue-26094.rs:3:9 +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/issue-26094.rs:10:17 | LL | $other(None) - | ^^^^^^^^^^^^ expected 0 parameters + | ---- supplied 1 argument ... LL | fn some_function() {} | ------------------ defined here ... LL | some_macro!(some_function); - | --------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^^^^^^^^^^^ expected 0 arguments error: aborting due to previous error diff --git a/src/test/ui/issues/issue-3044.rs b/src/test/ui/issues/issue-3044.rs index 26db04b69b4..81d76a90eb0 100644 --- a/src/test/ui/issues/issue-3044.rs +++ b/src/test/ui/issues/issue-3044.rs @@ -2,5 +2,5 @@ fn main() { let needlesArr: Vec = vec!['a', 'f']; needlesArr.iter().fold(|x, y| { }); - //~^^ ERROR this function takes 2 parameters but 1 parameter was supplied + //~^^ ERROR this function takes 2 arguments but 1 argument was supplied } diff --git a/src/test/ui/issues/issue-3044.stderr b/src/test/ui/issues/issue-3044.stderr index 35a85b604b2..d2c010659ed 100644 --- a/src/test/ui/issues/issue-3044.stderr +++ b/src/test/ui/issues/issue-3044.stderr @@ -1,8 +1,12 @@ -error[E0061]: this function takes 2 parameters but 1 parameter was supplied +error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/issue-3044.rs:3:23 | -LL | needlesArr.iter().fold(|x, y| { - | ^^^^ expected 2 parameters +LL | needlesArr.iter().fold(|x, y| { + | _______________________^^^^_- + | | | + | | expected 2 arguments +LL | | }); + | |_____- supplied 1 argument error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4935.rs b/src/test/ui/issues/issue-4935.rs index 3b258c35682..b342bbb1b8e 100644 --- a/src/test/ui/issues/issue-4935.rs +++ b/src/test/ui/issues/issue-4935.rs @@ -3,4 +3,4 @@ fn foo(a: usize) {} //~^ defined here fn main() { foo(5, 6) } -//~^ ERROR this function takes 1 parameter but 2 parameters were supplied +//~^ ERROR this function takes 1 argument but 2 arguments were supplied diff --git a/src/test/ui/issues/issue-4935.stderr b/src/test/ui/issues/issue-4935.stderr index a99581fdca1..0cc686e1cf8 100644 --- a/src/test/ui/issues/issue-4935.stderr +++ b/src/test/ui/issues/issue-4935.stderr @@ -1,11 +1,13 @@ -error[E0061]: this function takes 1 parameter but 2 parameters were supplied +error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/issue-4935.rs:5:13 | LL | fn foo(a: usize) {} | ---------------- defined here LL | LL | fn main() { foo(5, 6) } - | ^^^^^^^^^ expected 1 parameter + | ^^^ - - supplied 2 arguments + | | + | expected 1 argument error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.rs b/src/test/ui/methods/method-call-err-msg.rs index 5ff4b412667..9bfacc7babf 100644 --- a/src/test/ui/methods/method-call-err-msg.rs +++ b/src/test/ui/methods/method-call-err-msg.rs @@ -5,16 +5,18 @@ impl Foo { fn zero(self) -> Foo { self } fn one(self, _: isize) -> Foo { self } fn two(self, _: isize, _: isize) -> Foo { self } + fn three(self, _: T, _: T, _: T) -> Foo { self } } fn main() { let x = Foo; - x.zero(0) //~ ERROR this function takes 0 parameters but 1 parameter was supplied - .one() //~ ERROR this function takes 1 parameter but 0 parameters were supplied - .two(0); //~ ERROR this function takes 2 parameters but 1 parameter was supplied + x.zero(0) //~ ERROR this function takes 0 arguments but 1 argument was supplied + .one() //~ ERROR this function takes 1 argument but 0 arguments were supplied + .two(0); //~ ERROR this function takes 2 arguments but 1 argument was supplied let y = Foo; y.zero() .take() //~ ERROR no method named `take` found .one(0); + y.three::(); //~ ERROR this function takes 3 arguments but 0 arguments were supplied } diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 7efdd91708a..ab1ef5b9d5a 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -1,32 +1,38 @@ -error[E0061]: this function takes 0 parameters but 1 parameter was supplied - --> $DIR/method-call-err-msg.rs:12:7 +error[E0061]: this function takes 0 arguments but 1 argument was supplied + --> $DIR/method-call-err-msg.rs:13:7 | LL | fn zero(self) -> Foo { self } | -------------------- defined here ... LL | x.zero(0) - | ^^^^ expected 0 parameters + | ^^^^ - supplied 1 argument + | | + | expected 0 arguments -error[E0061]: this function takes 1 parameter but 0 parameters were supplied - --> $DIR/method-call-err-msg.rs:13:7 +error[E0061]: this function takes 1 argument but 0 arguments were supplied + --> $DIR/method-call-err-msg.rs:14:7 | LL | fn one(self, _: isize) -> Foo { self } | ----------------------------- defined here ... LL | .one() - | ^^^ expected 1 parameter + | ^^^- supplied 0 arguments + | | + | expected 1 argument -error[E0061]: this function takes 2 parameters but 1 parameter was supplied - --> $DIR/method-call-err-msg.rs:14:7 +error[E0061]: this function takes 2 arguments but 1 argument was supplied + --> $DIR/method-call-err-msg.rs:15:7 | LL | fn two(self, _: isize, _: isize) -> Foo { self } | --------------------------------------- defined here ... LL | .two(0); - | ^^^ expected 2 parameters + | ^^^ - supplied 1 argument + | | + | expected 2 arguments error[E0599]: no method named `take` found for struct `Foo` in the current scope - --> $DIR/method-call-err-msg.rs:18:7 + --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; | --------------- method `take` not found for this @@ -41,7 +47,18 @@ LL | .take() candidate #1: `std::io::Read` candidate #2: `std::iter::Iterator` -error: aborting due to 4 previous errors +error[E0061]: this function takes 3 arguments but 0 arguments were supplied + --> $DIR/method-call-err-msg.rs:21:7 + | +LL | fn three(self, _: T, _: T, _: T) -> Foo { self } + | ------------------------------------------ defined here +... +LL | y.three::(); + | ^^^^^--------- supplied 0 arguments + | | + | expected 3 arguments + +error: aborting due to 5 previous errors Some errors have detailed explanations: E0061, E0599. For more information about an error, try `rustc --explain E0061`. diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.rs b/src/test/ui/mismatched_types/overloaded-calls-bad.rs index 73e74a97f06..902a6ec81d6 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.rs +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.rs @@ -27,7 +27,7 @@ fn main() { }; let ans = s("what"); //~ ERROR mismatched types let ans = s(); - //~^ ERROR this function takes 1 parameter but 0 parameters were supplied + //~^ ERROR this function takes 1 argument but 0 arguments were supplied let ans = s("burma", "shave"); - //~^ ERROR this function takes 1 parameter but 2 parameters were supplied + //~^ ERROR this function takes 1 argument but 2 arguments were supplied } diff --git a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr index 5a5dd056261..706e25529bf 100644 --- a/src/test/ui/mismatched_types/overloaded-calls-bad.stderr +++ b/src/test/ui/mismatched_types/overloaded-calls-bad.stderr @@ -4,17 +4,21 @@ error[E0308]: mismatched types LL | let ans = s("what"); | ^^^^^^ expected `isize`, found `&str` -error[E0057]: this function takes 1 parameter but 0 parameters were supplied +error[E0057]: this function takes 1 argument but 0 arguments were supplied --> $DIR/overloaded-calls-bad.rs:29:15 | LL | let ans = s(); - | ^^^ expected 1 parameter + | ^-- supplied 0 arguments + | | + | expected 1 argument -error[E0057]: this function takes 1 parameter but 2 parameters were supplied +error[E0057]: this function takes 1 argument but 2 arguments were supplied --> $DIR/overloaded-calls-bad.rs:31:15 | LL | let ans = s("burma", "shave"); - | ^^^^^^^^^^^^^^^^^^^ expected 1 parameter + | ^ ------- ------- supplied 2 arguments + | | + | expected 1 argument error: aborting due to 3 previous errors diff --git a/src/test/ui/not-enough-arguments.rs b/src/test/ui/not-enough-arguments.rs index 309283ed7f4..631bb1dd274 100644 --- a/src/test/ui/not-enough-arguments.rs +++ b/src/test/ui/not-enough-arguments.rs @@ -8,5 +8,5 @@ fn foo(a: isize, b: isize, c: isize, d:isize) { fn main() { foo(1, 2, 3); - //~^ ERROR this function takes 4 parameters but 3 + //~^ ERROR this function takes 4 arguments but 3 } diff --git a/src/test/ui/not-enough-arguments.stderr b/src/test/ui/not-enough-arguments.stderr index c1ee43ea904..f2b57f71400 100644 --- a/src/test/ui/not-enough-arguments.stderr +++ b/src/test/ui/not-enough-arguments.stderr @@ -1,11 +1,13 @@ -error[E0061]: this function takes 4 parameters but 3 parameters were supplied +error[E0061]: this function takes 4 arguments but 3 arguments were supplied --> $DIR/not-enough-arguments.rs:10:3 | LL | fn foo(a: isize, b: isize, c: isize, d:isize) { | --------------------------------------------- defined here ... LL | foo(1, 2, 3); - | ^^^^^^^^^^^^ expected 4 parameters + | ^^^ - - - supplied 3 arguments + | | + | expected 4 arguments error: aborting due to previous error diff --git a/src/test/ui/resolve/resolve-primitive-fallback.rs b/src/test/ui/resolve/resolve-primitive-fallback.rs index e5a3d689d23..992bcd7977f 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.rs +++ b/src/test/ui/resolve/resolve-primitive-fallback.rs @@ -2,7 +2,7 @@ fn main() { // Make sure primitive type fallback doesn't work in value namespace std::mem::size_of(u16); //~^ ERROR expected value, found builtin type `u16` - //~| ERROR this function takes 0 parameters but 1 parameter was supplied + //~| ERROR this function takes 0 arguments but 1 argument was supplied // Make sure primitive type fallback doesn't work with global paths let _: ::u8; diff --git a/src/test/ui/resolve/resolve-primitive-fallback.stderr b/src/test/ui/resolve/resolve-primitive-fallback.stderr index 92c2a032983..6d61d2f16ca 100644 --- a/src/test/ui/resolve/resolve-primitive-fallback.stderr +++ b/src/test/ui/resolve/resolve-primitive-fallback.stderr @@ -10,11 +10,13 @@ error[E0412]: cannot find type `u8` in the crate root LL | let _: ::u8; | ^^ not found in the crate root -error[E0061]: this function takes 0 parameters but 1 parameter was supplied +error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/resolve-primitive-fallback.rs:3:5 | LL | std::mem::size_of(u16); - | ^^^^^^^^^^^^^^^^^^^^^^ expected 0 parameters + | ^^^^^^^^^^^^^^^^^ --- supplied 1 argument + | | + | expected 0 arguments error: aborting due to 3 previous errors diff --git a/src/test/ui/span/E0057.stderr b/src/test/ui/span/E0057.stderr index 6b5890cac36..31579e28289 100644 --- a/src/test/ui/span/E0057.stderr +++ b/src/test/ui/span/E0057.stderr @@ -1,14 +1,18 @@ -error[E0057]: this function takes 1 parameter but 0 parameters were supplied +error[E0057]: this function takes 1 argument but 0 arguments were supplied --> $DIR/E0057.rs:3:13 | LL | let a = f(); - | ^^^ expected 1 parameter + | ^-- supplied 0 arguments + | | + | expected 1 argument -error[E0057]: this function takes 1 parameter but 2 parameters were supplied +error[E0057]: this function takes 1 argument but 2 arguments were supplied --> $DIR/E0057.rs:5:13 | LL | let c = f(2, 3); - | ^^^^^^^ expected 1 parameter + | ^ - - supplied 2 arguments + | | + | expected 1 argument error: aborting due to 2 previous errors diff --git a/src/test/ui/span/issue-34264.stderr b/src/test/ui/span/issue-34264.stderr index 80a237ac6aa..116f5ddd5b4 100644 --- a/src/test/ui/span/issue-34264.stderr +++ b/src/test/ui/span/issue-34264.stderr @@ -50,14 +50,16 @@ help: if this is a type, explicitly ignore the parameter name LL | fn bar(_: x, y: usize) {} | ^^^^ -error[E0061]: this function takes 2 parameters but 3 parameters were supplied +error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:7:5 | LL | fn foo(Option, String) {} | --------------------------- defined here ... LL | foo(Some(42), 2, ""); - | ^^^^^^^^^^^^^^^^^^^^ expected 2 parameters + | ^^^ -------- - -- supplied 3 arguments + | | + | expected 2 arguments error[E0308]: mismatched types --> $DIR/issue-34264.rs:8:13 @@ -65,14 +67,16 @@ error[E0308]: mismatched types LL | bar("", ""); | ^^ expected `usize`, found `&str` -error[E0061]: this function takes 2 parameters but 3 parameters were supplied +error[E0061]: this function takes 2 arguments but 3 arguments were supplied --> $DIR/issue-34264.rs:10:5 | LL | fn bar(x, y: usize) {} | ------------------- defined here ... LL | bar(1, 2, 3); - | ^^^^^^^^^^^^ expected 2 parameters + | ^^^ - - - supplied 3 arguments + | | + | expected 2 arguments error: aborting due to 6 previous errors diff --git a/src/test/ui/span/missing-unit-argument.stderr b/src/test/ui/span/missing-unit-argument.stderr index 90a96e3f174..f6344fba3d3 100644 --- a/src/test/ui/span/missing-unit-argument.stderr +++ b/src/test/ui/span/missing-unit-argument.stderr @@ -1,68 +1,72 @@ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:11:33 | LL | let _: Result<(), String> = Ok(); - | ^^^^ + | ^^-- supplied 0 arguments | help: expected the unit value `()`; create it with empty parentheses | LL | let _: Result<(), String> = Ok(()); | ^^ -error[E0061]: this function takes 2 parameters but 0 parameters were supplied +error[E0061]: this function takes 2 arguments but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:12:5 | LL | fn foo(():(), ():()) {} | -------------------- defined here ... LL | foo(); - | ^^^^^ expected 2 parameters + | ^^^-- supplied 0 arguments + | | + | expected 2 arguments -error[E0061]: this function takes 2 parameters but 1 parameter was supplied +error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/missing-unit-argument.rs:13:5 | LL | fn foo(():(), ():()) {} | -------------------- defined here ... LL | foo(()); - | ^^^^^^^ expected 2 parameters + | ^^^ -- supplied 1 argument + | | + | expected 2 arguments -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:14:5 | LL | fn bar(():()) {} | ------------- defined here ... LL | bar(); - | ^^^^^ + | ^^^-- supplied 0 arguments | help: expected the unit value `()`; create it with empty parentheses | LL | bar(()); | ^^ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:15:7 | LL | fn baz(self, (): ()) { } | -------------------- defined here ... LL | S.baz(); - | ^^^ + | ^^^- supplied 0 arguments | help: expected the unit value `()`; create it with empty parentheses | LL | S.baz(()); | ^^ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/missing-unit-argument.rs:16:7 | LL | fn generic(self, _: T) { } | ------------------------- defined here ... LL | S.generic::<()>(); - | ^^^^^^^ + | ^^^^^^^------ supplied 0 arguments | help: expected the unit value `()`; create it with empty parentheses | diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs index fa3e1a35fc2..d012687533b 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.rs @@ -18,6 +18,6 @@ impl E2 { } fn main() { - ::V(); //~ ERROR this function takes 1 parameter but 0 parameters were supplied + ::V(); //~ ERROR this function takes 1 argument but 0 arguments were supplied let _: u8 = ::V; //~ ERROR mismatched types } diff --git a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr index 95c3a08c04a..46e7dd0c517 100644 --- a/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr +++ b/src/test/ui/type-alias-enum-variants/enum-variant-priority-higher-than-other-inherent.stderr @@ -1,11 +1,13 @@ -error[E0061]: this function takes 1 parameter but 0 parameters were supplied +error[E0061]: this function takes 1 argument but 0 arguments were supplied --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:21:5 | LL | V(u8) | ----- defined here ... LL | ::V(); - | ^^^^^^^^ expected 1 parameter + | ^^^^^^-- supplied 0 arguments + | | + | expected 1 argument error[E0308]: mismatched types --> $DIR/enum-variant-priority-higher-than-other-inherent.rs:22:17 diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.rs b/src/test/ui/type/type-ascription-instead-of-initializer.rs index aef25250b15..9f9b6f06bbc 100644 --- a/src/test/ui/type/type-ascription-instead-of-initializer.rs +++ b/src/test/ui/type/type-ascription-instead-of-initializer.rs @@ -1,4 +1,4 @@ fn main() { let x: Vec::with_capacity(10, 20); //~ ERROR expected type, found `10` - //~^ ERROR this function takes 1 parameter + //~^ ERROR this function takes 1 argument } diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr index 3fe676de59d..530f77e5ae9 100644 --- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr +++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr @@ -7,11 +7,13 @@ LL | let x: Vec::with_capacity(10, 20); | |help: use `=` if you meant to assign | while parsing the type for `x` -error[E0061]: this function takes 1 parameter but 2 parameters were supplied +error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/type-ascription-instead-of-initializer.rs:2:12 | LL | let x: Vec::with_capacity(10, 20); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected 1 parameter + | ^^^^^^^^^^^^^^^^^^ -- -- supplied 2 arguments + | | + | expected 1 argument error: aborting due to 2 previous errors From abcbf7c09d50421fb790d023740108016e4114de Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 30 Jan 2020 22:45:00 +0100 Subject: [PATCH 0052/1250] Document stable versions of `f32` and `f64` intrinsics Fix links --- src/libcore/intrinsics.rs | 238 +++++++++++++++++++++++++++++++++++++ src/libcore/sync/atomic.rs | 4 +- 2 files changed, 240 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2cee23a5c75..0aae6136811 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -553,28 +553,148 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor_relaxed(dst: *mut T, src: T) -> T; + /// Maximum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. For example, + /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max(dst: *mut T, src: T) -> T; + /// Maximum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. For example, + /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_acq(dst: *mut T, src: T) -> T; + /// Maximum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. For example, + /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_rel(dst: *mut T, src: T) -> T; + /// Maximum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. For example, + /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_acqrel(dst: *mut T, src: T) -> T; + /// Maximum with the current value. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing + /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) + /// as the `order`. For example, + /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_relaxed(dst: *mut T, src: T) -> T; + /// Minimum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. For example, + /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min(dst: *mut T, src: T) -> T; + /// Minimum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. For example, + /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acq(dst: *mut T, src: T) -> T; + /// Minimum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. For example, + /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_rel(dst: *mut T, src: T) -> T; + /// Minimum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. For example, + /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acqrel(dst: *mut T, src: T) -> T; + /// Minimum with the current value using a sized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing + /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) + /// as the `order`. For example, + /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_relaxed(dst: *mut T, src: T) -> T; + /// Minimum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. For example, + /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin(dst: *mut T, src: T) -> T; + /// Minimum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. For example, + /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acq(dst: *mut T, src: T) -> T; + /// Minimum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. For example, + /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_rel(dst: *mut T, src: T) -> T; + /// Minimum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. For example, + /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acqrel(dst: *mut T, src: T) -> T; + /// Minimum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing + /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) + /// as the `order`. For example, + /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_relaxed(dst: *mut T, src: T) -> T; + /// Maximum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. For example, + /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax(dst: *mut T, src: T) -> T; + /// Maximum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. For example, + /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acq(dst: *mut T, src: T) -> T; + /// Maximum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. For example, + /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_rel(dst: *mut T, src: T) -> T; + /// Maximum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. For example, + /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acqrel(dst: *mut T, src: T) -> T; + /// Maximum with the current value using an unsized comparison. + /// The stabilized version of this intrinsic is available on the + /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing + /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) + /// as the `order`. For example, + /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_relaxed(dst: *mut T, src: T) -> T; /// The `prefetch` intrinsic is a hint to the code generator to insert a prefetch instruction @@ -613,9 +733,33 @@ extern "rust-intrinsic" { extern "rust-intrinsic" { + /// An atomic fence. + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) + /// by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. pub fn atomic_fence(); + /// An atomic fence. + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) + /// by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. pub fn atomic_fence_acq(); + /// An atomic fence. + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) + /// by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. pub fn atomic_fence_rel(); + /// An atomic fence. + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) + /// by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. pub fn atomic_fence_acqrel(); /// A compiler-only memory barrier. @@ -625,8 +769,26 @@ extern "rust-intrinsic" { /// appropriate for operations on the same thread that may be preempted, /// such as when interacting with signal handlers. pub fn atomic_singlethreadfence(); + /// A compiler-only memory barrier. + /// + /// Memory accesses will never be reordered across this barrier by the + /// compiler, but no instructions will be emitted for it. This is + /// appropriate for operations on the same thread that may be preempted, + /// such as when interacting with signal handlers. pub fn atomic_singlethreadfence_acq(); + /// A compiler-only memory barrier. + /// + /// Memory accesses will never be reordered across this barrier by the + /// compiler, but no instructions will be emitted for it. This is + /// appropriate for operations on the same thread that may be preempted, + /// such as when interacting with signal handlers. pub fn atomic_singlethreadfence_rel(); + /// A compiler-only memory barrier. + /// + /// Memory accesses will never be reordered across this barrier by the + /// compiler, but no instructions will be emitted for it. This is + /// appropriate for operations on the same thread that may be preempted, + /// such as when interacting with signal handlers. pub fn atomic_singlethreadfence_acqrel(); /// Magic intrinsic that derives its meaning from attributes @@ -1047,92 +1209,164 @@ extern "rust-intrinsic" { pub fn unaligned_volatile_store(dst: *mut T, val: T); /// Returns the square root of an `f32` + /// The stabilized version of this intrinsic is + /// [`std::f32::sqrt`](../../std/primitive.f32.html#method.sqrt) pub fn sqrtf32(x: f32) -> f32; /// Returns the square root of an `f64` + /// The stabilized version of this intrinsic is + /// [`std::f64::sqrt`](../../std/primitive.f64.html#method.sqrt) pub fn sqrtf64(x: f64) -> f64; /// Raises an `f32` to an integer power. + /// The stabilized version of this intrinsic is + /// [`std::f32::powi`](../../std/primitive.f32.html#method.powi) pub fn powif32(a: f32, x: i32) -> f32; /// Raises an `f64` to an integer power. + /// The stabilized version of this intrinsic is + /// [`std::f64::powi`](../../std/primitive.f64.html#method.powi) pub fn powif64(a: f64, x: i32) -> f64; /// Returns the sine of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::sin`](../../std/primitive.f32.html#method.sin) pub fn sinf32(x: f32) -> f32; /// Returns the sine of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::sin`](../../std/primitive.f64.html#method.sin) pub fn sinf64(x: f64) -> f64; /// Returns the cosine of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::cos`](../../std/primitive.f32.html#method.cos) pub fn cosf32(x: f32) -> f32; /// Returns the cosine of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::cos`](../../std/primitive.f64.html#method.cos) pub fn cosf64(x: f64) -> f64; /// Raises an `f32` to an `f32` power. + /// The stabilized version of this intrinsic is + /// [`std::f32::powf`](../../std/primitive.f32.html#method.powf) pub fn powf32(a: f32, x: f32) -> f32; /// Raises an `f64` to an `f64` power. + /// The stabilized version of this intrinsic is + /// [`std::f64::powf`](../../std/primitive.f64.html#method.powf) pub fn powf64(a: f64, x: f64) -> f64; /// Returns the exponential of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::exp`](../../std/primitive.f32.html#method.exp) pub fn expf32(x: f32) -> f32; /// Returns the exponential of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::exp`](../../std/primitive.f64.html#method.exp) pub fn expf64(x: f64) -> f64; /// Returns 2 raised to the power of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::exp2`](../../std/primitive.f32.html#method.exp2) pub fn exp2f32(x: f32) -> f32; /// Returns 2 raised to the power of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::exp2`](../../std/primitive.f64.html#method.exp2) pub fn exp2f64(x: f64) -> f64; /// Returns the natural logarithm of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::ln`](../../std/primitive.f32.html#method.ln) pub fn logf32(x: f32) -> f32; /// Returns the natural logarithm of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::ln`](../../std/primitive.f64.html#method.ln) pub fn logf64(x: f64) -> f64; /// Returns the base 10 logarithm of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::log10`](../../std/primitive.f32.html#method.log10) pub fn log10f32(x: f32) -> f32; /// Returns the base 10 logarithm of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::log10`](../../std/primitive.f64.html#method.log10) pub fn log10f64(x: f64) -> f64; /// Returns the base 2 logarithm of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::log2`](../../std/primitive.f32.html#method.log2) pub fn log2f32(x: f32) -> f32; /// Returns the base 2 logarithm of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::log2`](../../std/primitive.f64.html#method.log2) pub fn log2f64(x: f64) -> f64; /// Returns `a * b + c` for `f32` values. + /// The stabilized version of this intrinsic is + /// [`std::f32::mul_add`](../../std/primitive.f32.html#method.mul_add) pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values. + /// The stabilized version of this intrinsic is + /// [`std::f64::mul_add`](../../std/primitive.f64.html#method.mul_add) pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; /// Returns the absolute value of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::abs`](../../std/primitive.f32.html#method.abs) pub fn fabsf32(x: f32) -> f32; /// Returns the absolute value of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::abs`](../../std/primitive.f64.html#method.abs) pub fn fabsf64(x: f64) -> f64; /// Returns the minimum of two `f32` values. + /// The stabilized version of this intrinsic is + /// [`std::f32::min`](../../std/primitive.f32.html#method.min) pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. + /// The stabilized version of this intrinsic is + /// [`std::f64::min`](../../std/primitive.f64.html#method.min) pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. + /// The stabilized version of this intrinsic is + /// [`std::f32::max`](../../std/primitive.f32.html#method.max) pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. + /// The stabilized version of this intrinsic is + /// [`std::f64::max`](../../std/primitive.f64.html#method.max) pub fn maxnumf64(x: f64, y: f64) -> f64; /// Copies the sign from `y` to `x` for `f32` values. + /// The stabilized version of this intrinsic is + /// [`std::f32::copysign`](../../std/primitive.f32.html#method.copysign) pub fn copysignf32(x: f32, y: f32) -> f32; /// Copies the sign from `y` to `x` for `f64` values. + /// The stabilized version of this intrinsic is + /// [`std::f64::copysign`](../../std/primitive.f64.html#method.copysign) pub fn copysignf64(x: f64, y: f64) -> f64; /// Returns the largest integer less than or equal to an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::floor`](../../std/primitive.f32.html#method.floor) pub fn floorf32(x: f32) -> f32; /// Returns the largest integer less than or equal to an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::floor`](../../std/primitive.f64.html#method.floor) pub fn floorf64(x: f64) -> f64; /// Returns the smallest integer greater than or equal to an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::ceil`](../../std/primitive.f32.html#method.ceil) pub fn ceilf32(x: f32) -> f32; /// Returns the smallest integer greater than or equal to an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::ceil`](../../std/primitive.f64.html#method.ceil) pub fn ceilf64(x: f64) -> f64; /// Returns the integer part of an `f32`. + /// The stabilized version of this intrinsic is + /// [`std::f32::trunc`](../../std/primitive.f32.html#method.trunc) pub fn truncf32(x: f32) -> f32; /// Returns the integer part of an `f64`. + /// The stabilized version of this intrinsic is + /// [`std::f64::trunc`](../../std/primitive.f64.html#method.trunc) pub fn truncf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. May raise an inexact floating-point exception @@ -1148,8 +1382,12 @@ extern "rust-intrinsic" { pub fn nearbyintf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. + /// The stabilized version of this intrinsic is + /// [`std::f32::round`](../../std/primitive.f32.html#method.round) pub fn roundf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. + /// The stabilized version of this intrinsic is + /// [`std::f64::round`](../../std/primitive.f64.html#method.round) pub fn roundf64(x: f64) -> f64; /// Float addition that allows optimizations based on algebraic rules. diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 9d449bb9915..3ba15968f89 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -2444,7 +2444,7 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { } } -/// returns the max value (signed comparison) +/// returns the max value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { @@ -2457,7 +2457,7 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { } } -/// returns the min value (signed comparison) +/// returns the min value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { From 216f100dfcd00891ea1f6684df77fc87711453ed Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 30 Jan 2020 14:34:29 +0100 Subject: [PATCH 0053/1250] Document stable versions of `type_name` and `type_id` --- src/libcore/intrinsics.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 0aae6136811..8991d405e79 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -870,12 +870,16 @@ extern "rust-intrinsic" { pub fn min_align_of_val(_: &T) -> usize; /// Gets a static string slice containing the name of a type. + /// The stabilized version of this intrinsic is + /// [`std::any::type_name`](../../std/any/fn.type_name.html) #[rustc_const_unstable(feature = "const_type_name", issue = "none")] pub fn type_name() -> &'static str; /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever /// crate it is invoked in. + /// The stabilized version of this intrinsic is + /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) #[rustc_const_unstable(feature = "const_type_id", issue = "none")] pub fn type_id() -> u64; From eb475b0f7fb0ab889dbc5beb66af22d2368e5ffb Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 30 Jan 2020 21:37:34 +0100 Subject: [PATCH 0054/1250] Document stable versions of memory-related intrinsics --- src/libcore/intrinsics.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 8991d405e79..1414217e971 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -855,8 +855,15 @@ extern "rust-intrinsic" { /// Moves a value to an uninitialized memory location. /// /// Drop glue is not run on the destination. + /// + /// The stabilized version of this intrinsic is + /// [`std::ptr::write`](../../std/ptr/fn.write.html). pub fn move_val_init(dst: *mut T, src: T); + /// The minimum alignment of a type. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::align_of`](../../std/mem/fn.align_of.html). #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")] pub fn min_align_of() -> usize; #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")] @@ -867,6 +874,10 @@ extern "rust-intrinsic" { /// The stabilized version of this intrinsic is /// [`std::mem::size_of_val`](../../std/mem/fn.size_of_val.html). pub fn size_of_val(_: &T) -> usize; + /// The minimum alignment of the type of the value that `val` points to. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::min_align_of_val`](../../std/mem/fn.min_align_of_val.html). pub fn min_align_of_val(_: &T) -> usize; /// Gets a static string slice containing the name of a type. @@ -897,6 +908,9 @@ extern "rust-intrinsic" { /// which is unsafe unless `T` is `Copy`. Also, even if T is /// `Copy`, an all-zero value may not correspond to any legitimate /// state for the type in question. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::zeroed`](../../std/mem/fn.zeroed.html). #[unstable( feature = "core_intrinsics", reason = "intrinsics are unlikely to ever be stabilized, instead \ @@ -914,6 +928,9 @@ extern "rust-intrinsic" { /// state, which means it may claim either dropped or /// undropped. In the general case one must use `ptr::write` to /// initialize memory previous set to the result of `uninit`. + /// + /// The stabilized version of this intrinsic is + /// [`std::mem::MaybeUninit`](../../std/mem/union.MaybeUninit.html). #[unstable( feature = "core_intrinsics", reason = "intrinsics are unlikely to ever be stabilized, instead \ @@ -1159,6 +1176,9 @@ extern "rust-intrinsic" { /// byte past the end of an allocated object. If either pointer is out of /// bounds or arithmetic overflow occurs then any further use of the /// returned value will result in undefined behavior. + /// + /// The stabilized version of this intrinsic is + /// [`std::pointer::offset`](../../std/primitive.pointer.html#method.offset). pub fn offset(dst: *const T, offset: isize) -> *const T; /// Calculates the offset from a pointer, potentially wrapping. @@ -1172,6 +1192,9 @@ extern "rust-intrinsic" { /// resulting pointer to point into or one byte past the end of an allocated /// object, and it wraps with two's complement arithmetic. The resulting /// value is not necessarily valid to be used to actually access memory. + /// + /// The stabilized version of this intrinsic is + /// [`std::pointer::wrapping_offset`](../../std/primitive.pointer.html#method.wrapping_offset). pub fn arith_offset(dst: *const T, offset: isize) -> *const T; /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with @@ -1626,6 +1649,8 @@ extern "rust-intrinsic" { /// Returns the value of the discriminant for the variant in 'v', /// cast to a `u64`; if `T` has no discriminant, returns 0. + /// The stabilized version of this intrinsic is + /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html) pub fn discriminant_value(v: &T) -> u64; /// Rust's "try catch" construct which invokes the function pointer `f` with From c37061896e444392997b2a0a5607c20df9a52531 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 30 Jan 2020 21:38:37 +0100 Subject: [PATCH 0055/1250] Document stable versions of number-related intrinsics --- src/libcore/intrinsics.rs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 1414217e971..0c45d2dd6fa 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1438,14 +1438,21 @@ extern "rust-intrinsic" { pub fn frem_fast(a: T, b: T) -> T; /// Convert with LLVM’s fptoui/fptosi, which may return undef for values out of range - /// https://github.com/rust-lang/rust/issues/10184 + /// () + /// This is under stabilization at pub fn float_to_int_approx_unchecked(value: Float) -> Int; /// Returns the number of bits set in an integer type `T` + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `count_ones` method. For example, + /// [`std::u32::count_ones`](../../std/primitive.u32.html#method.count_ones) #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")] pub fn ctpop(x: T) -> T; /// Returns the number of leading unset bits (zeroes) in an integer type `T`. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `leading_zeros` method. For example, + /// [`std::u32::leading_zeros`](../../std/primitive.u32.html#method.leading_zeros) /// /// # Examples /// @@ -1491,6 +1498,9 @@ extern "rust-intrinsic" { pub fn ctlz_nonzero(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `trailing_zeros` method. For example, + /// [`std::u32::trailing_zeros`](../../std/primitive.u32.html#method.trailing_zeros) /// /// # Examples /// @@ -1536,10 +1546,16 @@ extern "rust-intrinsic" { pub fn cttz_nonzero(x: T) -> T; /// Reverses the bytes in an integer type `T`. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `swap_bytes` method. For example, + /// [`std::u32::swap_bytes`](../../std/primitive.u32.html#method.swap_bytes) #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")] pub fn bswap(x: T) -> T; /// Reverses the bits in an integer type `T`. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `reverse_bits` method. For example, + /// [`std::u32::reverse_bits`](../../std/primitive.u32.html#method.reverse_bits) #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")] pub fn bitreverse(x: T) -> T; @@ -1569,20 +1585,34 @@ extern "rust-intrinsic" { pub fn exact_div(x: T, y: T) -> T; /// Performs an unchecked division, resulting in undefined behavior - /// where y = 0 or x = `T::min_value()` and y = -1 + /// where y = 0 or x = `T::min_value()` and y = -1. + /// + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `checked_div` method. For example, + /// [`std::u32::checked_div`](../../std/primitive.u32.html#method.checked_div) #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_div(x: T, y: T) -> T; /// Returns the remainder of an unchecked division, resulting in /// undefined behavior where y = 0 or x = `T::min_value()` and y = -1 + /// + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `checked_rem` method. For example, + /// [`std::u32::checked_rem`](../../std/primitive.u32.html#method.checked_rem) #[rustc_const_unstable(feature = "const_int_unchecked_arith", issue = "none")] pub fn unchecked_rem(x: T, y: T) -> T; /// Performs an unchecked left shift, resulting in undefined behavior when /// y < 0 or y >= N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_shl` method. For example, + /// [`std::u32::wrapping_shl`](../../std/primitive.u32.html#method.wrapping_shl) #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shl(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// y < 0 or y >= N, where N is the width of T in bits. + /// The stabilized versions of this intrinsic are available on the integer + /// primitives via the `wrapping_shr` method. For example, + /// [`std::u32::wrapping_shr`](../../std/primitive.u32.html#method.wrapping_shr) #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shr(x: T, y: T) -> T; From 842448d3102f236401d6a2d176e39977efe91176 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 31 Jan 2020 19:28:15 +0100 Subject: [PATCH 0056/1250] Add newline between summary and stable version documentation --- src/libcore/intrinsics.rs | 145 +++++++++++++++++++++++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 0c45d2dd6fa..571ef2389a9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -68,6 +68,7 @@ extern "rust-intrinsic" { // memory, which is not valid for either `&` or `&mut`. /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -77,6 +78,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -86,6 +88,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_acq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -97,6 +100,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_rel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -108,6 +112,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -117,6 +122,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -128,6 +134,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -139,6 +146,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_failacq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -150,6 +158,7 @@ extern "rust-intrinsic" { /// [compare_exchange]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange pub fn atomic_cxchg_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -162,6 +171,7 @@ extern "rust-intrinsic" { pub fn atomic_cxchg_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -171,6 +181,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -180,6 +191,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_acq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -191,6 +203,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_rel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -202,6 +215,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_acqrel(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -211,6 +225,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_relaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -222,6 +237,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -233,6 +249,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_failacq(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -244,6 +261,7 @@ extern "rust-intrinsic" { /// [cew]: ../../std/sync/atomic/struct.AtomicBool.html#method.compare_exchange_weak pub fn atomic_cxchgweak_acq_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Stores a value if the current value is the same as the `old` value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `compare_exchange_weak` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -256,6 +274,7 @@ extern "rust-intrinsic" { pub fn atomic_cxchgweak_acqrel_failrelaxed(dst: *mut T, old: T, src: T) -> (T, bool); /// Loads the current value of the pointer. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `load` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -263,6 +282,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load). pub fn atomic_load(src: *const T) -> T; /// Loads the current value of the pointer. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `load` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -270,6 +290,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::load`](../../std/sync/atomic/struct.AtomicBool.html#method.load). pub fn atomic_load_acq(src: *const T) -> T; /// Loads the current value of the pointer. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `load` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -279,6 +300,7 @@ extern "rust-intrinsic" { pub fn atomic_load_unordered(src: *const T) -> T; /// Stores the value at the specified memory location. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `store` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -286,6 +308,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store). pub fn atomic_store(dst: *mut T, val: T); /// Stores the value at the specified memory location. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `store` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -293,6 +316,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::store`](../../std/sync/atomic/struct.AtomicBool.html#method.store). pub fn atomic_store_rel(dst: *mut T, val: T); /// Stores the value at the specified memory location. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `store` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -302,6 +326,7 @@ extern "rust-intrinsic" { pub fn atomic_store_unordered(dst: *mut T, val: T); /// Stores the value at the specified memory location, returning the old value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `swap` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -309,6 +334,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). pub fn atomic_xchg(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `swap` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -316,6 +342,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). pub fn atomic_xchg_acq(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `swap` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -323,6 +350,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). pub fn atomic_xchg_rel(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `swap` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -330,6 +358,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::swap`](../../std/sync/atomic/struct.AtomicBool.html#method.swap). pub fn atomic_xchg_acqrel(dst: *mut T, src: T) -> T; /// Stores the value at the specified memory location, returning the old value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `swap` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -338,6 +367,7 @@ extern "rust-intrinsic" { pub fn atomic_xchg_relaxed(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_add` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -345,6 +375,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). pub fn atomic_xadd(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_add` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -352,6 +383,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). pub fn atomic_xadd_acq(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_add` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -359,6 +391,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). pub fn atomic_xadd_rel(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_add` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -366,6 +399,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_add`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_add). pub fn atomic_xadd_acqrel(dst: *mut T, src: T) -> T; /// Adds to the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_add` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -374,6 +408,7 @@ extern "rust-intrinsic" { pub fn atomic_xadd_relaxed(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_sub` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -381,6 +416,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). pub fn atomic_xsub(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_sub` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -388,6 +424,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). pub fn atomic_xsub_acq(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_sub` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -395,6 +432,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). pub fn atomic_xsub_rel(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_sub` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -402,6 +440,7 @@ extern "rust-intrinsic" { /// [`AtomicIsize::fetch_sub`](../../std/sync/atomic/struct.AtomicIsize.html#method.fetch_sub). pub fn atomic_xsub_acqrel(dst: *mut T, src: T) -> T; /// Subtract from the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_sub` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -410,6 +449,7 @@ extern "rust-intrinsic" { pub fn atomic_xsub_relaxed(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_and` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -417,6 +457,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). pub fn atomic_and(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_and` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -424,6 +465,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). pub fn atomic_and_acq(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_and` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -431,6 +473,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). pub fn atomic_and_rel(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_and` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -438,6 +481,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_and`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_and). pub fn atomic_and_acqrel(dst: *mut T, src: T) -> T; /// Bitwise and with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_and` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -446,6 +490,7 @@ extern "rust-intrinsic" { pub fn atomic_and_relaxed(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -453,6 +498,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). pub fn atomic_nand(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -460,6 +506,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). pub fn atomic_nand_acq(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -467,6 +514,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). pub fn atomic_nand_rel(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -474,6 +522,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_nand`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_nand). pub fn atomic_nand_acqrel(dst: *mut T, src: T) -> T; /// Bitwise nand with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic::AtomicBool` type via the `fetch_nand` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -482,6 +531,7 @@ extern "rust-intrinsic" { pub fn atomic_nand_relaxed(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_or` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -489,6 +539,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). pub fn atomic_or(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_or` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -496,6 +547,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). pub fn atomic_or_acq(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_or` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -503,6 +555,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). pub fn atomic_or_rel(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_or` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -510,6 +563,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_or`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_or). pub fn atomic_or_acqrel(dst: *mut T, src: T) -> T; /// Bitwise or with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_or` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -518,6 +572,7 @@ extern "rust-intrinsic" { pub fn atomic_or_relaxed(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_xor` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html) @@ -525,6 +580,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_xor` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html) @@ -532,6 +588,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor_acq(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_xor` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html) @@ -539,6 +596,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor_rel(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_xor` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html) @@ -546,6 +604,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor_acqrel(dst: *mut T, src: T) -> T; /// Bitwise xor with the current value, returning the previous value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` types via the `fetch_xor` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html) @@ -554,6 +613,7 @@ extern "rust-intrinsic" { pub fn atomic_xor_relaxed(dst: *mut T, src: T) -> T; /// Maximum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) @@ -561,6 +621,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max(dst: *mut T, src: T) -> T; /// Maximum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) @@ -568,6 +629,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_acq(dst: *mut T, src: T) -> T; /// Maximum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) @@ -575,6 +637,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_rel(dst: *mut T, src: T) -> T; /// Maximum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) @@ -582,6 +645,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_acqrel(dst: *mut T, src: T) -> T; /// Maximum with the current value. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) @@ -590,6 +654,7 @@ extern "rust-intrinsic" { pub fn atomic_max_relaxed(dst: *mut T, src: T) -> T; /// Minimum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) @@ -597,6 +662,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min(dst: *mut T, src: T) -> T; /// Minimum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) @@ -604,6 +670,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acq(dst: *mut T, src: T) -> T; /// Minimum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) @@ -611,6 +678,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_rel(dst: *mut T, src: T) -> T; /// Minimum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) @@ -618,6 +686,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acqrel(dst: *mut T, src: T) -> T; /// Minimum with the current value using a sized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) @@ -626,6 +695,7 @@ extern "rust-intrinsic" { pub fn atomic_min_relaxed(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) @@ -633,6 +703,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) @@ -640,6 +711,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acq(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) @@ -647,6 +719,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_rel(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) @@ -654,6 +727,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acqrel(dst: *mut T, src: T) -> T; /// Minimum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) @@ -662,6 +736,7 @@ extern "rust-intrinsic" { pub fn atomic_umin_relaxed(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) @@ -669,6 +744,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) @@ -676,6 +752,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acq(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) @@ -683,6 +760,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_rel(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) @@ -690,6 +768,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acqrel(dst: *mut T, src: T) -> T; /// Maximum with the current value using an unsized comparison. + /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing /// [`Ordering::Relaxed`](../../std/sync/atomic/enum.Ordering.html#variant.Relaxed) @@ -734,6 +813,7 @@ extern "rust-intrinsic" { extern "rust-intrinsic" { /// An atomic fence. + /// /// The stabilized version of this intrinsic is available in /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) /// by passing @@ -741,6 +821,7 @@ extern "rust-intrinsic" { /// as the `order`. pub fn atomic_fence(); /// An atomic fence. + /// /// The stabilized version of this intrinsic is available in /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) /// by passing @@ -748,6 +829,7 @@ extern "rust-intrinsic" { /// as the `order`. pub fn atomic_fence_acq(); /// An atomic fence. + /// /// The stabilized version of this intrinsic is available in /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) /// by passing @@ -755,6 +837,7 @@ extern "rust-intrinsic" { /// as the `order`. pub fn atomic_fence_rel(); /// An atomic fence. + /// /// The stabilized version of this intrinsic is available in /// [`std::sync::atomic::fence`](../../std/sync/atomic/fn.fence.html) /// by passing @@ -881,6 +964,7 @@ extern "rust-intrinsic" { pub fn min_align_of_val(_: &T) -> usize; /// Gets a static string slice containing the name of a type. + /// /// The stabilized version of this intrinsic is /// [`std::any::type_name`](../../std/any/fn.type_name.html) #[rustc_const_unstable(feature = "const_type_name", issue = "none")] @@ -889,6 +973,7 @@ extern "rust-intrinsic" { /// Gets an identifier which is globally unique to the specified type. This /// function will return the same value for a type regardless of whichever /// crate it is invoked in. + /// /// The stabilized version of this intrinsic is /// [`std::any::TypeId::of`](../../std/any/struct.TypeId.html#method.of) #[rustc_const_unstable(feature = "const_type_id", issue = "none")] @@ -1220,10 +1305,12 @@ extern "rust-intrinsic" { pub fn volatile_set_memory(dst: *mut T, val: u8, count: usize); /// Performs a volatile load from the `src` pointer. + /// /// The stabilized version of this intrinsic is /// [`std::ptr::read_volatile`](../../std/ptr/fn.read_volatile.html). pub fn volatile_load(src: *const T) -> T; /// Performs a volatile store to the `dst` pointer. + /// /// The stabilized version of this intrinsic is /// [`std::ptr::write_volatile`](../../std/ptr/fn.write_volatile.html). pub fn volatile_store(dst: *mut T, val: T); @@ -1236,162 +1323,198 @@ extern "rust-intrinsic" { pub fn unaligned_volatile_store(dst: *mut T, val: T); /// Returns the square root of an `f32` + /// /// The stabilized version of this intrinsic is /// [`std::f32::sqrt`](../../std/primitive.f32.html#method.sqrt) pub fn sqrtf32(x: f32) -> f32; /// Returns the square root of an `f64` + /// /// The stabilized version of this intrinsic is /// [`std::f64::sqrt`](../../std/primitive.f64.html#method.sqrt) pub fn sqrtf64(x: f64) -> f64; /// Raises an `f32` to an integer power. + /// /// The stabilized version of this intrinsic is /// [`std::f32::powi`](../../std/primitive.f32.html#method.powi) pub fn powif32(a: f32, x: i32) -> f32; /// Raises an `f64` to an integer power. + /// /// The stabilized version of this intrinsic is /// [`std::f64::powi`](../../std/primitive.f64.html#method.powi) pub fn powif64(a: f64, x: i32) -> f64; /// Returns the sine of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::sin`](../../std/primitive.f32.html#method.sin) pub fn sinf32(x: f32) -> f32; /// Returns the sine of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::sin`](../../std/primitive.f64.html#method.sin) pub fn sinf64(x: f64) -> f64; /// Returns the cosine of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::cos`](../../std/primitive.f32.html#method.cos) pub fn cosf32(x: f32) -> f32; /// Returns the cosine of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::cos`](../../std/primitive.f64.html#method.cos) pub fn cosf64(x: f64) -> f64; /// Raises an `f32` to an `f32` power. + /// /// The stabilized version of this intrinsic is /// [`std::f32::powf`](../../std/primitive.f32.html#method.powf) pub fn powf32(a: f32, x: f32) -> f32; /// Raises an `f64` to an `f64` power. + /// /// The stabilized version of this intrinsic is /// [`std::f64::powf`](../../std/primitive.f64.html#method.powf) pub fn powf64(a: f64, x: f64) -> f64; /// Returns the exponential of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::exp`](../../std/primitive.f32.html#method.exp) pub fn expf32(x: f32) -> f32; /// Returns the exponential of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::exp`](../../std/primitive.f64.html#method.exp) pub fn expf64(x: f64) -> f64; /// Returns 2 raised to the power of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::exp2`](../../std/primitive.f32.html#method.exp2) pub fn exp2f32(x: f32) -> f32; /// Returns 2 raised to the power of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::exp2`](../../std/primitive.f64.html#method.exp2) pub fn exp2f64(x: f64) -> f64; /// Returns the natural logarithm of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::ln`](../../std/primitive.f32.html#method.ln) pub fn logf32(x: f32) -> f32; /// Returns the natural logarithm of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::ln`](../../std/primitive.f64.html#method.ln) pub fn logf64(x: f64) -> f64; /// Returns the base 10 logarithm of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::log10`](../../std/primitive.f32.html#method.log10) pub fn log10f32(x: f32) -> f32; /// Returns the base 10 logarithm of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::log10`](../../std/primitive.f64.html#method.log10) pub fn log10f64(x: f64) -> f64; /// Returns the base 2 logarithm of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::log2`](../../std/primitive.f32.html#method.log2) pub fn log2f32(x: f32) -> f32; /// Returns the base 2 logarithm of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::log2`](../../std/primitive.f64.html#method.log2) pub fn log2f64(x: f64) -> f64; /// Returns `a * b + c` for `f32` values. + /// /// The stabilized version of this intrinsic is /// [`std::f32::mul_add`](../../std/primitive.f32.html#method.mul_add) pub fn fmaf32(a: f32, b: f32, c: f32) -> f32; /// Returns `a * b + c` for `f64` values. + /// /// The stabilized version of this intrinsic is /// [`std::f64::mul_add`](../../std/primitive.f64.html#method.mul_add) pub fn fmaf64(a: f64, b: f64, c: f64) -> f64; /// Returns the absolute value of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::abs`](../../std/primitive.f32.html#method.abs) pub fn fabsf32(x: f32) -> f32; /// Returns the absolute value of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::abs`](../../std/primitive.f64.html#method.abs) pub fn fabsf64(x: f64) -> f64; /// Returns the minimum of two `f32` values. + /// /// The stabilized version of this intrinsic is /// [`std::f32::min`](../../std/primitive.f32.html#method.min) pub fn minnumf32(x: f32, y: f32) -> f32; /// Returns the minimum of two `f64` values. + /// /// The stabilized version of this intrinsic is /// [`std::f64::min`](../../std/primitive.f64.html#method.min) pub fn minnumf64(x: f64, y: f64) -> f64; /// Returns the maximum of two `f32` values. + /// /// The stabilized version of this intrinsic is /// [`std::f32::max`](../../std/primitive.f32.html#method.max) pub fn maxnumf32(x: f32, y: f32) -> f32; /// Returns the maximum of two `f64` values. + /// /// The stabilized version of this intrinsic is /// [`std::f64::max`](../../std/primitive.f64.html#method.max) pub fn maxnumf64(x: f64, y: f64) -> f64; /// Copies the sign from `y` to `x` for `f32` values. + /// /// The stabilized version of this intrinsic is /// [`std::f32::copysign`](../../std/primitive.f32.html#method.copysign) pub fn copysignf32(x: f32, y: f32) -> f32; /// Copies the sign from `y` to `x` for `f64` values. + /// /// The stabilized version of this intrinsic is /// [`std::f64::copysign`](../../std/primitive.f64.html#method.copysign) pub fn copysignf64(x: f64, y: f64) -> f64; /// Returns the largest integer less than or equal to an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::floor`](../../std/primitive.f32.html#method.floor) pub fn floorf32(x: f32) -> f32; /// Returns the largest integer less than or equal to an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::floor`](../../std/primitive.f64.html#method.floor) pub fn floorf64(x: f64) -> f64; /// Returns the smallest integer greater than or equal to an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::ceil`](../../std/primitive.f32.html#method.ceil) pub fn ceilf32(x: f32) -> f32; /// Returns the smallest integer greater than or equal to an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::ceil`](../../std/primitive.f64.html#method.ceil) pub fn ceilf64(x: f64) -> f64; /// Returns the integer part of an `f32`. + /// /// The stabilized version of this intrinsic is /// [`std::f32::trunc`](../../std/primitive.f32.html#method.trunc) pub fn truncf32(x: f32) -> f32; /// Returns the integer part of an `f64`. + /// /// The stabilized version of this intrinsic is /// [`std::f64::trunc`](../../std/primitive.f64.html#method.trunc) pub fn truncf64(x: f64) -> f64; @@ -1409,10 +1532,12 @@ extern "rust-intrinsic" { pub fn nearbyintf64(x: f64) -> f64; /// Returns the nearest integer to an `f32`. Rounds half-way cases away from zero. + /// /// The stabilized version of this intrinsic is /// [`std::f32::round`](../../std/primitive.f32.html#method.round) pub fn roundf32(x: f32) -> f32; /// Returns the nearest integer to an `f64`. Rounds half-way cases away from zero. + /// /// The stabilized version of this intrinsic is /// [`std::f64::round`](../../std/primitive.f64.html#method.round) pub fn roundf64(x: f64) -> f64; @@ -1443,6 +1568,7 @@ extern "rust-intrinsic" { pub fn float_to_int_approx_unchecked(value: Float) -> Int; /// Returns the number of bits set in an integer type `T` + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `count_ones` method. For example, /// [`std::u32::count_ones`](../../std/primitive.u32.html#method.count_ones) @@ -1450,6 +1576,7 @@ extern "rust-intrinsic" { pub fn ctpop(x: T) -> T; /// Returns the number of leading unset bits (zeroes) in an integer type `T`. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `leading_zeros` method. For example, /// [`std::u32::leading_zeros`](../../std/primitive.u32.html#method.leading_zeros) @@ -1498,6 +1625,7 @@ extern "rust-intrinsic" { pub fn ctlz_nonzero(x: T) -> T; /// Returns the number of trailing unset bits (zeroes) in an integer type `T`. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `trailing_zeros` method. For example, /// [`std::u32::trailing_zeros`](../../std/primitive.u32.html#method.trailing_zeros) @@ -1546,6 +1674,7 @@ extern "rust-intrinsic" { pub fn cttz_nonzero(x: T) -> T; /// Reverses the bytes in an integer type `T`. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `swap_bytes` method. For example, /// [`std::u32::swap_bytes`](../../std/primitive.u32.html#method.swap_bytes) @@ -1553,6 +1682,7 @@ extern "rust-intrinsic" { pub fn bswap(x: T) -> T; /// Reverses the bits in an integer type `T`. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `reverse_bits` method. For example, /// [`std::u32::reverse_bits`](../../std/primitive.u32.html#method.reverse_bits) @@ -1560,6 +1690,7 @@ extern "rust-intrinsic" { pub fn bitreverse(x: T) -> T; /// Performs checked integer addition. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, /// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add) @@ -1567,6 +1698,7 @@ extern "rust-intrinsic" { pub fn add_with_overflow(x: T, y: T) -> (T, bool); /// Performs checked integer subtraction + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_sub` method. For example, /// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub) @@ -1574,6 +1706,7 @@ extern "rust-intrinsic" { pub fn sub_with_overflow(x: T, y: T) -> (T, bool); /// Performs checked integer multiplication + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_mul` method. For example, /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul) @@ -1585,7 +1718,7 @@ extern "rust-intrinsic" { pub fn exact_div(x: T, y: T) -> T; /// Performs an unchecked division, resulting in undefined behavior - /// where y = 0 or x = `T::min_value()` and y = -1. + /// where y = 0 or x = `T::min_value()` and y = -1 /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `checked_div` method. For example, @@ -1603,6 +1736,7 @@ extern "rust-intrinsic" { /// Performs an unchecked left shift, resulting in undefined behavior when /// y < 0 or y >= N, where N is the width of T in bits. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_shl` method. For example, /// [`std::u32::wrapping_shl`](../../std/primitive.u32.html#method.wrapping_shl) @@ -1610,6 +1744,7 @@ extern "rust-intrinsic" { pub fn unchecked_shl(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// y < 0 or y >= N, where N is the width of T in bits. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `wrapping_shr` method. For example, /// [`std::u32::wrapping_shr`](../../std/primitive.u32.html#method.wrapping_shr) @@ -1632,6 +1767,7 @@ extern "rust-intrinsic" { pub fn unchecked_mul(x: T, y: T) -> T; /// Performs rotate left. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_left` method. For example, /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left) @@ -1639,6 +1775,7 @@ extern "rust-intrinsic" { pub fn rotate_left(x: T, y: T) -> T; /// Performs rotate right. + /// /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `rotate_right` method. For example, /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right) @@ -1646,18 +1783,21 @@ extern "rust-intrinsic" { pub fn rotate_right(x: T, y: T) -> T; /// Returns (a + b) mod 2N, 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) #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, 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) #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, 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) @@ -1665,12 +1805,14 @@ extern "rust-intrinsic" { pub fn wrapping_mul(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, /// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add) #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")] pub fn saturating_add(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_sub` method. For example, /// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub) @@ -1679,6 +1821,7 @@ extern "rust-intrinsic" { /// Returns the value of the discriminant for the variant in 'v', /// cast to a `u64`; if `T` has no discriminant, returns 0. + /// /// The stabilized version of this intrinsic is /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html) pub fn discriminant_value(v: &T) -> u64; From 768470b901eb9b8a06ccc56d3f85d18dd7ac6b69 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 31 Jan 2020 21:49:00 +0100 Subject: [PATCH 0057/1250] Fix mistake in atomic comparaison docs --- src/libcore/intrinsics.rs | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 571ef2389a9..bb8b3eae2d9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -612,7 +612,7 @@ extern "rust-intrinsic" { /// [`AtomicBool::fetch_xor`](../../std/sync/atomic/struct.AtomicBool.html#method.fetch_xor). pub fn atomic_xor_relaxed(dst: *mut T, src: T) -> T; - /// Maximum with the current value using a sized comparison. + /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing @@ -620,7 +620,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max(dst: *mut T, src: T) -> T; - /// Maximum with the current value using a sized comparison. + /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing @@ -628,7 +628,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_acq(dst: *mut T, src: T) -> T; - /// Maximum with the current value using a sized comparison. + /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing @@ -636,7 +636,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_rel(dst: *mut T, src: T) -> T; - /// Maximum with the current value using a sized comparison. + /// Maximum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_max` method by passing @@ -653,7 +653,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_max`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_max). pub fn atomic_max_relaxed(dst: *mut T, src: T) -> T; - /// Minimum with the current value using a sized comparison. + /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing @@ -661,7 +661,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min(dst: *mut T, src: T) -> T; - /// Minimum with the current value using a sized comparison. + /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing @@ -669,7 +669,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acq(dst: *mut T, src: T) -> T; - /// Minimum with the current value using a sized comparison. + /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing @@ -677,7 +677,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_rel(dst: *mut T, src: T) -> T; - /// Minimum with the current value using a sized comparison. + /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing @@ -685,7 +685,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_acqrel(dst: *mut T, src: T) -> T; - /// Minimum with the current value using a sized comparison. + /// Minimum with the current value using a signed comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` signed integer types via the `fetch_min` method by passing @@ -694,7 +694,7 @@ extern "rust-intrinsic" { /// [`AtomicI32::fetch_min`](../../std/sync/atomic/struct.AtomicI32.html#method.fetch_min). pub fn atomic_min_relaxed(dst: *mut T, src: T) -> T; - /// Minimum with the current value using an unsized comparison. + /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing @@ -702,7 +702,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin(dst: *mut T, src: T) -> T; - /// Minimum with the current value using an unsized comparison. + /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing @@ -710,7 +710,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acq(dst: *mut T, src: T) -> T; - /// Minimum with the current value using an unsized comparison. + /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing @@ -718,7 +718,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_rel(dst: *mut T, src: T) -> T; - /// Minimum with the current value using an unsized comparison. + /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing @@ -726,7 +726,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_acqrel(dst: *mut T, src: T) -> T; - /// Minimum with the current value using an unsized comparison. + /// Minimum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_min` method by passing @@ -735,7 +735,7 @@ extern "rust-intrinsic" { /// [`AtomicU32::fetch_min`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_min). pub fn atomic_umin_relaxed(dst: *mut T, src: T) -> T; - /// Maximum with the current value using an unsized comparison. + /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing @@ -743,7 +743,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax(dst: *mut T, src: T) -> T; - /// Maximum with the current value using an unsized comparison. + /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing @@ -751,7 +751,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acq(dst: *mut T, src: T) -> T; - /// Maximum with the current value using an unsized comparison. + /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing @@ -759,7 +759,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_rel(dst: *mut T, src: T) -> T; - /// Maximum with the current value using an unsized comparison. + /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing @@ -767,7 +767,7 @@ extern "rust-intrinsic" { /// as the `order`. For example, /// [`AtomicU32::fetch_max`](../../std/sync/atomic/struct.AtomicU32.html#method.fetch_max). pub fn atomic_umax_acqrel(dst: *mut T, src: T) -> T; - /// Maximum with the current value using an unsized comparison. + /// Maximum with the current value using an unsigned comparison. /// /// The stabilized version of this intrinsic is available on the /// `std::sync::atomic` unsigned integer types via the `fetch_max` method by passing From d53ee472eb96da448ffd6392678ff3eeb1e87a37 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 31 Jan 2020 21:53:30 +0100 Subject: [PATCH 0058/1250] Remove references to `wrapping` methods --- src/libcore/intrinsics.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index bb8b3eae2d9..f38e0d64862 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1738,16 +1738,16 @@ extern "rust-intrinsic" { /// y < 0 or y >= N, where N is the width of T in bits. /// /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_shl` method. For example, - /// [`std::u32::wrapping_shl`](../../std/primitive.u32.html#method.wrapping_shl) + /// primitives via the `checked_shl` method. For example, + /// [`std::u32::checked_shl`](../../std/primitive.u32.html#method.checked_shl) #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shl(x: T, y: T) -> T; /// Performs an unchecked right shift, resulting in undefined behavior when /// y < 0 or y >= N, where N is the width of T in bits. /// /// The stabilized versions of this intrinsic are available on the integer - /// primitives via the `wrapping_shr` method. For example, - /// [`std::u32::wrapping_shr`](../../std/primitive.u32.html#method.wrapping_shr) + /// primitives via the `checked_shr` method. For example, + /// [`std::u32::checked_shr`](../../std/primitive.u32.html#method.checked_shr) #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")] pub fn unchecked_shr(x: T, y: T) -> T; @@ -1785,22 +1785,22 @@ extern "rust-intrinsic" { /// Returns (a + b) mod 2N, 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) + /// primitives via the `checked_add` method. For example, + /// [`std::u32::checked_add`](../../std/primitive.u32.html#method.checked_add) #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_add(a: T, b: T) -> T; /// Returns (a - b) mod 2N, 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) + /// primitives via the `checked_sub` method. For example, + /// [`std::u32::checked_sub`](../../std/primitive.u32.html#method.checked_sub) #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_sub(a: T, b: T) -> T; /// Returns (a * b) mod 2N, 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) + /// primitives via the `checked_mul` method. For example, + /// [`std::u32::checked_mul`](../../std/primitive.u32.html#method.checked_mul) #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")] pub fn wrapping_mul(a: T, b: T) -> T; From b22d3703a873adb097b89ea9285d4d7a97ecd67d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 31 Jan 2020 22:03:59 +0100 Subject: [PATCH 0059/1250] Document stabilized versions of atomic singlethreaded fences --- src/libcore/intrinsics.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index f38e0d64862..3d92284f947 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -851,6 +851,12 @@ extern "rust-intrinsic" { /// compiler, but no instructions will be emitted for it. This is /// appropriate for operations on the same thread that may be preempted, /// such as when interacting with signal handlers. + /// + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) + /// by passing + /// [`Ordering::SeqCst`](../../std/sync/atomic/enum.Ordering.html#variant.SeqCst) + /// as the `order`. pub fn atomic_singlethreadfence(); /// A compiler-only memory barrier. /// @@ -858,6 +864,12 @@ extern "rust-intrinsic" { /// compiler, but no instructions will be emitted for it. This is /// appropriate for operations on the same thread that may be preempted, /// such as when interacting with signal handlers. + /// + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) + /// by passing + /// [`Ordering::Acquire`](../../std/sync/atomic/enum.Ordering.html#variant.Acquire) + /// as the `order`. pub fn atomic_singlethreadfence_acq(); /// A compiler-only memory barrier. /// @@ -865,6 +877,12 @@ extern "rust-intrinsic" { /// compiler, but no instructions will be emitted for it. This is /// appropriate for operations on the same thread that may be preempted, /// such as when interacting with signal handlers. + /// + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) + /// by passing + /// [`Ordering::Release`](../../std/sync/atomic/enum.Ordering.html#variant.Release) + /// as the `order`. pub fn atomic_singlethreadfence_rel(); /// A compiler-only memory barrier. /// @@ -872,6 +890,12 @@ extern "rust-intrinsic" { /// compiler, but no instructions will be emitted for it. This is /// appropriate for operations on the same thread that may be preempted, /// such as when interacting with signal handlers. + /// + /// The stabilized version of this intrinsic is available in + /// [`std::sync::atomic::compiler_fence`](../../std/sync/atomic/fn.compiler_fence.html) + /// by passing + /// [`Ordering::AcqRel`](../../std/sync/atomic/enum.Ordering.html#variant.AcqRel) + /// as the `order`. pub fn atomic_singlethreadfence_acqrel(); /// Magic intrinsic that derives its meaning from attributes From 77ab0d091e32ac9ec4154bba1727fc3937975d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 31 Jan 2020 04:00:03 +0100 Subject: [PATCH 0060/1250] Construct query job latches on-demand --- src/librustc/ty/context.rs | 4 +- src/librustc/ty/query/job.rs | 292 +++++++++++++++++++----------- src/librustc/ty/query/mod.rs | 3 +- src/librustc/ty/query/plumbing.rs | 127 ++++++++----- 4 files changed, 275 insertions(+), 151 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index f2ad01b3d59..21640996d5d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1608,7 +1608,7 @@ pub mod tls { use crate::dep_graph::TaskDeps; use crate::ty::query; - use rustc_data_structures::sync::{self, Lock, Lrc}; + use rustc_data_structures::sync::{self, Lock}; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::OnDrop; use rustc_errors::Diagnostic; @@ -1633,7 +1633,7 @@ pub mod tls { /// The current query job, if any. This is updated by `JobOwner::start` in /// `ty::query::plumbing` when executing a query. - pub query: Option>>, + pub query: Option, /// Where to store diagnostics for the current query job, if any. /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index 393125f278c..d440b5150b0 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -3,11 +3,11 @@ use crate::ty::query::plumbing::CycleError; use crate::ty::query::Query; use crate::ty::tls; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::fx::FxHashMap; use rustc_span::Span; -#[cfg(not(parallel_compiler))] -use std::ptr; +use std::marker::PhantomData; +use std::num::NonZeroUsize; #[cfg(parallel_compiler)] use { @@ -15,6 +15,7 @@ use { rustc_data_structures::fx::FxHashSet, rustc_data_structures::stable_hasher::{HashStable, StableHasher}, rustc_data_structures::sync::Lock, + rustc_data_structures::sync::Lrc, rustc_data_structures::{jobserver, OnDrop}, rustc_rayon_core as rayon_core, rustc_span::DUMMY_SP, @@ -30,61 +31,119 @@ pub struct QueryInfo<'tcx> { pub query: Query<'tcx>, } -/// Representss an object representing an active query job. -pub struct QueryJob<'tcx> { +type QueryMap<'tcx> = FxHashMap>; + +/// A value uniquely identifiying an active query job. +/// This value is created from a stack pointer in `get_query` and `force_query` +/// which is alive while the query executes. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct QueryToken(NonZeroUsize); + +impl QueryToken { + pub fn from(v: &T) -> Self { + QueryToken(NonZeroUsize::new(v as *const T as usize).unwrap()) + } + + fn query<'tcx>(self, map: &QueryMap<'tcx>) -> Query<'tcx> { + map.get(&self).unwrap().info.query.clone() + } + + #[cfg(parallel_compiler)] + fn span(self, map: &QueryMap<'_>) -> Span { + map.get(&self).unwrap().job.span + } + + #[cfg(parallel_compiler)] + fn parent(self, map: &QueryMap<'_>) -> Option { + map.get(&self).unwrap().job.parent + } + + #[cfg(parallel_compiler)] + fn latch<'a, 'tcx>(self, map: &'a QueryMap<'tcx>) -> Option<&'a QueryLatch<'tcx>> { + map.get(&self).unwrap().job.latch.as_ref() + } +} + +pub struct QueryJobInfo<'tcx> { pub info: QueryInfo<'tcx>, + pub job: QueryJob<'tcx>, +} + +/// Represents an active query job. +#[derive(Clone)] +pub struct QueryJob<'tcx> { + pub token: QueryToken, + + /// The span corresponding to the reason for which this query was required. + pub span: Span, /// The parent query job which created this job and is implicitly waiting on it. - pub parent: Option>>, + pub parent: Option, /// The latch that is used to wait on this job. #[cfg(parallel_compiler)] - latch: QueryLatch<'tcx>, + latch: Option>, + + dummy: PhantomData>, } impl<'tcx> QueryJob<'tcx> { /// Creates a new query job. - pub fn new(info: QueryInfo<'tcx>, parent: Option>>) -> Self { + pub fn new(token: QueryToken, span: Span, parent: Option) -> Self { QueryJob { - info, + token, + span, parent, #[cfg(parallel_compiler)] - latch: QueryLatch::new(), + latch: None, + dummy: PhantomData, } } - /// Awaits for the query job to complete. #[cfg(parallel_compiler)] - pub(super) fn r#await(&self, tcx: TyCtxt<'tcx>, span: Span) -> Result<(), CycleError<'tcx>> { - tls::with_related_context(tcx, move |icx| { - let waiter = Lrc::new(QueryWaiter { - query: icx.query.clone(), - span, - cycle: Lock::new(None), - condvar: Condvar::new(), - }); - self.latch.r#await(&waiter); - // FIXME: Get rid of this lock. We have ownership of the QueryWaiter - // although another thread may still have a Lrc reference so we cannot - // use Lrc::get_mut - let mut cycle = waiter.cycle.lock(); - match cycle.take() { - None => Ok(()), - Some(cycle) => Err(cycle), - } - }) + pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { + if self.latch.is_none() { + self.latch = Some(QueryLatch::new()); + } + self.latch.as_ref().unwrap().clone() } #[cfg(not(parallel_compiler))] + pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { + QueryLatch { token: self.token, dummy: PhantomData } + } + + /// Signals to waiters that the query is complete. + /// + /// This does nothing for single threaded rustc, + /// as there are no concurrent jobs which could be waiting on us + pub fn signal_complete(self) { + #[cfg(parallel_compiler)] + self.latch.map(|latch| latch.set()); + } +} + +#[cfg(not(parallel_compiler))] +#[derive(Clone)] +pub(super) struct QueryLatch<'tcx> { + token: QueryToken, + dummy: PhantomData<&'tcx ()>, +} + +#[cfg(not(parallel_compiler))] +impl<'tcx> QueryLatch<'tcx> { pub(super) fn find_cycle_in_stack(&self, tcx: TyCtxt<'tcx>, span: Span) -> CycleError<'tcx> { + let query_map = tcx.queries.try_collect_active_jobs().unwrap(); + // Get the current executing query (waiter) and find the waitee amongst its parents - let mut current_job = tls::with_related_context(tcx, |icx| icx.query.clone()); + let mut current_job = tls::with_related_context(tcx, |icx| icx.query); let mut cycle = Vec::new(); while let Some(job) = current_job { - cycle.push(job.info.clone()); + let info = query_map.get(&job).unwrap(); + cycle.push(info.info.clone()); - if ptr::eq(&*job, self) { + if job == self.token { cycle.reverse(); // This is the end of the cycle @@ -93,35 +152,24 @@ impl<'tcx> QueryJob<'tcx> { // Replace it with the span which caused the cycle to form cycle[0].span = span; // Find out why the cycle itself was used - let usage = - job.parent.as_ref().map(|parent| (job.info.span, parent.info.query.clone())); + let usage = info + .job + .parent + .as_ref() + .map(|parent| (info.info.span, parent.query(&query_map))); return CycleError { usage, cycle }; } - current_job = job.parent.clone(); + current_job = info.job.parent.clone(); } panic!("did not find a cycle") } - - /// Signals to waiters that the query is complete. - /// - /// This does nothing for single threaded rustc, - /// as there are no concurrent jobs which could be waiting on us - pub fn signal_complete(&self) { - #[cfg(parallel_compiler)] - self.latch.set(); - } - - #[cfg(parallel_compiler)] - fn as_ptr(&self) -> *const QueryJob<'tcx> { - self as *const _ - } } #[cfg(parallel_compiler)] struct QueryWaiter<'tcx> { - query: Option>>, + query: Option, condvar: Condvar, span: Span, cycle: Lock>>, @@ -142,18 +190,43 @@ struct QueryLatchInfo<'tcx> { } #[cfg(parallel_compiler)] -struct QueryLatch<'tcx> { - info: Mutex>, +#[derive(Clone)] +pub(super) struct QueryLatch<'tcx> { + info: Lrc>>, } #[cfg(parallel_compiler)] impl<'tcx> QueryLatch<'tcx> { fn new() -> Self { - QueryLatch { info: Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() }) } + QueryLatch { + info: Lrc::new(Mutex::new(QueryLatchInfo { complete: false, waiters: Vec::new() })), + } + } + + /// Awaits for the query job to complete. + #[cfg(parallel_compiler)] + pub(super) fn wait_on(&self, tcx: TyCtxt<'tcx>, span: Span) -> Result<(), CycleError<'tcx>> { + tls::with_related_context(tcx, move |icx| { + let waiter = Lrc::new(QueryWaiter { + query: icx.query, + span, + cycle: Lock::new(None), + condvar: Condvar::new(), + }); + self.wait_on_inner(&waiter); + // FIXME: Get rid of this lock. We have ownership of the QueryWaiter + // although another thread may still have a Lrc reference so we cannot + // use Lrc::get_mut + let mut cycle = waiter.cycle.lock(); + match cycle.take() { + None => Ok(()), + Some(cycle) => Err(cycle), + } + }) } /// Awaits the caller on this latch by blocking the current thread. - fn r#await(&self, waiter: &Lrc>) { + fn wait_on_inner(&self, waiter: &Lrc>) { let mut info = self.info.lock(); if !info.complete { // We push the waiter on to the `waiters` list. It can be accessed inside @@ -197,7 +270,7 @@ impl<'tcx> QueryLatch<'tcx> { /// A resumable waiter of a query. The usize is the index into waiters in the query's latch #[cfg(parallel_compiler)] -type Waiter<'tcx> = (Lrc>, usize); +type Waiter = (QueryToken, usize); /// Visits all the non-resumable and resumable waiters of a query. /// Only waiters in a query are visited. @@ -209,26 +282,33 @@ type Waiter<'tcx> = (Lrc>, usize); /// required information to resume the waiter. /// If all `visit` calls returns None, this function also returns None. #[cfg(parallel_compiler)] -fn visit_waiters<'tcx, F>(query: Lrc>, mut visit: F) -> Option>> +fn visit_waiters<'tcx, F>( + query_map: &QueryMap<'tcx>, + query: QueryToken, + mut visit: F, +) -> Option> where - F: FnMut(Span, Lrc>) -> Option>>, + F: FnMut(Span, QueryToken) -> Option>, { // Visit the parent query which is a non-resumable waiter since it's on the same stack - if let Some(ref parent) = query.parent { - if let Some(cycle) = visit(query.info.span, parent.clone()) { + if let Some(parent) = query.parent(query_map) { + if let Some(cycle) = visit(query.span(query_map), parent) { return Some(cycle); } } // Visit the explicit waiters which use condvars and are resumable - for (i, waiter) in query.latch.info.lock().waiters.iter().enumerate() { - if let Some(ref waiter_query) = waiter.query { - if visit(waiter.span, waiter_query.clone()).is_some() { - // Return a value which indicates that this waiter can be resumed - return Some(Some((query.clone(), i))); + if let Some(latch) = query.latch(query_map) { + for (i, waiter) in latch.info.lock().waiters.iter().enumerate() { + if let Some(waiter_query) = waiter.query { + if visit(waiter.span, waiter_query).is_some() { + // Return a value which indicates that this waiter can be resumed + return Some(Some((query, i))); + } } } } + None } @@ -238,13 +318,14 @@ where /// the cycle. #[cfg(parallel_compiler)] fn cycle_check<'tcx>( - query: Lrc>, + query_map: &QueryMap<'tcx>, + query: QueryToken, span: Span, - stack: &mut Vec<(Span, Lrc>)>, - visited: &mut FxHashSet<*const QueryJob<'tcx>>, -) -> Option>> { - if !visited.insert(query.as_ptr()) { - return if let Some(p) = stack.iter().position(|q| q.1.as_ptr() == query.as_ptr()) { + stack: &mut Vec<(Span, QueryToken)>, + visited: &mut FxHashSet, +) -> Option> { + if !visited.insert(query) { + return if let Some(p) = stack.iter().position(|q| q.1 == query) { // We detected a query cycle, fix up the initial span and return Some // Remove previous stack entries @@ -258,10 +339,12 @@ fn cycle_check<'tcx>( } // Query marked as visited is added it to the stack - stack.push((span, query.clone())); + stack.push((span, query)); // Visit all the waiters - let r = visit_waiters(query, |span, successor| cycle_check(successor, span, stack, visited)); + let r = visit_waiters(query_map, query, |span, successor| { + cycle_check(query_map, successor, span, stack, visited) + }); // Remove the entry in our stack if we didn't find a cycle if r.is_none() { @@ -276,26 +359,30 @@ fn cycle_check<'tcx>( /// This is achieved with a depth first search. #[cfg(parallel_compiler)] fn connected_to_root<'tcx>( - query: Lrc>, - visited: &mut FxHashSet<*const QueryJob<'tcx>>, + query_map: &QueryMap<'tcx>, + query: QueryToken, + visited: &mut FxHashSet, ) -> bool { // We already visited this or we're deliberately ignoring it - if !visited.insert(query.as_ptr()) { + if !visited.insert(query) { return false; } // This query is connected to the root (it has no query parent), return true - if query.parent.is_none() { + if query.parent(query_map).is_none() { return true; } - visit_waiters(query, |_, successor| connected_to_root(successor, visited).then_some(None)) - .is_some() + visit_waiters(query_map, query, |_, successor| { + connected_to_root(query_map, successor, visited).then_some(None) + }) + .is_some() } // Deterministically pick an query from a list #[cfg(parallel_compiler)] -fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc>)>( +fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryToken)>( + query_map: &QueryMap<'tcx>, tcx: TyCtxt<'tcx>, queries: &'a [T], f: F, @@ -308,7 +395,7 @@ fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc>)>( .min_by_key(|v| { let (span, query) = f(v); let mut stable_hasher = StableHasher::new(); - query.info.query.hash_stable(&mut hcx, &mut stable_hasher); + query.query(query_map).hash_stable(&mut hcx, &mut stable_hasher); // Prefer entry points which have valid spans for nicer error messages // We add an integer to the tuple ensuring that entry points // with valid spans are picked first @@ -325,14 +412,17 @@ fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, Lrc>)>( /// the function returns false. #[cfg(parallel_compiler)] fn remove_cycle<'tcx>( - jobs: &mut Vec>>, + query_map: &QueryMap<'tcx>, + jobs: &mut Vec, wakelist: &mut Vec>>, tcx: TyCtxt<'tcx>, ) -> bool { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); // Look for a cycle starting with the last query in `jobs` - if let Some(waiter) = cycle_check(jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) { + if let Some(waiter) = + cycle_check(query_map, jobs.pop().unwrap(), DUMMY_SP, &mut stack, &mut visited) + { // The stack is a vector of pairs of spans and queries; reverse it so that // the earlier entries require later entries let (mut spans, queries): (Vec<_>, Vec<_>) = stack.into_iter().rev().unzip(); @@ -345,27 +435,25 @@ fn remove_cycle<'tcx>( // Remove the queries in our cycle from the list of jobs to look at for r in &stack { - if let Some(pos) = jobs.iter().position(|j| j.as_ptr() == r.1.as_ptr()) { - jobs.remove(pos); - } + jobs.remove_item(&r.1); } // Find the queries in the cycle which are // connected to queries outside the cycle let entry_points = stack .iter() - .filter_map(|(span, query)| { - if query.parent.is_none() { + .filter_map(|&(span, query)| { + if query.parent(query_map).is_none() { // This query is connected to the root (it has no query parent) - Some((*span, query.clone(), None)) + Some((span, query, None)) } else { let mut waiters = Vec::new(); // Find all the direct waiters who lead to the root - visit_waiters(query.clone(), |span, waiter| { + visit_waiters(query_map, query, |span, waiter| { // Mark all the other queries in the cycle as already visited - let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1.as_ptr())); + let mut visited = FxHashSet::from_iter(stack.iter().map(|q| q.1)); - if connected_to_root(waiter.clone(), &mut visited) { + if connected_to_root(query_map, waiter, &mut visited) { waiters.push((span, waiter)); } @@ -375,31 +463,30 @@ fn remove_cycle<'tcx>( None } else { // Deterministically pick one of the waiters to show to the user - let waiter = pick_query(tcx, &waiters, |s| s.clone()).clone(); - Some((*span, query.clone(), Some(waiter))) + let waiter = *pick_query(query_map, tcx, &waiters, |s| *s); + Some((span, query, Some(waiter))) } } }) - .collect::>, Option<(Span, Lrc>)>)>>(); + .collect::)>>(); // Deterministically pick an entry point - let (_, entry_point, usage) = pick_query(tcx, &entry_points, |e| (e.0, e.1.clone())); + let (_, entry_point, usage) = pick_query(query_map, tcx, &entry_points, |e| (e.0, e.1)); // Shift the stack so that our entry point is first - let entry_point_pos = - stack.iter().position(|(_, query)| query.as_ptr() == entry_point.as_ptr()); + let entry_point_pos = stack.iter().position(|(_, query)| query == entry_point); if let Some(pos) = entry_point_pos { stack.rotate_left(pos); } - let usage = usage.as_ref().map(|(span, query)| (*span, query.info.query.clone())); + let usage = usage.as_ref().map(|(span, query)| (*span, query.query(query_map))); // Create the cycle error let error = CycleError { usage, cycle: stack .iter() - .map(|&(s, ref q)| QueryInfo { span: s, query: q.info.query.clone() }) + .map(|&(s, ref q)| QueryInfo { span: s, query: q.query(query_map) }) .collect(), }; @@ -408,7 +495,7 @@ fn remove_cycle<'tcx>( let (waitee_query, waiter_idx) = waiter.unwrap(); // Extract the waiter we want to resume - let waiter = waitee_query.latch.extract_waiter(waiter_idx); + let waiter = waitee_query.latch(query_map).unwrap().extract_waiter(waiter_idx); // Set the cycle error so it will be picked up when resumed *waiter.cycle.lock() = Some(error); @@ -460,12 +547,13 @@ fn deadlock(tcx: TyCtxt<'_>, registry: &rayon_core::Registry) { }); let mut wakelist = Vec::new(); - let mut jobs: Vec<_> = tcx.queries.collect_active_jobs(); + let query_map = tcx.queries.try_collect_active_jobs().unwrap(); + let mut jobs: Vec = query_map.keys().cloned().collect(); let mut found_cycle = false; while jobs.len() > 0 { - if remove_cycle(&mut jobs, &mut wakelist, tcx) { + if remove_cycle(&query_map, &mut jobs, &mut wakelist, tcx) { found_cycle = true; } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index e7b95af103c..ade8cdbb3e5 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -66,7 +66,8 @@ pub use self::plumbing::{force_from_dep_node, CycleError}; mod job; #[cfg(parallel_compiler)] pub use self::job::handle_deadlock; -pub use self::job::{QueryInfo, QueryJob}; +use self::job::QueryJobInfo; +pub use self::job::{QueryInfo, QueryJob, QueryToken}; mod keys; use self::keys::Key; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 6d9fff351e9..fdb86c0bede 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -4,7 +4,7 @@ use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ty::query::config::{QueryConfig, QueryDescription}; -use crate::ty::query::job::{QueryInfo, QueryJob}; +use crate::ty::query::job::{QueryInfo, QueryJob, QueryToken}; use crate::ty::query::Query; use crate::ty::tls; use crate::ty::{self, TyCtxt}; @@ -15,7 +15,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHasher}; #[cfg(parallel_compiler)] use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::sharded::Sharded; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::Lock; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level}; use rustc_span::source_map::DUMMY_SP; @@ -46,9 +46,9 @@ impl QueryValue { /// Indicates the state of a query for a given key in a query map. pub(super) enum QueryResult<'tcx> { /// An already executing query. The query job can be used to await for its completion. - Started(Lrc>), + Started(QueryJob<'tcx>), - /// The query panicked. Queries trying to wait on this will raise a fatal error or + /// The query panicked. Queries trying to wait on this will raise a fatal error which will /// silently panic. Poisoned, } @@ -69,7 +69,7 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { cache: &'a Sharded>, key: Q::Key, - job: Lrc>, + token: QueryToken, } impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { @@ -81,7 +81,12 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> { + pub(super) fn try_get( + tcx: TyCtxt<'tcx>, + span: Span, + key: &Q::Key, + token: QueryToken, + ) -> TryGetJob<'a, 'tcx, Q> { // Handling the `query_blocked_prof_timer` is a bit weird because of the // control flow in this function: Blocking is implemented by // awaiting a running job and, once that is done, entering the loop below @@ -127,10 +132,10 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { return TryGetJob::JobCompleted(result); } - let job = match lock.active.entry((*key).clone()) { - Entry::Occupied(entry) => { - match *entry.get() { - QueryResult::Started(ref job) => { + let latch = match lock.active.entry((*key).clone()) { + Entry::Occupied(mut entry) => { + match entry.get_mut() { + QueryResult::Started(job) => { // For parallel queries, we'll block and wait until the query running // in another thread has completed. Record how long we wait in the // self-profiler. @@ -139,7 +144,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { query_blocked_prof_timer = Some(tcx.prof.query_blocked()); } - job.clone() + job.latch() } QueryResult::Poisoned => FatalError.raise(), } @@ -147,12 +152,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { Entry::Vacant(entry) => { // No job entry for this query. Return a new one to be started later. return tls::with_related_context(tcx, |icx| { - // Create the `parent` variable before `info`. This allows LLVM - // to elide the move of `info` - let parent = icx.query.clone(); - let info = QueryInfo { span, query: Q::query(key.clone()) }; - let job = Lrc::new(QueryJob::new(info, parent)); - let owner = JobOwner { cache, job: job.clone(), key: (*key).clone() }; + let job = QueryJob::new(token, span, icx.query); + let owner = JobOwner { cache, token, key: (*key).clone() }; entry.insert(QueryResult::Started(job)); TryGetJob::NotYetStarted(owner) }); @@ -164,14 +165,14 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { // so we just return the error. #[cfg(not(parallel_compiler))] return TryGetJob::Cycle(cold_path(|| { - Q::handle_cycle_error(tcx, job.find_cycle_in_stack(tcx, span)) + Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span)) })); // With parallel queries we might just have to wait on some other // thread. #[cfg(parallel_compiler)] { - let result = job.r#await(tcx, span); + let result = latch.wait_on(tcx, span); if let Err(cycle) = result { return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); @@ -186,18 +187,21 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; - let job = unsafe { ptr::read(&self.job) }; let cache = self.cache; // Forget ourself so our destructor won't poison the query mem::forget(self); let value = QueryValue::new(result.clone(), dep_node_index); - { + let job = { let mut lock = cache.get_shard_by_value(&key).lock(); - lock.active.remove(&key); + let job = match lock.active.remove(&key).unwrap() { + QueryResult::Started(job) => job, + QueryResult::Poisoned => panic!(), + }; lock.results.insert(key, value); - } + job + }; job.signal_complete(); } @@ -219,10 +223,18 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { fn drop(&mut self) { // Poison the query so jobs waiting on it panic. let shard = self.cache.get_shard_by_value(&self.key); - shard.lock().active.insert(self.key.clone(), QueryResult::Poisoned); + let job = { + let mut shard = shard.lock(); + let job = match shard.active.remove(&self.key).unwrap() { + QueryResult::Started(job) => job, + QueryResult::Poisoned => panic!(), + }; + shard.active.insert(self.key.clone(), QueryResult::Poisoned); + job + }; // Also signal the completion of the job, so waiters // will continue execution. - self.job.signal_complete(); + job.signal_complete(); } } @@ -254,7 +266,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub(super) fn start_query( self, - job: Lrc>, + token: QueryToken, diagnostics: Option<&Lock>>, compute: F, ) -> R @@ -268,7 +280,7 @@ impl<'tcx> TyCtxt<'tcx> { // Update the `ImplicitCtxt` to point to our new query job. let new_icx = tls::ImplicitCtxt { tcx: self, - query: Some(job), + query: Some(token), diagnostics, layout_depth: current_icx.layout_depth, task_deps: current_icx.task_deps, @@ -335,23 +347,31 @@ impl<'tcx> TyCtxt<'tcx> { // state if it was responsible for triggering the panic. tls::with_context_opt(|icx| { if let Some(icx) = icx { - let mut current_query = icx.query.clone(); + let query_map = icx.tcx.queries.try_collect_active_jobs(); + + let mut current_query = icx.query; let mut i = 0; while let Some(query) = current_query { + let query_info = + if let Some(info) = query_map.as_ref().and_then(|map| map.get(&query)) { + info + } else { + break; + }; let mut diag = Diagnostic::new( Level::FailureNote, &format!( "#{} [{}] {}", i, - query.info.query.name(), - query.info.query.describe(icx.tcx) + query_info.info.query.name(), + query_info.info.query.describe(icx.tcx) ), ); - diag.span = icx.tcx.sess.source_map().def_span(query.info.span).into(); + diag.span = icx.tcx.sess.source_map().def_span(query_info.info.span).into(); handler.force_print_diagnostic(diag); - current_query = query.parent.clone(); + current_query = query_info.job.parent; i += 1; } } @@ -364,7 +384,12 @@ impl<'tcx> TyCtxt<'tcx> { pub(super) fn get_query>(self, span: Span, key: Q::Key) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - let job = match JobOwner::try_get(self, span, &key) { + // Create a token which uniquely identifies this query amongst the executing queries + // by using a pointer to `key`. `key` is alive until the query completes execution + // which will prevent reuse of the token value. + let token = QueryToken::from(&key); + + let job = match JobOwner::try_get(self, span, &key, token) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, TryGetJob::JobCompleted((v, index)) => { @@ -384,7 +409,7 @@ impl<'tcx> TyCtxt<'tcx> { let prof_timer = self.prof.query_provider(); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - self.start_query(job.job.clone(), diagnostics, |tcx| { + self.start_query(job.token, diagnostics, |tcx| { tcx.dep_graph.with_anon_task(Q::dep_kind(), || Q::compute(tcx, key)) }) }); @@ -410,7 +435,7 @@ impl<'tcx> TyCtxt<'tcx> { // The diagnostics for this query will be // promoted to the current session during // `try_mark_green()`, so we can ignore them here. - let loaded = self.start_query(job.job.clone(), None, |tcx| { + let loaded = self.start_query(job.token, None, |tcx| { let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node); marked.map(|(prev_dep_node_index, dep_node_index)| { ( @@ -544,7 +569,7 @@ impl<'tcx> TyCtxt<'tcx> { let prof_timer = self.prof.query_provider(); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - self.start_query(job.job.clone(), diagnostics, |tcx| { + self.start_query(job.token, diagnostics, |tcx| { if Q::EVAL_ALWAYS { tcx.dep_graph.with_eval_always_task( dep_node, @@ -608,9 +633,14 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(dead_code)] fn force_query>(self, key: Q::Key, span: Span, dep_node: DepNode) { + // Create a token which uniquely identifies this query amongst the executing queries + // by using a pointer to `key`. `key` is alive until the query completes execution + // which will prevent reuse of the token value. + let token = QueryToken::from(&key); + // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let job = match JobOwner::try_get(self, span, &key) { + let job = match JobOwner::try_get(self, span, &key, token) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(_) | TryGetJob::JobCompleted(_) => return, }; @@ -716,24 +746,29 @@ macro_rules! define_queries_inner { } } - #[cfg(parallel_compiler)] - pub fn collect_active_jobs(&self) -> Vec>> { - let mut jobs = Vec::new(); + pub fn try_collect_active_jobs( + &self + ) -> Option>> { + let mut jobs = FxHashMap::default(); - // We use try_lock_shards here since we are only called from the - // deadlock handler, and this shouldn't be locked. $( - let shards = self.$name.try_lock_shards().unwrap(); - jobs.extend(shards.iter().flat_map(|shard| shard.active.values().filter_map(|v| + // We use try_lock_shards here since we are called from the + // deadlock handler, and this shouldn't be locked. + let shards = self.$name.try_lock_shards()?; + jobs.extend(shards.iter().flat_map(|shard| shard.active.iter().filter_map(|(k, v)| if let QueryResult::Started(ref job) = *v { - Some(job.clone()) + let info = QueryInfo { + span: job.span, + query: queries::$name::query(k.clone()) + }; + Some((job.token, QueryJobInfo { info, job: job.clone() })) } else { None } ))); )* - jobs + Some(jobs) } pub fn print_stats(&self) { From 19c1012483fe8fb3c793a6ba83f97d896c6a6c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 11:50:00 +0100 Subject: [PATCH 0061/1250] Use a counter instead of pointers to the stack --- src/librustc/ty/context.rs | 2 +- src/librustc/ty/query/job.rs | 72 +++++++++-------- src/librustc/ty/query/mod.rs | 3 +- src/librustc/ty/query/plumbing.rs | 103 +++++++++++++++--------- src/librustc_data_structures/sharded.rs | 13 ++- 5 files changed, 117 insertions(+), 76 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 21640996d5d..a3541db1291 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1633,7 +1633,7 @@ pub mod tls { /// The current query job, if any. This is updated by `JobOwner::start` in /// `ty::query::plumbing` when executing a query. - pub query: Option, + pub query: Option, /// Where to store diagnostics for the current query job, if any. /// This is updated by `JobOwner::start` in `ty::query::plumbing` when executing a query. diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index d440b5150b0..a3c2bb2f1f5 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -1,3 +1,4 @@ +use crate::dep_graph::DepKind; use crate::ty::context::TyCtxt; use crate::ty::query::plumbing::CycleError; use crate::ty::query::Query; @@ -7,7 +8,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_span::Span; use std::marker::PhantomData; -use std::num::NonZeroUsize; +use std::num::NonZeroU32; #[cfg(parallel_compiler)] use { @@ -31,19 +32,26 @@ pub struct QueryInfo<'tcx> { pub query: Query<'tcx>, } -type QueryMap<'tcx> = FxHashMap>; +type QueryMap<'tcx> = FxHashMap>; + +/// A value uniquely identifiying an active query job within a shard in the query cache. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct QueryShardJobId(pub NonZeroU32); /// A value uniquely identifiying an active query job. -/// This value is created from a stack pointer in `get_query` and `force_query` -/// which is alive while the query executes. #[derive(Copy, Clone, Eq, PartialEq, Hash)] -pub struct QueryToken(NonZeroUsize); +pub struct QueryJobId { + /// Which job within a shard is this + pub job: QueryShardJobId, -impl QueryToken { - pub fn from(v: &T) -> Self { - QueryToken(NonZeroUsize::new(v as *const T as usize).unwrap()) - } + /// In which shard is this job + pub shard: u16, + + /// What kind of query this job is + pub kind: DepKind, +} +impl QueryJobId { fn query<'tcx>(self, map: &QueryMap<'tcx>) -> Query<'tcx> { map.get(&self).unwrap().info.query.clone() } @@ -54,7 +62,7 @@ impl QueryToken { } #[cfg(parallel_compiler)] - fn parent(self, map: &QueryMap<'_>) -> Option { + fn parent(self, map: &QueryMap<'_>) -> Option { map.get(&self).unwrap().job.parent } @@ -72,13 +80,13 @@ pub struct QueryJobInfo<'tcx> { /// Represents an active query job. #[derive(Clone)] pub struct QueryJob<'tcx> { - pub token: QueryToken, + pub id: QueryShardJobId, /// The span corresponding to the reason for which this query was required. pub span: Span, /// The parent query job which created this job and is implicitly waiting on it. - pub parent: Option, + pub parent: Option, /// The latch that is used to wait on this job. #[cfg(parallel_compiler)] @@ -89,9 +97,9 @@ pub struct QueryJob<'tcx> { impl<'tcx> QueryJob<'tcx> { /// Creates a new query job. - pub fn new(token: QueryToken, span: Span, parent: Option) -> Self { + pub fn new(id: QueryShardJobId, span: Span, parent: Option) -> Self { QueryJob { - token, + id, span, parent, #[cfg(parallel_compiler)] @@ -101,7 +109,7 @@ impl<'tcx> QueryJob<'tcx> { } #[cfg(parallel_compiler)] - pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { + pub(super) fn latch(&mut self, _id: QueryJobId) -> QueryLatch<'tcx> { if self.latch.is_none() { self.latch = Some(QueryLatch::new()); } @@ -109,8 +117,8 @@ impl<'tcx> QueryJob<'tcx> { } #[cfg(not(parallel_compiler))] - pub(super) fn latch(&mut self) -> QueryLatch<'tcx> { - QueryLatch { token: self.token, dummy: PhantomData } + pub(super) fn latch(&mut self, id: QueryJobId) -> QueryLatch<'tcx> { + QueryLatch { id, dummy: PhantomData } } /// Signals to waiters that the query is complete. @@ -126,7 +134,7 @@ impl<'tcx> QueryJob<'tcx> { #[cfg(not(parallel_compiler))] #[derive(Clone)] pub(super) struct QueryLatch<'tcx> { - token: QueryToken, + id: QueryJobId, dummy: PhantomData<&'tcx ()>, } @@ -143,7 +151,7 @@ impl<'tcx> QueryLatch<'tcx> { let info = query_map.get(&job).unwrap(); cycle.push(info.info.clone()); - if job == self.token { + if job == self.id { cycle.reverse(); // This is the end of the cycle @@ -169,7 +177,7 @@ impl<'tcx> QueryLatch<'tcx> { #[cfg(parallel_compiler)] struct QueryWaiter<'tcx> { - query: Option, + query: Option, condvar: Condvar, span: Span, cycle: Lock>>, @@ -270,7 +278,7 @@ impl<'tcx> QueryLatch<'tcx> { /// A resumable waiter of a query. The usize is the index into waiters in the query's latch #[cfg(parallel_compiler)] -type Waiter = (QueryToken, usize); +type Waiter = (QueryJobId, usize); /// Visits all the non-resumable and resumable waiters of a query. /// Only waiters in a query are visited. @@ -284,11 +292,11 @@ type Waiter = (QueryToken, usize); #[cfg(parallel_compiler)] fn visit_waiters<'tcx, F>( query_map: &QueryMap<'tcx>, - query: QueryToken, + query: QueryJobId, mut visit: F, ) -> Option> where - F: FnMut(Span, QueryToken) -> Option>, + F: FnMut(Span, QueryJobId) -> Option>, { // Visit the parent query which is a non-resumable waiter since it's on the same stack if let Some(parent) = query.parent(query_map) { @@ -319,10 +327,10 @@ where #[cfg(parallel_compiler)] fn cycle_check<'tcx>( query_map: &QueryMap<'tcx>, - query: QueryToken, + query: QueryJobId, span: Span, - stack: &mut Vec<(Span, QueryToken)>, - visited: &mut FxHashSet, + stack: &mut Vec<(Span, QueryJobId)>, + visited: &mut FxHashSet, ) -> Option> { if !visited.insert(query) { return if let Some(p) = stack.iter().position(|q| q.1 == query) { @@ -360,8 +368,8 @@ fn cycle_check<'tcx>( #[cfg(parallel_compiler)] fn connected_to_root<'tcx>( query_map: &QueryMap<'tcx>, - query: QueryToken, - visited: &mut FxHashSet, + query: QueryJobId, + visited: &mut FxHashSet, ) -> bool { // We already visited this or we're deliberately ignoring it if !visited.insert(query) { @@ -381,7 +389,7 @@ fn connected_to_root<'tcx>( // Deterministically pick an query from a list #[cfg(parallel_compiler)] -fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryToken)>( +fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryJobId)>( query_map: &QueryMap<'tcx>, tcx: TyCtxt<'tcx>, queries: &'a [T], @@ -413,7 +421,7 @@ fn pick_query<'a, 'tcx, T, F: Fn(&T) -> (Span, QueryToken)>( #[cfg(parallel_compiler)] fn remove_cycle<'tcx>( query_map: &QueryMap<'tcx>, - jobs: &mut Vec, + jobs: &mut Vec, wakelist: &mut Vec>>, tcx: TyCtxt<'tcx>, ) -> bool { @@ -468,7 +476,7 @@ fn remove_cycle<'tcx>( } } }) - .collect::)>>(); + .collect::)>>(); // Deterministically pick an entry point let (_, entry_point, usage) = pick_query(query_map, tcx, &entry_points, |e| (e.0, e.1)); @@ -548,7 +556,7 @@ fn deadlock(tcx: TyCtxt<'_>, registry: &rayon_core::Registry) { let mut wakelist = Vec::new(); let query_map = tcx.queries.try_collect_active_jobs().unwrap(); - let mut jobs: Vec = query_map.keys().cloned().collect(); + let mut jobs: Vec = query_map.keys().cloned().collect(); let mut found_cycle = false; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index ade8cdbb3e5..ce867134831 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -54,6 +54,7 @@ use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use std::any::type_name; use std::borrow::Cow; +use std::convert::TryFrom; use std::ops::Deref; use std::sync::Arc; use syntax::ast; @@ -67,7 +68,7 @@ mod job; #[cfg(parallel_compiler)] pub use self::job::handle_deadlock; use self::job::QueryJobInfo; -pub use self::job::{QueryInfo, QueryJob, QueryToken}; +pub use self::job::{QueryInfo, QueryJob, QueryJobId}; mod keys; use self::keys::Key; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index fdb86c0bede..4fa82156c40 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -4,7 +4,7 @@ use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ty::query::config::{QueryConfig, QueryDescription}; -use crate::ty::query::job::{QueryInfo, QueryJob, QueryToken}; +use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId}; use crate::ty::query::Query; use crate::ty::tls; use crate::ty::{self, TyCtxt}; @@ -21,13 +21,19 @@ use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, H use rustc_span::source_map::DUMMY_SP; use rustc_span::Span; use std::collections::hash_map::Entry; +use std::convert::TryFrom; use std::hash::{Hash, Hasher}; use std::mem; +use std::num::NonZeroU32; use std::ptr; pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { pub(super) results: FxHashMap>, pub(super) active: FxHashMap>, + + /// Used to generate unique ids for active jobs. + pub(super) jobs: u32, + #[cfg(debug_assertions)] pub(super) cache_hits: usize, } @@ -58,6 +64,7 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { QueryCache { results: FxHashMap::default(), active: FxHashMap::default(), + jobs: 0, #[cfg(debug_assertions)] cache_hits: 0, } @@ -69,7 +76,7 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { cache: &'a Sharded>, key: Q::Key, - token: QueryToken, + id: QueryJobId, } impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { @@ -81,12 +88,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - pub(super) fn try_get( - tcx: TyCtxt<'tcx>, - span: Span, - key: &Q::Key, - token: QueryToken, - ) -> TryGetJob<'a, 'tcx, Q> { + pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> { // Handling the `query_blocked_prof_timer` is a bit weird because of the // control flow in this function: Blocking is implemented by // awaiting a running job and, once that is done, entering the loop below @@ -109,7 +111,10 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { key.hash(&mut state); let key_hash = state.finish(); - let mut lock = cache.get_shard_by_hash(key_hash).lock(); + let shard = cache.get_shard_index_by_hash(key_hash); + let mut lock = cache.get_shard_by_index(shard).lock(); + let lock = &mut *lock; + if let Some((_, value)) = lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key) { @@ -144,16 +149,35 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { query_blocked_prof_timer = Some(tcx.prof.query_blocked()); } - job.latch() + // Create the id of the job we're waiting for + let id = QueryJobId { + job: job.id, + shard: u16::try_from(shard).unwrap(), + kind: Q::dep_kind(), + }; + + job.latch(id) } QueryResult::Poisoned => FatalError.raise(), } } Entry::Vacant(entry) => { + let jobs = &mut lock.jobs; + // No job entry for this query. Return a new one to be started later. return tls::with_related_context(tcx, |icx| { - let job = QueryJob::new(token, span, icx.query); - let owner = JobOwner { cache, token, key: (*key).clone() }; + // Generate an id unique within this shard. + let id = jobs.checked_add(1).unwrap(); + *jobs = id; + let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); + + let global_id = QueryJobId { + job: id, + shard: u16::try_from(shard).unwrap(), + kind: Q::dep_kind(), + }; + let job = QueryJob::new(id, span, icx.query); + let owner = JobOwner { cache, id: global_id, key: (*key).clone() }; entry.insert(QueryResult::Started(job)); TryGetJob::NotYetStarted(owner) }); @@ -266,7 +290,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub(super) fn start_query( self, - token: QueryToken, + token: QueryJobId, diagnostics: Option<&Lock>>, compute: F, ) -> R @@ -384,12 +408,7 @@ impl<'tcx> TyCtxt<'tcx> { pub(super) fn get_query>(self, span: Span, key: Q::Key) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - // Create a token which uniquely identifies this query amongst the executing queries - // by using a pointer to `key`. `key` is alive until the query completes execution - // which will prevent reuse of the token value. - let token = QueryToken::from(&key); - - let job = match JobOwner::try_get(self, span, &key, token) { + let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, TryGetJob::JobCompleted((v, index)) => { @@ -409,7 +428,7 @@ impl<'tcx> TyCtxt<'tcx> { let prof_timer = self.prof.query_provider(); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - self.start_query(job.token, diagnostics, |tcx| { + self.start_query(job.id, diagnostics, |tcx| { tcx.dep_graph.with_anon_task(Q::dep_kind(), || Q::compute(tcx, key)) }) }); @@ -435,7 +454,7 @@ impl<'tcx> TyCtxt<'tcx> { // The diagnostics for this query will be // promoted to the current session during // `try_mark_green()`, so we can ignore them here. - let loaded = self.start_query(job.token, None, |tcx| { + let loaded = self.start_query(job.id, None, |tcx| { let marked = tcx.dep_graph.try_mark_green_and_read(tcx, &dep_node); marked.map(|(prev_dep_node_index, dep_node_index)| { ( @@ -569,7 +588,7 @@ impl<'tcx> TyCtxt<'tcx> { let prof_timer = self.prof.query_provider(); let ((result, dep_node_index), diagnostics) = with_diagnostics(|diagnostics| { - self.start_query(job.token, diagnostics, |tcx| { + self.start_query(job.id, diagnostics, |tcx| { if Q::EVAL_ALWAYS { tcx.dep_graph.with_eval_always_task( dep_node, @@ -633,14 +652,9 @@ impl<'tcx> TyCtxt<'tcx> { #[allow(dead_code)] fn force_query>(self, key: Q::Key, span: Span, dep_node: DepNode) { - // Create a token which uniquely identifies this query amongst the executing queries - // by using a pointer to `key`. `key` is alive until the query completes execution - // which will prevent reuse of the token value. - let token = QueryToken::from(&key); - // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let job = match JobOwner::try_get(self, span, &key, token) { + let job = match JobOwner::try_get(self, span, &key) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(_) | TryGetJob::JobCompleted(_) => return, }; @@ -748,24 +762,33 @@ macro_rules! define_queries_inner { pub fn try_collect_active_jobs( &self - ) -> Option>> { + ) -> Option>> { let mut jobs = FxHashMap::default(); $( // We use try_lock_shards here since we are called from the // deadlock handler, and this shouldn't be locked. let shards = self.$name.try_lock_shards()?; - jobs.extend(shards.iter().flat_map(|shard| shard.active.iter().filter_map(|(k, v)| - if let QueryResult::Started(ref job) = *v { - let info = QueryInfo { - span: job.span, - query: queries::$name::query(k.clone()) - }; - Some((job.token, QueryJobInfo { info, job: job.clone() })) - } else { - None - } - ))); + let shards = shards.iter().enumerate(); + jobs.extend(shards.flat_map(|(shard_id, shard)| { + shard.active.iter().filter_map(move |(k, v)| { + if let QueryResult::Started(ref job) = *v { + let id = QueryJobId { + job: job.id, + shard: u16::try_from(shard_id).unwrap(), + kind: + as QueryAccessors<'tcx>>::dep_kind(), + }; + let info = QueryInfo { + span: job.span, + query: queries::$name::query(k.clone()) + }; + Some((id, QueryJobInfo { info, job: job.clone() })) + } else { + None + } + }) + })); )* Some(jobs) diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index ee3f88ff167..15d1e2dd0b6 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -69,12 +69,21 @@ impl Sharded { /// `hash` can be computed with any hasher, so long as that hasher is used /// consistently for each `Sharded` instance. #[inline] - pub fn get_shard_by_hash(&self, hash: u64) -> &Lock { + pub fn get_shard_index_by_hash(&self, hash: u64) -> usize { let hash_len = mem::size_of::(); // Ignore the top 7 bits as hashbrown uses these and get the next SHARD_BITS highest bits. // hashbrown also uses the lowest bits, so we can't use those let bits = (hash >> (hash_len * 8 - 7 - SHARD_BITS)) as usize; - let i = bits % SHARDS; + bits % SHARDS + } + + #[inline] + pub fn get_shard_by_hash(&self, hash: u64) -> &Lock { + &self.shards[self.get_shard_index_by_hash(hash)].0 + } + + #[inline] + pub fn get_shard_by_index(&self, i: usize) -> &Lock { &self.shards[i].0 } From 5de82b926486edc54d7183971fde901be9445c6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 12:26:27 +0100 Subject: [PATCH 0062/1250] Drop the lock guard --- src/librustc/ty/query/plumbing.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 4fa82156c40..4e7a23be383 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -112,8 +112,8 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { let key_hash = state.finish(); let shard = cache.get_shard_index_by_hash(key_hash); - let mut lock = cache.get_shard_by_index(shard).lock(); - let lock = &mut *lock; + let mut lock_guard = cache.get_shard_by_index(shard).lock(); + let lock = &mut *lock_guard; if let Some((_, value)) = lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key) @@ -183,7 +183,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { }); } }; - mem::drop(lock); + mem::drop(lock_guard); // If we are single-threaded we know that we have cycle error, // so we just return the error. From 5206827933177ab83e91c38042597b9061c85b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 14:24:38 +0100 Subject: [PATCH 0063/1250] Address comments --- src/librustc/ty/query/job.rs | 5 ++++ src/librustc/ty/query/plumbing.rs | 40 +++++++++++++------------------ 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/librustc/ty/query/job.rs b/src/librustc/ty/query/job.rs index a3c2bb2f1f5..8aae57e72cd 100644 --- a/src/librustc/ty/query/job.rs +++ b/src/librustc/ty/query/job.rs @@ -7,6 +7,7 @@ use crate::ty::tls; use rustc_data_structures::fx::FxHashMap; use rustc_span::Span; +use std::convert::TryFrom; use std::marker::PhantomData; use std::num::NonZeroU32; @@ -52,6 +53,10 @@ pub struct QueryJobId { } impl QueryJobId { + pub fn new(job: QueryShardJobId, shard: usize, kind: DepKind) -> Self { + QueryJobId { job, shard: u16::try_from(shard).unwrap(), kind } + } + fn query<'tcx>(self, map: &QueryMap<'tcx>) -> Query<'tcx> { map.get(&self).unwrap().info.query.clone() } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 4e7a23be383..8b787915de6 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -21,7 +21,6 @@ use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, H use rustc_span::source_map::DUMMY_SP; use rustc_span::Span; use std::collections::hash_map::Entry; -use std::convert::TryFrom; use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; @@ -150,11 +149,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { } // Create the id of the job we're waiting for - let id = QueryJobId { - job: job.id, - shard: u16::try_from(shard).unwrap(), - kind: Q::dep_kind(), - }; + let id = QueryJobId::new(job.id, shard, Q::dep_kind()); job.latch(id) } @@ -162,25 +157,22 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { } } Entry::Vacant(entry) => { - let jobs = &mut lock.jobs; - // No job entry for this query. Return a new one to be started later. - return tls::with_related_context(tcx, |icx| { - // Generate an id unique within this shard. - let id = jobs.checked_add(1).unwrap(); - *jobs = id; - let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); - - let global_id = QueryJobId { - job: id, - shard: u16::try_from(shard).unwrap(), - kind: Q::dep_kind(), - }; - let job = QueryJob::new(id, span, icx.query); - let owner = JobOwner { cache, id: global_id, key: (*key).clone() }; - entry.insert(QueryResult::Started(job)); - TryGetJob::NotYetStarted(owner) - }); + + // Generate an id unique within this shard. + let id = lock.jobs.checked_add(1).unwrap(); + lock.jobs = id; + let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); + + let global_id = QueryJobId::new(id, shard, Q::dep_kind()); + + let job = + tls::with_related_context(tcx, |icx| QueryJob::new(id, span, icx.query)); + + entry.insert(QueryResult::Started(job)); + + let owner = JobOwner { cache, id: global_id, key: (*key).clone() }; + return TryGetJob::NotYetStarted(owner); } }; mem::drop(lock_guard); From 99b4357f1763f7d98b9b78221207e09d075513b1 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Wed, 12 Feb 2020 16:56:09 +0100 Subject: [PATCH 0064/1250] Add tracking number, adjust documentation wording --- src/libcore/cell.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b1d799953e7..17222b27b2d 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1249,8 +1249,9 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// Convert into a reference to the underlying data. /// /// The underlying `RefCell` can never be mutably borrowed from again and will always appear - /// already immutably borrowed. It can still be immutably borrowed until more than `isize::MAX` - /// `Ref`s of this `RefCell` have been leaked, through this function or another leak, in total. + /// already immutably borrowed. It is not a good idea to leak more than a constant number of + /// references. The `RefCell` can be immutably borrowed again if only a smaller number of leaks + /// have occurred in total. /// /// This is an associated function that needs to be used as /// `Ref::leak(...)`. A method would interfere with methods of the @@ -1269,7 +1270,7 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// assert!(cell.try_borrow().is_ok()); /// assert!(cell.try_borrow_mut().is_err()); /// ``` - #[unstable(feature = "cell_leak", issue = "none")] + #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: Ref<'b, T>) -> &'b T { // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never // goes back to UNUSED again. No further references can be created from the original cell, @@ -1385,7 +1386,7 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// /// assert!(cell.try_borrow_mut().is_err()); /// ``` - #[unstable(feature = "cell_leak", issue = "none")] + #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never // goes back to UNUSED again. No further references can be created from the original cell, From 271ba5a3ea59f25ebc7ba3b9a2e620a833e50b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:01:11 +0100 Subject: [PATCH 0065/1250] Stabilize assoc_int_consts --- src/libcore/lib.rs | 1 - src/libcore/num/f32.rs | 28 ++++++++++++++-------------- src/libcore/num/f64.rs | 28 ++++++++++++++-------------- src/libcore/num/mod.rs | 12 ++++-------- src/libstd/lib.rs | 1 - 5 files changed, 32 insertions(+), 38 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 12647fae900..4c543f1173b 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -138,7 +138,6 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] -#![feature(assoc_int_consts)] #![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303 #[prelude_import] diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index da8dd9acd9f..99df846c095 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -154,15 +154,15 @@ pub mod consts { #[cfg(not(test))] impl f32 { /// The radix or base of the internal representation of `f32`. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; /// Number of significant digits in base 2. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MANTISSA_DIGITS: u32 = 24; /// Approximate number of significant digits in base 10. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 6; /// [Machine epsilon] value for `f32`. @@ -170,41 +170,41 @@ impl f32 { /// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f32 = 1.19209290e-07_f32; /// Smallest finite `f32` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f32 = -3.40282347e+38_f32; /// Smallest positive normal `f32` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32; /// Largest finite `f32` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f32 = 3.40282347e+38_f32; /// One greater than the minimum possible normal power of 2 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -125; /// Maximum possible power of 2 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 128; /// Minimum possible normal power of 10 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -37; /// Maximum possible power of 10 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 38; /// Not a Number (NaN). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NAN: f32 = 0.0_f32 / 0.0_f32; /// Infinity (∞). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const INFINITY: f32 = 1.0_f32 / 0.0_f32; /// Negative infinity (-∞). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; /// Returns `true` if this value is `NaN`. diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index a6081f184ab..63caffc19c6 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -154,14 +154,14 @@ pub mod consts { #[cfg(not(test))] impl f64 { /// The radix or base of the internal representation of `f64`. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const RADIX: u32 = 2; /// Number of significant digits in base 2. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MANTISSA_DIGITS: u32 = 53; /// Approximate number of significant digits in base 10. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const DIGITS: u32 = 15; /// [Machine epsilon] value for `f64`. @@ -169,41 +169,41 @@ impl f64 { /// This is the difference between `1.0` and the next larger representable number. /// /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const EPSILON: f64 = 2.2204460492503131e-16_f64; /// Smallest finite `f64` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: f64 = -1.7976931348623157e+308_f64; /// Smallest positive normal `f64` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64; /// Largest finite `f64` value. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: f64 = 1.7976931348623157e+308_f64; /// One greater than the minimum possible normal power of 2 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_EXP: i32 = -1021; /// Maximum possible power of 2 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_EXP: i32 = 1024; /// Minimum possible normal power of 10 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN_10_EXP: i32 = -307; /// Maximum possible power of 10 exponent. - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX_10_EXP: i32 = 308; /// Not a Number (NaN). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NAN: f64 = 0.0_f64 / 0.0_f64; /// Infinity (∞). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const INFINITY: f64 = 1.0_f64 / 0.0_f64; /// Negative infinity (-∞). - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; /// Returns `true` if this value is `NaN`. diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 471ab966622..bcc38d0f0c8 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -257,11 +257,10 @@ macro_rules! int_impl { Basic usage: ``` -#![feature(assoc_int_consts)] ", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");", $EndFeature, " ```"), - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self; } @@ -273,11 +272,10 @@ $EndFeature, " Basic usage: ``` -#![feature(assoc_int_consts)] ", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");", $EndFeature, " ```"), - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: Self = !Self::MIN; } @@ -2435,10 +2433,9 @@ macro_rules! uint_impl { Basic usage: ``` -#![feature(assoc_int_consts)] ", $Feature, "assert_eq!(", stringify!($SelfT), "::MIN, 0);", $EndFeature, " ```"), - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MIN: Self = 0; } @@ -2450,11 +2447,10 @@ Basic usage: Basic usage: ``` -#![feature(assoc_int_consts)] ", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($MaxV), ");", $EndFeature, " ```"), - #[unstable(feature = "assoc_int_consts", reason = "recently added", issue = "68490")] + #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const MAX: Self = !0; } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index f9c9f224730..50f05d0c7f9 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -237,7 +237,6 @@ #![feature(arbitrary_self_types)] #![feature(array_error_internals)] #![feature(asm)] -#![feature(assoc_int_consts)] #![feature(associated_type_bounds)] #![feature(box_syntax)] #![feature(c_variadic)] From 35298349c3efd75cd8050f9f23e4bf1409d96118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:08:17 +0100 Subject: [PATCH 0066/1250] Add "soft deprecation" notice to old min/max_value() docs --- src/libcore/num/mod.rs | 100 ++++++++++++++++++++++++----------------- 1 file changed, 60 insertions(+), 40 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index bcc38d0f0c8..09e4cfa87a7 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -279,28 +279,6 @@ $EndFeature, " pub const MAX: Self = !Self::MIN; } - doc_comment! { - "Returns the smallest value that can be represented by this integer type.", - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - #[rustc_promotable] - #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")] - pub const fn min_value() -> Self { - Self::MIN - } - } - - doc_comment! { - "Returns the largest value that can be represented by this integer type.", - #[stable(feature = "rust1", since = "1.0.0")] - #[inline(always)] - #[rustc_promotable] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn max_value() -> Self { - Self::MAX - } - } - doc_comment! { concat!("Converts a string slice in a given base to an integer. @@ -2351,6 +2329,38 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), unsafe { mem::transmute(bytes) } } } + + doc_comment! { + concat!("**This method is soft-deprecated.** + +Although using it won’t cause compilation warning, +new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead. + +Returns the smallest value that can be represented by this integer type."), + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_min_value", since = "1.32.0")] + pub const fn min_value() -> Self { + Self::MIN + } + } + + doc_comment! { + concat!("**This method is soft-deprecated.** + +Although using it won’t cause compilation warning, +new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead. + +Returns the largest value that can be represented by this integer type."), + #[stable(feature = "rust1", since = "1.0.0")] + #[inline(always)] + #[rustc_promotable] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn max_value() -> Self { + Self::MAX + } + } } } @@ -2454,24 +2464,6 @@ $EndFeature, " pub const MAX: Self = !0; } - doc_comment! { - "Returns the smallest value that can be represented by this integer type.", - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_promotable] - #[inline(always)] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn min_value() -> Self { Self::MIN } - } - - doc_comment! { - "Returns the largest value that can be represented by this integer type.", - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_promotable] - #[inline(always)] - #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] - pub const fn max_value() -> Self { Self::MAX } - } - doc_comment! { concat!("Converts a string slice in a given base to an integer. @@ -4277,6 +4269,34 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), unsafe { mem::transmute(bytes) } } } + + doc_comment! { + concat!("**This method is soft-deprecated.** + +Although using it won’t cause compilation warning, +new code should use [`", stringify!($SelfT), "::MIN", "`](#associatedconstant.MIN) instead. + +Returns the smallest value that can be represented by this integer type."), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn min_value() -> Self { Self::MIN } + } + + doc_comment! { + concat!("**This method is soft-deprecated.** + +Although using it won’t cause compilation warning, +new code should use [`", stringify!($SelfT), "::MAX", "`](#associatedconstant.MAX) instead. + +Returns the largest value that can be represented by this integer type."), + #[stable(feature = "rust1", since = "1.0.0")] + #[rustc_promotable] + #[inline(always)] + #[rustc_const_stable(feature = "const_max_value", since = "1.32.0")] + pub const fn max_value() -> Self { Self::MAX } + } } } From 97bdd31b0eab51d0a51b8746123f910cd868dff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:13:26 +0100 Subject: [PATCH 0067/1250] Add "soft deprecation" notice to old MIN/MAX docs --- src/libcore/num/int_macros.rs | 19 +++++++++++++------ src/libcore/num/uint_macros.rs | 34 ++++++++++++++++++++++++++++------ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 5c59fe25f64..d3d6db5a768 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -3,11 +3,18 @@ macro_rules! int_module { ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); ($T:ident, #[$attr:meta]) => ( - /// The smallest value that can be represented by this integer type. - #[$attr] - pub const MIN: $T = $T::min_value(); - /// The largest value that can be represented by this integer type. - #[$attr] - pub const MAX: $T = $T::max_value(); + doc_comment! { + concat!("The smallest value that can be represented by this integer type. +Use [`", stringify!($T), "::MIN", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MIN) instead."), + #[$attr] + pub const MIN: $T = $T::min_value(); + } + + doc_comment! { + concat!("The largest value that can be represented by this integer type. +Use [`", stringify!($T), "::MAX", "`](../../std/primitive.", stringify!($T), ".html#associatedconstant.MAX) instead."), + #[$attr] + pub const MAX: $T = $T::max_value(); + } ) } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index a94b541ddb9..ff16a1f38d8 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -1,13 +1,35 @@ #![doc(hidden)] +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + }; +} + macro_rules! uint_module { ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); ($T:ident, #[$attr:meta]) => ( - /// The smallest value that can be represented by this integer type. - #[$attr] - pub const MIN: $T = $T::min_value(); - /// The largest value that can be represented by this integer type. - #[$attr] - pub const MAX: $T = $T::max_value(); + doc_comment! { + concat!("**This method is soft-deprecated.** + + Although using it won’t cause compilation warning, + new code should use [`", stringify!($T), "::MIN", "`] instead. + + The smallest value that can be represented by this integer type."), + #[$attr] + pub const MIN: $T = $T::min_value(); + } + + doc_comment! { + concat!("**This method is soft-deprecated.** + + Although using it won’t cause compilation warning, + new code should use [`", stringify!($T), "::MAX", "`] instead. + + The largest value that can be represented by this integer type."), + #[$attr] + pub const MAX: $T = $T::max_value(); + } ) } From fd71fbe8d51dc291f87fdb6beb12e174a304bd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 10 Feb 2020 19:42:14 +0100 Subject: [PATCH 0068/1250] Remove reference from integer docs to their modules --- src/libstd/primitive_docs.rs | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index d4b41e11c0e..b6bd709efe7 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -788,80 +788,60 @@ mod prim_f64 {} #[doc(primitive = "i8")] // /// The 8-bit signed integer type. -/// -/// *[See also the `std::i8` module](i8/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_i8 {} #[doc(primitive = "i16")] // /// The 16-bit signed integer type. -/// -/// *[See also the `std::i16` module](i16/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_i16 {} #[doc(primitive = "i32")] // /// The 32-bit signed integer type. -/// -/// *[See also the `std::i32` module](i32/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_i32 {} #[doc(primitive = "i64")] // /// The 64-bit signed integer type. -/// -/// *[See also the `std::i64` module](i64/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_i64 {} #[doc(primitive = "i128")] // /// The 128-bit signed integer type. -/// -/// *[See also the `std::i128` module](i128/index.html).* #[stable(feature = "i128", since = "1.26.0")] mod prim_i128 {} #[doc(primitive = "u8")] // /// The 8-bit unsigned integer type. -/// -/// *[See also the `std::u8` module](u8/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_u8 {} #[doc(primitive = "u16")] // /// The 16-bit unsigned integer type. -/// -/// *[See also the `std::u16` module](u16/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_u16 {} #[doc(primitive = "u32")] // /// The 32-bit unsigned integer type. -/// -/// *[See also the `std::u32` module](u32/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_u32 {} #[doc(primitive = "u64")] // /// The 64-bit unsigned integer type. -/// -/// *[See also the `std::u64` module](u64/index.html).* #[stable(feature = "rust1", since = "1.0.0")] mod prim_u64 {} #[doc(primitive = "u128")] // /// The 128-bit unsigned integer type. -/// -/// *[See also the `std::u128` module](u128/index.html).* #[stable(feature = "i128", since = "1.26.0")] mod prim_u128 {} @@ -869,8 +849,6 @@ mod prim_u128 {} // /// The pointer-sized signed integer type. /// -/// *[See also the `std::isize` module](isize/index.html).* -/// /// The size of this primitive is how many bytes it takes to reference any /// location in memory. For example, on a 32 bit target, this is 4 bytes /// and on a 64 bit target, this is 8 bytes. @@ -881,8 +859,6 @@ mod prim_isize {} // /// The pointer-sized unsigned integer type. /// -/// *[See also the `std::usize` module](usize/index.html).* -/// /// The size of this primitive is how many bytes it takes to reference any /// location in memory. For example, on a 32 bit target, this is 4 bytes /// and on a 64 bit target, this is 8 bytes. From cf255c6dc1a9c41bf8e98865d85f8577ce8d2056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:34:50 +0100 Subject: [PATCH 0069/1250] Use new preferred consts in int docs --- src/libcore/num/mod.rs | 48 ++++++++++++------------------------------ 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 09e4cfa87a7..782d1103000 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -805,8 +805,7 @@ assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None); assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);", @@ -836,8 +835,6 @@ if `rhs == 0` or the division results in overflow. Basic usage: ``` -use std::", stringify!($SelfT), "; - assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(2), Some(1)); assert_eq!(5", stringify!($SelfT), ".checked_rem_euclid(0), None); assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); @@ -864,8 +861,7 @@ assert_eq!(", stringify!($SelfT), "::MIN.checked_rem_euclid(-1), None); Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5)); assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);", $EndFeature, " @@ -936,8 +932,7 @@ $EndFeature, " Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5)); assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);", $EndFeature, " @@ -1115,8 +1110,7 @@ numeric bounds instead of overflowing. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120); assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX); assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);", @@ -1148,8 +1142,7 @@ saturating at the numeric bounds instead of overflowing. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64); assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX); assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);", @@ -1536,8 +1529,7 @@ occur. If an overflow would have occurred then the wrapped value is returned. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));", $EndFeature, " @@ -1564,8 +1556,7 @@ would occur. If an overflow would have occurred then the wrapped value is return Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " @@ -1622,8 +1613,7 @@ This function will panic if `rhs` is 0. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));", @@ -1658,8 +1648,6 @@ This function will panic if `rhs` is 0. Basic usage: ``` -use std::", stringify!($SelfT), "; - assert_eq!(5", stringify!($SelfT), ".overflowing_div_euclid(2), (2, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div_euclid(-1), (", stringify!($SelfT), "::MIN, true)); @@ -1693,8 +1681,7 @@ This function will panic if `rhs` is 0. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));", $EndFeature, " @@ -1729,8 +1716,6 @@ This function will panic if `rhs` is 0. Basic usage: ``` -use std::", stringify!($SelfT), "; - assert_eq!(5", stringify!($SelfT), ".overflowing_rem_euclid(2), (1, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem_euclid(-1), (0, true)); ```"), @@ -1761,8 +1746,6 @@ minimum value will be returned again and `true` will be returned for an overflow Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - assert_eq!(2", stringify!($SelfT), ".overflowing_neg(), (-2, false)); assert_eq!(", stringify!($SelfT), "::MIN.overflowing_neg(), (", stringify!($SelfT), "::MIN, true));", $EndFeature, " @@ -3187,8 +3170,7 @@ saturating at the numeric bounds instead of overflowing. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(2", stringify!($SelfT), ".saturating_mul(10), 20); assert_eq!((", stringify!($SelfT), "::MAX).saturating_mul(10), ", stringify!($SelfT), "::MAX);", $EndFeature, " @@ -3215,8 +3197,7 @@ saturating at the numeric bounds instead of overflowing. Basic usage: ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(4", stringify!($SelfT), ".saturating_pow(3), 64); assert_eq!(", stringify!($SelfT), "::MAX.saturating_pow(2), ", stringify!($SelfT), "::MAX);", $EndFeature, " @@ -3553,8 +3534,7 @@ have occurred then the wrapped value is returned. Basic usage ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false)); assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));", $EndFeature, " ```"), @@ -3581,8 +3561,7 @@ have occurred then the wrapped value is returned. Basic usage ``` -", $Feature, "use std::", stringify!($SelfT), "; - +", $Feature, " assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false)); assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));", $EndFeature, " @@ -4868,7 +4847,6 @@ impl usize { /// /// ``` /// use std::num::FpCategory; -/// use std::f32; /// /// let num = 12.4_f32; /// let inf = f32::INFINITY; From 5e17f31d94a0e2f1e69d5c4bd5171cf48ff9e5b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:39:15 +0100 Subject: [PATCH 0070/1250] Replace min/max_value() with MIN/MAX in integer docs --- src/libcore/num/mod.rs | 104 ++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 782d1103000..50d967dba63 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -336,7 +336,7 @@ $EndFeature, " Basic usage: ``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 1);", $EndFeature, " +", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 1);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] @@ -673,8 +673,8 @@ Basic usage: ``` ", $Feature, "assert_eq!((", stringify!($SelfT), -"::max_value() - 2).checked_add(1), Some(", stringify!($SelfT), "::max_value() - 1)); -assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", +"::MAX - 2).checked_add(1), Some(", stringify!($SelfT), "::MAX - 1)); +assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -698,8 +698,8 @@ Basic usage: ``` ", $Feature, "assert_eq!((", stringify!($SelfT), -"::min_value() + 2).checked_sub(1), Some(", stringify!($SelfT), "::min_value() + 1)); -assert_eq!((", stringify!($SelfT), "::min_value() + 2).checked_sub(3), None);", +"::MIN + 2).checked_sub(1), Some(", stringify!($SelfT), "::MIN + 1)); +assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -723,8 +723,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(", stringify!($SelfT), -"::max_value().checked_mul(1), Some(", stringify!($SelfT), "::max_value())); -assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", +"::MAX.checked_mul(1), Some(", stringify!($SelfT), "::MAX)); +assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -748,8 +748,8 @@ Basic usage: ``` ", $Feature, "assert_eq!((", stringify!($SelfT), -"::min_value() + 1).checked_div(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::min_value().checked_div(-1), None); +"::MIN + 1).checked_div(-1), Some(", stringify!($Max), ")); +assert_eq!(", stringify!($SelfT), "::MIN.checked_div(-1), None); assert_eq!((1", stringify!($SelfT), ").checked_div(0), None);", $EndFeature, " ```"), @@ -778,8 +778,8 @@ Basic usage: ``` assert_eq!((", stringify!($SelfT), -"::min_value() + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); -assert_eq!(", stringify!($SelfT), "::min_value().checked_div_euclid(-1), None); +"::MIN + 1).checked_div_euclid(-1), Some(", stringify!($Max), ")); +assert_eq!(", stringify!($SelfT), "::MIN.checked_div_euclid(-1), None); assert_eq!((1", stringify!($SelfT), ").checked_div_euclid(0), None); ```"), #[stable(feature = "euclidean_division", since = "1.38.0")] @@ -959,7 +959,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(8", stringify!($SelfT), ".checked_pow(2), Some(64)); -assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", +assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " ```"), @@ -1000,10 +1000,10 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_add(1), 101); -assert_eq!(", stringify!($SelfT), "::max_value().saturating_add(100), ", stringify!($SelfT), -"::max_value()); -assert_eq!(", stringify!($SelfT), "::min_value().saturating_add(-1), ", stringify!($SelfT), -"::min_value());", +assert_eq!(", stringify!($SelfT), "::MAX.saturating_add(100), ", stringify!($SelfT), +"::MAX); +assert_eq!(", stringify!($SelfT), "::MIN.saturating_add(-1), ", stringify!($SelfT), +"::MIN);", $EndFeature, " ```"), @@ -1027,10 +1027,10 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".saturating_sub(127), -27); -assert_eq!(", stringify!($SelfT), "::min_value().saturating_sub(100), ", stringify!($SelfT), -"::min_value()); -assert_eq!(", stringify!($SelfT), "::max_value().saturating_sub(-1), ", stringify!($SelfT), -"::max_value());", +assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub(100), ", stringify!($SelfT), +"::MIN); +assert_eq!(", stringify!($SelfT), "::MAX.saturating_sub(-1), ", stringify!($SelfT), +"::MAX);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -1055,10 +1055,10 @@ Basic usage: ", $Feature, "#![feature(saturating_neg)] assert_eq!(100", stringify!($SelfT), ".saturating_neg(), -100); assert_eq!((-100", stringify!($SelfT), ").saturating_neg(), 100); -assert_eq!(", stringify!($SelfT), "::min_value().saturating_neg(), ", stringify!($SelfT), -"::max_value()); -assert_eq!(", stringify!($SelfT), "::max_value().saturating_neg(), ", stringify!($SelfT), -"::min_value() + 1);", +assert_eq!(", stringify!($SelfT), "::MIN.saturating_neg(), ", stringify!($SelfT), +"::MAX); +assert_eq!(", stringify!($SelfT), "::MAX.saturating_neg(), ", stringify!($SelfT), +"::MIN + 1);", $EndFeature, " ```"), @@ -1082,10 +1082,10 @@ Basic usage: ", $Feature, "#![feature(saturating_neg)] assert_eq!(100", stringify!($SelfT), ".saturating_abs(), 100); assert_eq!((-100", stringify!($SelfT), ").saturating_abs(), 100); -assert_eq!(", stringify!($SelfT), "::min_value().saturating_abs(), ", stringify!($SelfT), -"::max_value()); -assert_eq!((", stringify!($SelfT), "::min_value() + 1).saturating_abs(), ", stringify!($SelfT), -"::max_value());", +assert_eq!(", stringify!($SelfT), "::MIN.saturating_abs(), ", stringify!($SelfT), +"::MAX); +assert_eq!((", stringify!($SelfT), "::MIN + 1).saturating_abs(), ", stringify!($SelfT), +"::MAX);", $EndFeature, " ```"), @@ -1171,8 +1171,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_add(27), 127); -assert_eq!(", stringify!($SelfT), "::max_value().wrapping_add(2), ", stringify!($SelfT), -"::min_value() + 1);", +assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add(2), ", stringify!($SelfT), +"::MIN + 1);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -1195,8 +1195,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(0", stringify!($SelfT), ".wrapping_sub(127), -127); -assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::max_value()), ", -stringify!($SelfT), "::max_value());", +assert_eq!((-2", stringify!($SelfT), ").wrapping_sub(", stringify!($SelfT), "::MAX), ", +stringify!($SelfT), "::MAX);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -1367,8 +1367,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_neg(), -100); -assert_eq!(", stringify!($SelfT), "::min_value().wrapping_neg(), ", stringify!($SelfT), -"::min_value());", +assert_eq!(", stringify!($SelfT), "::MIN.wrapping_neg(), ", stringify!($SelfT), +"::MIN);", $EndFeature, " ```"), #[stable(feature = "num_wrapping", since = "1.2.0")] @@ -1458,8 +1458,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_abs(), 100); assert_eq!((-100", stringify!($SelfT), ").wrapping_abs(), 100); -assert_eq!(", stringify!($SelfT), "::min_value().wrapping_abs(), ", stringify!($SelfT), -"::min_value()); +assert_eq!(", stringify!($SelfT), "::MIN.wrapping_abs(), ", stringify!($SelfT), +"::MIN); assert_eq!((-128i8).wrapping_abs() as u8, 128);", $EndFeature, " ```"), @@ -1831,8 +1831,8 @@ Basic usage: ``` ", $Feature, "assert_eq!(10", stringify!($SelfT), ".overflowing_abs(), (10, false)); assert_eq!((-10", stringify!($SelfT), ").overflowing_abs(), (10, false)); -assert_eq!((", stringify!($SelfT), "::min_value()).overflowing_abs(), (", stringify!($SelfT), -"::min_value(), true));", +assert_eq!((", stringify!($SelfT), "::MIN).overflowing_abs(), (", stringify!($SelfT), +"::MIN, true));", $EndFeature, " ```"), #[stable(feature = "no_panic_abs", since = "1.13.0")] @@ -2028,10 +2028,10 @@ assert_eq!((-a).rem_euclid(-b), 1); # Overflow behavior -The absolute value of `", stringify!($SelfT), "::min_value()` cannot be represented as an +The absolute value of `", stringify!($SelfT), "::MIN` cannot be represented as an `", stringify!($SelfT), "`, and attempting to calculate it will cause an overflow. This means that code in debug mode will trigger a panic on this case and optimized code will return `", -stringify!($SelfT), "::min_value()` without a panic. +stringify!($SelfT), "::MIN` without a panic. # Examples @@ -2505,7 +2505,7 @@ assert_eq!(n.count_ones(), 3);", $EndFeature, " Basic usage: ``` -", $Feature, "assert_eq!(", stringify!($SelfT), "::max_value().count_zeros(), 0);", $EndFeature, " +", $Feature, "assert_eq!(", stringify!($SelfT), "::MAX.count_zeros(), 0);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_math", since = "1.32.0")] @@ -2523,7 +2523,7 @@ Basic usage: Basic usage: ``` -", $Feature, "let n = ", stringify!($SelfT), "::max_value() >> 2; +", $Feature, "let n = ", stringify!($SelfT), "::MAX >> 2; assert_eq!(n.leading_zeros(), 2);", $EndFeature, " ```"), @@ -2565,7 +2565,7 @@ Basic usage: ``` ", $Feature, "#![feature(leading_trailing_ones)] -let n = !(", stringify!($SelfT), "::max_value() >> 2); +let n = !(", stringify!($SelfT), "::MAX >> 2); assert_eq!(n.leading_ones(), 2);", $EndFeature, " ```"), @@ -2839,9 +2839,9 @@ if overflow occurred. Basic usage: ``` -", $Feature, "assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(1), ", -"Some(", stringify!($SelfT), "::max_value() - 1)); -assert_eq!((", stringify!($SelfT), "::max_value() - 2).checked_add(3), None);", $EndFeature, " +", $Feature, "assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(1), ", +"Some(", stringify!($SelfT), "::MAX - 1)); +assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] @@ -2887,7 +2887,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(5", stringify!($SelfT), ".checked_mul(1), Some(5)); -assert_eq!(", stringify!($SelfT), "::max_value().checked_mul(2), None);", $EndFeature, " +assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_unstable(feature = "const_checked_int_methods", issue = "53718")] @@ -3087,7 +3087,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_pow(5), Some(32)); -assert_eq!(", stringify!($SelfT), "::max_value().checked_pow(2), None);", $EndFeature, " +assert_eq!(", stringify!($SelfT), "::MAX.checked_pow(2), None);", $EndFeature, " ```"), #[stable(feature = "no_panic_pow", since = "1.34.0")] #[must_use = "this returns the result of the operation, \ @@ -3224,7 +3224,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(200", stringify!($SelfT), ".wrapping_add(55), 255); -assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::max_value()), 199);", +assert_eq!(200", stringify!($SelfT), ".wrapping_add(", stringify!($SelfT), "::MAX), 199);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -3247,7 +3247,7 @@ Basic usage: ``` ", $Feature, "assert_eq!(100", stringify!($SelfT), ".wrapping_sub(100), 0); -assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::max_value()), 101);", +assert_eq!(100", stringify!($SelfT), ".wrapping_sub(", stringify!($SelfT), "::MAX), 101);", $EndFeature, " ```"), #[stable(feature = "rust1", since = "1.0.0")] @@ -4029,7 +4029,7 @@ Basic usage: ", $Feature, "assert_eq!(2", stringify!($SelfT), ".checked_next_power_of_two(), Some(2)); assert_eq!(3", stringify!($SelfT), ".checked_next_power_of_two(), Some(4)); -assert_eq!(", stringify!($SelfT), "::max_value().checked_next_power_of_two(), None);", +assert_eq!(", stringify!($SelfT), "::MAX.checked_next_power_of_two(), None);", $EndFeature, " ```"), #[inline] @@ -4053,7 +4053,7 @@ Basic usage: ", $Feature, " assert_eq!(2", stringify!($SelfT), ".wrapping_next_power_of_two(), 2); assert_eq!(3", stringify!($SelfT), ".wrapping_next_power_of_two(), 4); -assert_eq!(", stringify!($SelfT), "::max_value().wrapping_next_power_of_two(), 0);", +assert_eq!(", stringify!($SelfT), "::MAX.wrapping_next_power_of_two(), 0);", $EndFeature, " ```"), #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", From 847a0dd845dbc74b4d49adf873c585519e356b4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 18:56:04 +0100 Subject: [PATCH 0071/1250] Remove uint_macros that was identical to int_macros --- src/libcore/lib.rs | 4 ---- src/libcore/num/int_macros.rs | 7 +++++++ src/libcore/num/u128.rs | 2 +- src/libcore/num/u16.rs | 2 +- src/libcore/num/u32.rs | 2 +- src/libcore/num/u64.rs | 2 +- src/libcore/num/u8.rs | 2 +- src/libcore/num/uint_macros.rs | 35 ---------------------------------- src/libcore/num/usize.rs | 2 +- 9 files changed, 13 insertions(+), 45 deletions(-) delete mode 100644 src/libcore/num/uint_macros.rs diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 4c543f1173b..1cd3e413ecc 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -155,10 +155,6 @@ mod internal_macros; #[macro_use] mod int_macros; -#[path = "num/uint_macros.rs"] -#[macro_use] -mod uint_macros; - #[path = "num/i128.rs"] pub mod i128; #[path = "num/i16.rs"] diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index d3d6db5a768..b68a09e1131 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -1,5 +1,12 @@ #![doc(hidden)] +macro_rules! doc_comment { + ($x:expr, $($tt:tt)*) => { + #[doc = $x] + $($tt)* + }; +} + macro_rules! int_module { ($T:ident) => (int_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); ($T:ident, #[$attr:meta]) => ( diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs index 7d1aa664de3..b9a83a55ced 100644 --- a/src/libcore/num/u128.rs +++ b/src/libcore/num/u128.rs @@ -3,4 +3,4 @@ //! *[See also the `u128` primitive type](../../std/primitive.u128.html).* #![stable(feature = "i128", since = "1.26.0")] -uint_module! { u128, #[stable(feature = "i128", since="1.26.0")] } +int_module! { u128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs index 34f80abaecc..b481755c8d3 100644 --- a/src/libcore/num/u16.rs +++ b/src/libcore/num/u16.rs @@ -4,4 +4,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u16 } +int_module! { u16 } diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs index 5fd486f5466..7355b6c1986 100644 --- a/src/libcore/num/u32.rs +++ b/src/libcore/num/u32.rs @@ -4,4 +4,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u32 } +int_module! { u32 } diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs index 044d238aea9..2da5f013f05 100644 --- a/src/libcore/num/u64.rs +++ b/src/libcore/num/u64.rs @@ -4,4 +4,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u64 } +int_module! { u64 } diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs index 6747e6a0f6c..76d3d70d9e9 100644 --- a/src/libcore/num/u8.rs +++ b/src/libcore/num/u8.rs @@ -4,4 +4,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { u8 } +int_module! { u8 } diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs deleted file mode 100644 index ff16a1f38d8..00000000000 --- a/src/libcore/num/uint_macros.rs +++ /dev/null @@ -1,35 +0,0 @@ -#![doc(hidden)] - -macro_rules! doc_comment { - ($x:expr, $($tt:tt)*) => { - #[doc = $x] - $($tt)* - }; -} - -macro_rules! uint_module { - ($T:ident) => (uint_module!($T, #[stable(feature = "rust1", since = "1.0.0")]);); - ($T:ident, #[$attr:meta]) => ( - doc_comment! { - concat!("**This method is soft-deprecated.** - - Although using it won’t cause compilation warning, - new code should use [`", stringify!($T), "::MIN", "`] instead. - - The smallest value that can be represented by this integer type."), - #[$attr] - pub const MIN: $T = $T::min_value(); - } - - doc_comment! { - concat!("**This method is soft-deprecated.** - - Although using it won’t cause compilation warning, - new code should use [`", stringify!($T), "::MAX", "`] instead. - - The largest value that can be represented by this integer type."), - #[$attr] - pub const MAX: $T = $T::max_value(); - } - ) -} diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs index e3a5239d908..fe132575459 100644 --- a/src/libcore/num/usize.rs +++ b/src/libcore/num/usize.rs @@ -4,4 +4,4 @@ #![stable(feature = "rust1", since = "1.0.0")] -uint_module! { usize } +int_module! { usize } From c67de2570f881a0601f15c7c15e1fb9a26f2d3bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Mon, 10 Feb 2020 19:45:44 +0100 Subject: [PATCH 0072/1250] Add notice about using new consts in new code on float modules --- src/libcore/num/f32.rs | 3 +++ src/libcore/num/f64.rs | 3 +++ src/libstd/f32.rs | 3 +++ src/libstd/f64.rs | 3 +++ src/libstd/primitive_docs.rs | 4 ++-- 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 99df846c095..ee3e09f3577 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -4,6 +4,9 @@ //! *[See also the `f32` primitive type](../../std/primitive.f32.html).* //! //! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 63caffc19c6..40c1cee1d2d 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -4,6 +4,9 @@ //! *[See also the `f64` primitive type](../../std/primitive.f64.html).* //! //! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs index 941ea6a767c..20425aea8d5 100644 --- a/src/libstd/f32.rs +++ b/src/libstd/f32.rs @@ -4,6 +4,9 @@ //! *[See also the `f32` primitive type](../../std/primitive.f32.html).* //! //! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs index d89b38e1a00..a1128a589a6 100644 --- a/src/libstd/f64.rs +++ b/src/libstd/f64.rs @@ -4,6 +4,9 @@ //! *[See also the `f64` primitive type](../../std/primitive.f64.html).* //! //! Mathematically significant numbers are provided in the `consts` sub-module. +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] #![allow(missing_docs)] diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index b6bd709efe7..adad90f56d1 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -771,7 +771,7 @@ mod prim_tuple {} #[doc(primitive = "f32")] /// The 32-bit floating point type. /// -/// *[See also the `std::f32` module](f32/index.html).* +/// *[See also the `std::f32::consts` module](f32/consts/index.html).* /// #[stable(feature = "rust1", since = "1.0.0")] mod prim_f32 {} @@ -780,7 +780,7 @@ mod prim_f32 {} // /// The 64-bit floating point type. /// -/// *[See also the `std::f64` module](f64/index.html).* +/// *[See also the `std::f64::consts` module](f64/consts/index.html).* /// #[stable(feature = "rust1", since = "1.0.0")] mod prim_f64 {} From 086927480be716a14f9c68954d417b544066184b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 23:00:40 +0100 Subject: [PATCH 0073/1250] Add notice about using new consts in new code on int modules --- src/libcore/num/i128.rs | 3 +++ src/libcore/num/i16.rs | 3 +++ src/libcore/num/i32.rs | 3 +++ src/libcore/num/i64.rs | 3 +++ src/libcore/num/i8.rs | 3 +++ src/libcore/num/isize.rs | 3 +++ src/libcore/num/u128.rs | 3 +++ src/libcore/num/u16.rs | 3 +++ src/libcore/num/u32.rs | 3 +++ src/libcore/num/u64.rs | 3 +++ src/libcore/num/u8.rs | 3 +++ src/libcore/num/usize.rs | 3 +++ 12 files changed, 36 insertions(+) diff --git a/src/libcore/num/i128.rs b/src/libcore/num/i128.rs index 564ed598a88..08cb7959468 100644 --- a/src/libcore/num/i128.rs +++ b/src/libcore/num/i128.rs @@ -1,6 +1,9 @@ //! The 128-bit signed integer type. //! //! *[See also the `i128` primitive type](../../std/primitive.i128.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "i128", since = "1.26.0")] diff --git a/src/libcore/num/i16.rs b/src/libcore/num/i16.rs index 44d6aaef25b..288eaceba59 100644 --- a/src/libcore/num/i16.rs +++ b/src/libcore/num/i16.rs @@ -1,6 +1,9 @@ //! The 16-bit signed integer type. //! //! *[See also the `i16` primitive type](../../std/primitive.i16.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/i32.rs b/src/libcore/num/i32.rs index 90a5f89195e..0e1a2ec56cc 100644 --- a/src/libcore/num/i32.rs +++ b/src/libcore/num/i32.rs @@ -1,6 +1,9 @@ //! The 32-bit signed integer type. //! //! *[See also the `i32` primitive type](../../std/primitive.i32.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/i64.rs b/src/libcore/num/i64.rs index 04a8a9d7579..27f7092710b 100644 --- a/src/libcore/num/i64.rs +++ b/src/libcore/num/i64.rs @@ -1,6 +1,9 @@ //! The 64-bit signed integer type. //! //! *[See also the `i64` primitive type](../../std/primitive.i64.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/i8.rs b/src/libcore/num/i8.rs index 5a52a967cf9..e84b421e1a4 100644 --- a/src/libcore/num/i8.rs +++ b/src/libcore/num/i8.rs @@ -1,6 +1,9 @@ //! The 8-bit signed integer type. //! //! *[See also the `i8` primitive type](../../std/primitive.i8.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/isize.rs b/src/libcore/num/isize.rs index 143f8b3b272..0dcfa4a2bd1 100644 --- a/src/libcore/num/isize.rs +++ b/src/libcore/num/isize.rs @@ -1,6 +1,9 @@ //! The pointer-sized signed integer type. //! //! *[See also the `isize` primitive type](../../std/primitive.isize.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/u128.rs b/src/libcore/num/u128.rs index b9a83a55ced..dd45ff14153 100644 --- a/src/libcore/num/u128.rs +++ b/src/libcore/num/u128.rs @@ -1,6 +1,9 @@ //! The 128-bit unsigned integer type. //! //! *[See also the `u128` primitive type](../../std/primitive.u128.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "i128", since = "1.26.0")] int_module! { u128, #[stable(feature = "i128", since="1.26.0")] } diff --git a/src/libcore/num/u16.rs b/src/libcore/num/u16.rs index b481755c8d3..738071643b6 100644 --- a/src/libcore/num/u16.rs +++ b/src/libcore/num/u16.rs @@ -1,6 +1,9 @@ //! The 16-bit unsigned integer type. //! //! *[See also the `u16` primitive type](../../std/primitive.u16.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/u32.rs b/src/libcore/num/u32.rs index 7355b6c1986..9800c909974 100644 --- a/src/libcore/num/u32.rs +++ b/src/libcore/num/u32.rs @@ -1,6 +1,9 @@ //! The 32-bit unsigned integer type. //! //! *[See also the `u32` primitive type](../../std/primitive.u32.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/u64.rs b/src/libcore/num/u64.rs index 2da5f013f05..fb686c396f0 100644 --- a/src/libcore/num/u64.rs +++ b/src/libcore/num/u64.rs @@ -1,6 +1,9 @@ //! The 64-bit unsigned integer type. //! //! *[See also the `u64` primitive type](../../std/primitive.u64.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/u8.rs b/src/libcore/num/u8.rs index 76d3d70d9e9..c03cbdda25d 100644 --- a/src/libcore/num/u8.rs +++ b/src/libcore/num/u8.rs @@ -1,6 +1,9 @@ //! The 8-bit unsigned integer type. //! //! *[See also the `u8` primitive type](../../std/primitive.u8.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/num/usize.rs b/src/libcore/num/usize.rs index fe132575459..a8930416152 100644 --- a/src/libcore/num/usize.rs +++ b/src/libcore/num/usize.rs @@ -1,6 +1,9 @@ //! The pointer-sized unsigned integer type. //! //! *[See also the `usize` primitive type](../../std/primitive.usize.html).* +//! +//! Although using these constants won’t cause compilation warnings, +//! new code should use the associated constants directly on the primitive type. #![stable(feature = "rust1", since = "1.0.0")] From 83191c2da6da6c13466f7f30568cdea02c761ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Tue, 4 Feb 2020 23:08:59 +0100 Subject: [PATCH 0074/1250] Update float documentation to use associated consts --- src/libcore/num/f32.rs | 15 ++------------- src/libcore/num/f64.rs | 9 --------- 2 files changed, 2 insertions(+), 22 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index ee3e09f3577..3a2f3691d8a 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -213,8 +213,6 @@ impl f32 { /// Returns `true` if this value is `NaN`. /// /// ``` - /// use std::f32; - /// /// let nan = f32::NAN; /// let f = 7.0_f32; /// @@ -239,8 +237,6 @@ impl f32 { /// `false` otherwise. /// /// ``` - /// use std::f32; - /// /// let f = 7.0f32; /// let inf = f32::INFINITY; /// let neg_inf = f32::NEG_INFINITY; @@ -261,8 +257,6 @@ impl f32 { /// Returns `true` if this number is neither infinite nor `NaN`. /// /// ``` - /// use std::f32; - /// /// let f = 7.0f32; /// let inf = f32::INFINITY; /// let neg_inf = f32::NEG_INFINITY; @@ -286,8 +280,6 @@ impl f32 { /// [subnormal], or `NaN`. /// /// ``` - /// use std::f32; - /// /// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32 /// let max = f32::MAX; /// let lower_than_min = 1.0e-40_f32; @@ -315,7 +307,6 @@ impl f32 { /// /// ``` /// use std::num::FpCategory; - /// use std::f32; /// /// let num = 12.4_f32; /// let inf = f32::INFINITY; @@ -375,8 +366,6 @@ impl f32 { /// Takes the reciprocal (inverse) of a number, `1/x`. /// /// ``` - /// use std::f32; - /// /// let x = 2.0_f32; /// let abs_difference = (x.recip() - (1.0 / x)).abs(); /// @@ -391,7 +380,7 @@ impl f32 { /// Converts radians to degrees. /// /// ``` - /// use std::f32::{self, consts}; + /// use std::f32::consts; /// /// let angle = consts::PI; /// @@ -410,7 +399,7 @@ impl f32 { /// Converts degrees to radians. /// /// ``` - /// use std::f32::{self, consts}; + /// use std::f32::consts; /// /// let angle = 180.0f32; /// diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 40c1cee1d2d..ca81f98a6b5 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -212,8 +212,6 @@ impl f64 { /// Returns `true` if this value is `NaN`. /// /// ``` - /// use std::f64; - /// /// let nan = f64::NAN; /// let f = 7.0_f64; /// @@ -238,8 +236,6 @@ impl f64 { /// `false` otherwise. /// /// ``` - /// use std::f64; - /// /// let f = 7.0f64; /// let inf = f64::INFINITY; /// let neg_inf = f64::NEG_INFINITY; @@ -260,8 +256,6 @@ impl f64 { /// Returns `true` if this number is neither infinite nor `NaN`. /// /// ``` - /// use std::f64; - /// /// let f = 7.0f64; /// let inf: f64 = f64::INFINITY; /// let neg_inf: f64 = f64::NEG_INFINITY; @@ -285,8 +279,6 @@ impl f64 { /// [subnormal], or `NaN`. /// /// ``` - /// use std::f64; - /// /// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64 /// let max = f64::MAX; /// let lower_than_min = 1.0e-308_f64; @@ -314,7 +306,6 @@ impl f64 { /// /// ``` /// use std::num::FpCategory; - /// use std::f64; /// /// let num = 12.4_f64; /// let inf = f64::INFINITY; From b2dc6187699d99436f6183218d928be09d439578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Linus=20F=C3=A4rnstrand?= Date: Sat, 8 Feb 2020 12:15:22 +0100 Subject: [PATCH 0075/1250] Add usage recommendation to old float constants --- src/libcore/num/f32.rs | 14 ++++++++++++++ src/libcore/num/f64.rs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 3a2f3691d8a..3a641ae94a4 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -17,17 +17,21 @@ use crate::mem; use crate::num::FpCategory; /// The radix or base of the internal representation of `f32`. +/// Use [`f32::RADIX`](../../std/primitive.f32.html#associatedconstant.RADIX) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const RADIX: u32 = f32::RADIX; /// Number of significant digits in base 2. +/// Use [`f32::MANTISSA_DIGITS`](../../std/primitive.f32.html#associatedconstant.MANTISSA_DIGITS) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS; /// Approximate number of significant digits in base 10. +/// Use [`f32::DIGITS`](../../std/primitive.f32.html#associatedconstant.DIGITS) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const DIGITS: u32 = f32::DIGITS; /// [Machine epsilon] value for `f32`. +/// Use [`f32::EPSILON`](../../std/primitive.f32.html#associatedconstant.EPSILON) instead. /// /// This is the difference between `1.0` and the next larger representable number. /// @@ -36,36 +40,46 @@ pub const DIGITS: u32 = f32::DIGITS; pub const EPSILON: f32 = f32::EPSILON; /// Smallest finite `f32` value. +/// Use [`f32::MIN`](../../std/primitive.f32.html#associatedconstant.MIN) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN: f32 = f32::MIN; /// Smallest positive normal `f32` value. +/// Use [`f32::MIN_POSITIVE`](../../std/primitive.f32.html#associatedconstant.MIN_POSITIVE) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE; /// Largest finite `f32` value. +/// Use [`f32::MAX`](../../std/primitive.f32.html#associatedconstant.MAX) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: f32 = f32::MAX; /// One greater than the minimum possible normal power of 2 exponent. +/// Use [`f32::MIN_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_EXP: i32 = f32::MIN_EXP; /// Maximum possible power of 2 exponent. +/// Use [`f32::MAX_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX_EXP: i32 = f32::MAX_EXP; /// Minimum possible normal power of 10 exponent. +/// Use [`f32::MIN_10_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_10_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_10_EXP: i32 = f32::MIN_10_EXP; /// Maximum possible power of 10 exponent. +/// Use [`f32::MAX_10_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_10_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX_10_EXP: i32 = f32::MAX_10_EXP; /// Not a Number (NaN). +/// Use [`f32::NAN`](../../std/primitive.f32.html#associatedconstant.NAN) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const NAN: f32 = f32::NAN; /// Infinity (∞). +/// Use [`f32::INFINITY`](../../std/primitive.f32.html#associatedconstant.INFINITY) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const INFINITY: f32 = f32::INFINITY; /// Negative infinity (−∞). +/// Use [`f32::NEG_INFINITY`](../../std/primitive.f32.html#associatedconstant.NEG_INFINITY) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const NEG_INFINITY: f32 = f32::NEG_INFINITY; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index ca81f98a6b5..121ed149294 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -17,17 +17,21 @@ use crate::mem; use crate::num::FpCategory; /// The radix or base of the internal representation of `f64`. +/// Use [`f64::RADIX`](../../std/primitive.f64.html#associatedconstant.RADIX) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const RADIX: u32 = f64::RADIX; /// Number of significant digits in base 2. +/// Use [`f64::MANTISSA_DIGITS`](../../std/primitive.f64.html#associatedconstant.MANTISSA_DIGITS) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS; /// Approximate number of significant digits in base 10. +/// Use [`f64::DIGITS`](../../std/primitive.f64.html#associatedconstant.DIGITS) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const DIGITS: u32 = f64::DIGITS; /// [Machine epsilon] value for `f64`. +/// Use [`f64::EPSILON`](../../std/primitive.f64.html#associatedconstant.EPSILON) instead. /// /// This is the difference between `1.0` and the next larger representable number. /// @@ -36,36 +40,46 @@ pub const DIGITS: u32 = f64::DIGITS; pub const EPSILON: f64 = f64::EPSILON; /// Smallest finite `f64` value. +/// Use [`f64::MIN`](../../std/primitive.f64.html#associatedconstant.MIN) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN: f64 = f64::MIN; /// Smallest positive normal `f64` value. +/// Use [`f64::MIN_POSITIVE`](../../std/primitive.f64.html#associatedconstant.MIN_POSITIVE) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE; /// Largest finite `f64` value. +/// Use [`f64::MAX`](../../std/primitive.f64.html#associatedconstant.MAX) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX: f64 = f64::MAX; /// One greater than the minimum possible normal power of 2 exponent. +/// Use [`f64::MIN_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_EXP: i32 = f64::MIN_EXP; /// Maximum possible power of 2 exponent. +/// Use [`f64::MAX_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX_EXP: i32 = f64::MAX_EXP; /// Minimum possible normal power of 10 exponent. +/// Use [`f64::MIN_10_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_10_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MIN_10_EXP: i32 = f64::MIN_10_EXP; /// Maximum possible power of 10 exponent. +/// Use [`f64::MAX_10_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_10_EXP) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const MAX_10_EXP: i32 = f64::MAX_10_EXP; /// Not a Number (NaN). +/// Use [`f64::NAN`](../../std/primitive.f64.html#associatedconstant.NAN) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const NAN: f64 = f64::NAN; /// Infinity (∞). +/// Use [`f64::INFINITY`](../../std/primitive.f64.html#associatedconstant.INFINITY) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const INFINITY: f64 = f64::INFINITY; /// Negative infinity (−∞). +/// Use [`f64::NEG_INFINITY`](../../std/primitive.f64.html#associatedconstant.NEG_INFINITY) instead. #[stable(feature = "rust1", since = "1.0.0")] pub const NEG_INFINITY: f64 = f64::NEG_INFINITY; From 8fb8bb4b3ff25570a7a9b105c1a569bb2307f25f Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Wed, 12 Feb 2020 19:51:30 +0000 Subject: [PATCH 0076/1250] Fix std::fs::copy on WASI target Previously `std::fs::copy` on wasm32-wasi would reuse code from the `sys_common` module and would successfully copy contents of the file just to fail right before closing it. This was happening because `sys_common::copy` tries to copy permissions of the file, but permissions are not a thing in WASI (at least yet) and `set_permissions` is implemented as an unconditional runtime error. This change instead adds a custom working implementation of `std::fs::copy` (like Rust already has on some other targets) that doesn't try to call `set_permissions` and is essentially a thin wrapper around `std::io::copy`. Fixes #68560. --- src/libstd/sys/wasi/fs.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs index 04bfdf67e12..a11f61fdd69 100644 --- a/src/libstd/sys/wasi/fs.rs +++ b/src/libstd/sys/wasi/fs.rs @@ -12,7 +12,6 @@ use crate::sys::time::SystemTime; use crate::sys::unsupported; use crate::sys_common::FromInner; -pub use crate::sys_common::fs::copy; pub use crate::sys_common::fs::remove_dir_all; pub struct File { @@ -647,3 +646,12 @@ fn open_parent(p: &Path) -> io::Result<(ManuallyDrop, PathBuf)> { pub fn osstr2str(f: &OsStr) -> io::Result<&str> { f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8")) } + +pub fn copy(from: &Path, to: &Path) -> io::Result { + use crate::fs::File; + + let mut reader = File::open(from)?; + let mut writer = File::create(to)?; + + io::copy(&mut reader, &mut writer) +} From fc5c2956b11e29f931cec010e3f38461ec4ac309 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:33:43 -0800 Subject: [PATCH 0077/1250] Impl `GenKill` for old dataflow framework's `GenKillSet` This impl is temporary and will be removed along with the old dataflow framework. It allows us to reuse the transfer function of new dataflow analyses when defining old ones --- src/librustc_mir/dataflow/generic/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index ea643042c5f..23b22550a3b 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -395,5 +395,16 @@ impl GenKill for BitSet { } } +// For compatibility with old framework +impl GenKill for crate::dataflow::GenKillSet { + fn gen(&mut self, elem: T) { + self.gen(elem); + } + + fn kill(&mut self, elem: T) { + self.kill(elem); + } +} + #[cfg(test)] mod tests; From 7d9dadcccca9efc63f30fa1c9adee00effb860d4 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:36:47 -0800 Subject: [PATCH 0078/1250] Implement `Maybe{Mut,}BorrowedLocals` analyses --- .../dataflow/impls/borrowed_locals.rs | 268 ++++++++++++++---- src/librustc_mir/dataflow/mod.rs | 3 +- 2 files changed, 209 insertions(+), 62 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 63834d0ecda..519db963d1e 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -1,102 +1,250 @@ pub use super::*; -use crate::dataflow::{BitDenotation, GenKillSet}; +use crate::dataflow::generic::{AnalysisDomain, GenKill, GenKillAnalysis}; use rustc::mir::visit::Visitor; use rustc::mir::*; +use rustc::ty::{ParamEnv, TyCtxt}; +use rustc_span::DUMMY_SP; + +pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals>; + +/// A dataflow analysis that tracks whether a pointer or reference could possibly exist that points +/// to a given local. +/// +/// The `K` parameter determines what kind of borrows are tracked. By default, +/// `MaybeBorrowedLocals` looks for *any* borrow of a local. If you are only interested in borrows +/// that might allow mutation, use the `MaybeMutBorrowedLocals` type alias instead. +/// +/// At present, this is used as a very limited form of alias analysis. For example, +/// `MaybeBorrowedLocals` is used to compute which locals are live during a yield expression for +/// immovable generators. `MaybeMutBorrowedLocals` is used during const checking to prove that a +/// local has not been mutated via indirect assignment (e.g., `*p = 42`), the side-effects of a +/// function call or inline assembly. +pub struct MaybeBorrowedLocals { + kind: K, +} -/// This calculates if any part of a MIR local could have previously been borrowed. -/// This means that once a local has been borrowed, its bit will be set -/// from that point and onwards, until we see a StorageDead statement for the local, -/// at which points there is no memory associated with the local, so it cannot be borrowed. -/// This is used to compute which locals are live during a yield expression for -/// immovable generators. -#[derive(Copy, Clone)] -pub struct HaveBeenBorrowedLocals<'a, 'tcx> { - body: &'a Body<'tcx>, +impl MaybeBorrowedLocals { + /// A dataflow analysis that records whether a pointer or reference exists that may alias the + /// given local. + pub fn new() -> Self { + MaybeBorrowedLocals { kind: AnyBorrow } + } } -impl<'a, 'tcx> HaveBeenBorrowedLocals<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>) -> Self { - HaveBeenBorrowedLocals { body } +impl MaybeMutBorrowedLocals<'mir, 'tcx> { + /// A dataflow analysis that records whether a pointer or reference exists that may *mutably* + /// alias the given local. + pub fn new_mut_only( + tcx: TyCtxt<'tcx>, + body: &'mir mir::Body<'tcx>, + param_env: ParamEnv<'tcx>, + ) -> Self { + MaybeBorrowedLocals { kind: MutBorrow { body, tcx, param_env } } } +} - pub fn body(&self) -> &Body<'tcx> { - self.body +impl MaybeBorrowedLocals { + fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> { + TransferFunction { kind: &self.kind, trans } } } -impl<'a, 'tcx> BitDenotation<'tcx> for HaveBeenBorrowedLocals<'a, 'tcx> { +impl AnalysisDomain<'tcx> for MaybeBorrowedLocals +where + K: BorrowAnalysisKind<'tcx>, +{ type Idx = Local; - fn name() -> &'static str { - "has_been_borrowed_locals" + + const NAME: &'static str = K::ANALYSIS_NAME; + + fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize { + body.local_decls().len() + } + + fn initialize_start_block(&self, _: &mir::Body<'tcx>, _: &mut BitSet) { + // No locals are aliased on function entry + } +} + +impl GenKillAnalysis<'tcx> for MaybeBorrowedLocals +where + K: BorrowAnalysisKind<'tcx>, +{ + fn statement_effect( + &self, + trans: &mut impl GenKill, + statement: &mir::Statement<'tcx>, + location: Location, + ) { + self.transfer_function(trans).visit_statement(statement, location); } - fn bits_per_block(&self) -> usize { - self.body.local_decls.len() + + fn terminator_effect( + &self, + trans: &mut impl GenKill, + terminator: &mir::Terminator<'tcx>, + location: Location, + ) { + self.transfer_function(trans).visit_terminator(terminator, location); } - fn start_block_effect(&self, _on_entry: &mut BitSet) { - // Nothing is borrowed on function entry + fn call_return_effect( + &self, + _trans: &mut impl GenKill, + _block: mir::BasicBlock, + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], + _dest_place: &mir::Place<'tcx>, + ) { } +} - fn statement_effect(&self, trans: &mut GenKillSet, loc: Location) { - let stmt = &self.body[loc.block].statements[loc.statement_index]; +impl BottomValue for MaybeBorrowedLocals { + // bottom = unborrowed + const BOTTOM_VALUE: bool = false; +} - BorrowedLocalsVisitor { trans }.visit_statement(stmt, loc); +/// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`. +struct TransferFunction<'a, T, K> { + trans: &'a mut T, + kind: &'a K, +} - // StorageDead invalidates all borrows and raw pointers to a local - match stmt.kind { - StatementKind::StorageDead(l) => trans.kill(l), - _ => (), +impl Visitor<'tcx> for TransferFunction<'a, T, K> +where + T: GenKill, + K: BorrowAnalysisKind<'tcx>, +{ + fn visit_statement(&mut self, stmt: &Statement<'tcx>, location: Location) { + self.super_statement(stmt, location); + + // When we reach a `StorageDead` statement, we can assume that any pointers to this memory + // are now invalid. + if let StatementKind::StorageDead(local) = stmt.kind { + self.trans.kill(local); } } - fn terminator_effect(&self, trans: &mut GenKillSet, loc: Location) { - let terminator = self.body[loc.block].terminator(); - BorrowedLocalsVisitor { trans }.visit_terminator(terminator, loc); - match &terminator.kind { - // Drop terminators borrows the location - TerminatorKind::Drop { location, .. } - | TerminatorKind::DropAndReplace { location, .. } => { - if let Some(local) = find_local(location) { - trans.gen(local); + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { + self.super_rvalue(rvalue, location); + + match rvalue { + mir::Rvalue::AddressOf(mt, borrowed_place) => { + if !borrowed_place.is_indirect() && self.kind.in_address_of(*mt, borrowed_place) { + self.trans.gen(borrowed_place.local); } } - _ => (), + + mir::Rvalue::Ref(_, kind, borrowed_place) => { + if !borrowed_place.is_indirect() && self.kind.in_ref(*kind, borrowed_place) { + self.trans.gen(borrowed_place.local); + } + } + + mir::Rvalue::Cast(..) + | mir::Rvalue::Use(..) + | mir::Rvalue::Repeat(..) + | mir::Rvalue::Len(..) + | mir::Rvalue::BinaryOp(..) + | mir::Rvalue::CheckedBinaryOp(..) + | mir::Rvalue::NullaryOp(..) + | mir::Rvalue::UnaryOp(..) + | mir::Rvalue::Discriminant(..) + | mir::Rvalue::Aggregate(..) => {} } } - fn propagate_call_return( - &self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place<'tcx>, - ) { - // Nothing to do when a call returns successfully + fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { + self.super_terminator(terminator, location); + + match terminator.kind { + // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` + // as a parameter. Hypothetically, a drop impl could launder that reference into the + // surrounding environment through a raw pointer, thus creating a valid `*mut` pointing + // to the dropped local. We are not yet willing to declare this particular case UB, so + // we must treat all dropped locals as mutably borrowed for now. See discussion on + // [#61069]. + // + // [#61069]: https://github.com/rust-lang/rust/pull/61069 + mir::TerminatorKind::Drop { location: dropped_place, .. } + | mir::TerminatorKind::DropAndReplace { location: dropped_place, .. } => { + self.trans.gen(dropped_place.local); + } + + TerminatorKind::Abort + | TerminatorKind::Assert { .. } + | TerminatorKind::Call { .. } + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Return + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Unreachable + | TerminatorKind::Yield { .. } => {} + } } } -impl<'a, 'tcx> BottomValue for HaveBeenBorrowedLocals<'a, 'tcx> { - // bottom = unborrowed - const BOTTOM_VALUE: bool = false; +pub struct AnyBorrow; + +pub struct MutBorrow<'mir, 'tcx> { + tcx: TyCtxt<'tcx>, + body: &'mir Body<'tcx>, + param_env: ParamEnv<'tcx>, } -struct BorrowedLocalsVisitor<'gk> { - trans: &'gk mut GenKillSet, +impl MutBorrow<'mir, 'tcx> { + // `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`. + // + // This assumes that it is UB to take the address of a struct field whose type is + // `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of + // that same struct whose type is `!Freeze`. If we decide that this is not UB, we will + // have to check the type of the borrowed **local** instead of the borrowed **place** + // below. See [rust-lang/unsafe-code-guidelines#134]. + // + // [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 + fn shared_borrow_allows_mutation(&self, place: &Place<'tcx>) -> bool { + !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) + } } -fn find_local(place: &Place<'_>) -> Option { - if !place.is_indirect() { Some(place.local) } else { None } +pub trait BorrowAnalysisKind<'tcx> { + const ANALYSIS_NAME: &'static str; + + fn in_address_of(&self, mt: Mutability, place: &Place<'tcx>) -> bool; + fn in_ref(&self, kind: mir::BorrowKind, place: &Place<'tcx>) -> bool; } -impl<'tcx> Visitor<'tcx> for BorrowedLocalsVisitor<'_> { - fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { - if let Rvalue::Ref(_, _, ref place) = *rvalue { - if let Some(local) = find_local(place) { - self.trans.gen(local); +impl BorrowAnalysisKind<'tcx> for AnyBorrow { + const ANALYSIS_NAME: &'static str = "maybe_borrowed_locals"; + + fn in_ref(&self, _: mir::BorrowKind, _: &Place<'_>) -> bool { + true + } + fn in_address_of(&self, _: Mutability, _: &Place<'_>) -> bool { + true + } +} + +impl BorrowAnalysisKind<'tcx> for MutBorrow<'mir, 'tcx> { + const ANALYSIS_NAME: &'static str = "maybe_mut_borrowed_locals"; + + fn in_ref(&self, kind: mir::BorrowKind, place: &Place<'tcx>) -> bool { + match kind { + mir::BorrowKind::Mut { .. } => true, + mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => { + self.shared_borrow_allows_mutation(place) } } + } - self.super_rvalue(rvalue, location) + fn in_address_of(&self, mt: Mutability, place: &Place<'tcx>) -> bool { + match mt { + Mutability::Mut => true, + Mutability::Not => self.shared_borrow_allows_mutation(place), + } } } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 7cd7fc309b6..41bac894e48 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -23,8 +23,7 @@ pub(crate) use self::drop_flag_effects::*; pub use self::impls::borrows::Borrows; pub use self::impls::DefinitelyInitializedPlaces; pub use self::impls::EverInitializedPlaces; -pub use self::impls::HaveBeenBorrowedLocals; -pub use self::impls::IndirectlyMutableLocals; +pub use self::impls::{MaybeBorrowedLocals, MaybeMutBorrowedLocals}; pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; pub use self::impls::{MaybeStorageLive, RequiresStorage}; From 34783b73bd891a66fb2af613fef7492376fc7c8a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:37:19 -0800 Subject: [PATCH 0079/1250] Remove outdated `IndirectlyMutableLocals` `MaybeMutBorrowedLocals` serves the same purpose and has a better name. --- .../dataflow/impls/indirect_mutation.rs | 136 ------------------ src/librustc_mir/dataflow/impls/mod.rs | 2 - 2 files changed, 138 deletions(-) delete mode 100644 src/librustc_mir/dataflow/impls/indirect_mutation.rs diff --git a/src/librustc_mir/dataflow/impls/indirect_mutation.rs b/src/librustc_mir/dataflow/impls/indirect_mutation.rs deleted file mode 100644 index 85bf342c8a3..00000000000 --- a/src/librustc_mir/dataflow/impls/indirect_mutation.rs +++ /dev/null @@ -1,136 +0,0 @@ -use rustc::mir::visit::Visitor; -use rustc::mir::{self, Local, Location}; -use rustc::ty::{self, TyCtxt}; -use rustc_index::bit_set::BitSet; -use rustc_span::DUMMY_SP; - -use crate::dataflow::{self, GenKillSet}; - -/// Whether a borrow to a `Local` has been created that could allow that `Local` to be mutated -/// indirectly. This could either be a mutable reference (`&mut`) or a shared borrow if the type of -/// that `Local` allows interior mutability. Operations that can mutate local's indirectly include: -/// assignments through a pointer (`*p = 42`), function calls, drop terminators and inline assembly. -/// -/// If this returns false for a `Local` at a given statement (or terminator), that `Local` could -/// not possibly have been mutated indirectly prior to that statement. -#[derive(Copy, Clone)] -pub struct IndirectlyMutableLocals<'mir, 'tcx> { - body: &'mir mir::Body<'tcx>, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, -} - -impl<'mir, 'tcx> IndirectlyMutableLocals<'mir, 'tcx> { - pub fn new( - tcx: TyCtxt<'tcx>, - body: &'mir mir::Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, - ) -> Self { - IndirectlyMutableLocals { body, tcx, param_env } - } - - fn transfer_function<'a>( - &self, - trans: &'a mut GenKillSet, - ) -> TransferFunction<'a, 'mir, 'tcx> { - TransferFunction { body: self.body, tcx: self.tcx, param_env: self.param_env, trans } - } -} - -impl<'mir, 'tcx> dataflow::BitDenotation<'tcx> for IndirectlyMutableLocals<'mir, 'tcx> { - type Idx = Local; - - fn name() -> &'static str { - "mut_borrowed_locals" - } - - fn bits_per_block(&self) -> usize { - self.body.local_decls.len() - } - - fn start_block_effect(&self, _entry_set: &mut BitSet) { - // Nothing is borrowed on function entry - } - - fn statement_effect(&self, trans: &mut GenKillSet, loc: Location) { - let stmt = &self.body[loc.block].statements[loc.statement_index]; - self.transfer_function(trans).visit_statement(stmt, loc); - } - - fn terminator_effect(&self, trans: &mut GenKillSet, loc: Location) { - let terminator = self.body[loc.block].terminator(); - self.transfer_function(trans).visit_terminator(terminator, loc); - } - - fn propagate_call_return( - &self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place<'tcx>, - ) { - // Nothing to do when a call returns successfully - } -} - -impl<'mir, 'tcx> dataflow::BottomValue for IndirectlyMutableLocals<'mir, 'tcx> { - // bottom = unborrowed - const BOTTOM_VALUE: bool = false; -} - -/// A `Visitor` that defines the transfer function for `IndirectlyMutableLocals`. -struct TransferFunction<'a, 'mir, 'tcx> { - trans: &'a mut GenKillSet, - body: &'mir mir::Body<'tcx>, - tcx: TyCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, -} - -impl<'tcx> TransferFunction<'_, '_, 'tcx> { - /// Returns `true` if this borrow would allow mutation of the `borrowed_place`. - fn borrow_allows_mutation( - &self, - kind: mir::BorrowKind, - borrowed_place: &mir::Place<'tcx>, - ) -> bool { - match kind { - mir::BorrowKind::Mut { .. } => true, - - mir::BorrowKind::Shared | mir::BorrowKind::Shallow | mir::BorrowKind::Unique => { - !borrowed_place.ty(self.body, self.tcx).ty.is_freeze( - self.tcx, - self.param_env, - DUMMY_SP, - ) - } - } - } -} - -impl<'tcx> Visitor<'tcx> for TransferFunction<'_, '_, 'tcx> { - fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { - if let mir::Rvalue::Ref(_, kind, ref borrowed_place) = *rvalue { - if self.borrow_allows_mutation(kind, borrowed_place) { - if !borrowed_place.is_indirect() { - self.trans.gen(borrowed_place.local); - } - } - } - - self.super_rvalue(rvalue, location); - } - - fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) { - // This method purposely does nothing except call `super_terminator`. It exists solely to - // document the subtleties around drop terminators. - - self.super_terminator(terminator, location); - - if let mir::TerminatorKind::Drop { location: _, .. } - | mir::TerminatorKind::DropAndReplace { location: _, .. } = &terminator.kind - { - // Although drop terminators mutably borrow the location being dropped, that borrow - // cannot live beyond the drop terminator because the dropped location is invalidated. - } - } -} diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 5b2264c2a65..acea3185781 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -20,11 +20,9 @@ use super::drop_flag_effects_for_location; use super::on_lookup_result_bits; mod borrowed_locals; -mod indirect_mutation; mod storage_liveness; pub use self::borrowed_locals::*; -pub use self::indirect_mutation::IndirectlyMutableLocals; pub use self::storage_liveness::*; pub(super) mod borrows; From 9972502bafab062b06ef04c02c653f1b868937bd Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:38:11 -0800 Subject: [PATCH 0080/1250] Reenable peek test for indirect mutation analysis This uses the new `MaybeMutBorrowedLocals` pass but we keep the `rustc_peek_indirectly_mutable` since the two are interchangable except when inspecting a local after it has been marked `StorageDead`. --- src/librustc_mir/transform/rustc_peek.rs | 26 ++++++------------------ 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 7d8506eb281..16edb7d552b 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -12,9 +12,8 @@ use rustc_index::bit_set::BitSet; use crate::dataflow::generic::{Analysis, Results, ResultsCursor}; use crate::dataflow::move_paths::{HasMoveData, MoveData}; use crate::dataflow::move_paths::{LookupResult, MovePathIndex}; -use crate::dataflow::IndirectlyMutableLocals; +use crate::dataflow::MaybeMutBorrowedLocals; use crate::dataflow::MoveDataParamEnv; -use crate::dataflow::{do_dataflow, DebugFormatted}; use crate::dataflow::{ DefinitelyInitializedPlaces, MaybeInitializedPlaces, MaybeUninitializedPlaces, }; @@ -24,7 +23,6 @@ pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) { use crate::dataflow::has_rustc_mir_with; - let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); @@ -37,7 +35,6 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap(); let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; - let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body, def_id) @@ -48,15 +45,9 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body, def_id) .iterate_to_fixpoint(); - let _flow_indirectly_mut = do_dataflow( - tcx, - body, - def_id, - &attributes, - &dead_unwinds, - IndirectlyMutableLocals::new(tcx, body, param_env), - |_, i| DebugFormatted::new(&i), - ); + let flow_mut_borrowed = MaybeMutBorrowedLocals::new_mut_only(tcx, body, param_env) + .into_engine(tcx, body, def_id) + .iterate_to_fixpoint(); if has_rustc_mir_with(&attributes, sym::rustc_peek_maybe_init).is_some() { sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_inits); @@ -67,12 +58,9 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { if has_rustc_mir_with(&attributes, sym::rustc_peek_definite_init).is_some() { sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_def_inits); } - // FIXME: Uncomment these as analyses are migrated to the new framework - /* if has_rustc_mir_with(&attributes, sym::rustc_peek_indirectly_mutable).is_some() { - sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_indirectly_mut); + sanity_check_via_rustc_peek(tcx, body, def_id, &attributes, &flow_mut_borrowed); } - */ if has_rustc_mir_with(&attributes, sym::stop_after_dataflow).is_some() { tcx.sess.fatal("stop_after_dataflow ended compilation"); } @@ -276,8 +264,7 @@ where } } -/* FIXME: Add this back once `IndirectlyMutableLocals` uses the new dataflow framework. -impl<'tcx> RustcPeekAt<'tcx> for IndirectlyMutableLocals<'_, 'tcx> { +impl<'tcx> RustcPeekAt<'tcx> for MaybeMutBorrowedLocals<'_, 'tcx> { fn peek_at( &self, tcx: TyCtxt<'tcx>, @@ -298,4 +285,3 @@ impl<'tcx> RustcPeekAt<'tcx> for IndirectlyMutableLocals<'_, 'tcx> { } } } -*/ From 1d737fb032b762e69e8d809c0e042d45e08b457d Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:41:26 -0800 Subject: [PATCH 0081/1250] Use `MaybeBorrowedLocals` for generator analyses It should have the same semantics as `HaveBeenBorrowedLocals` --- .../dataflow/impls/storage_liveness.rs | 46 ++++++++----------- src/librustc_mir/transform/generator.rs | 20 +++----- 2 files changed, 27 insertions(+), 39 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 040c13e8210..7508d71945e 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -1,8 +1,8 @@ pub use super::*; +use crate::dataflow::generic::{Results, ResultsRefCursor}; use crate::dataflow::BitDenotation; -use crate::dataflow::HaveBeenBorrowedLocals; -use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor}; +use crate::dataflow::MaybeBorrowedLocals; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; use std::cell::RefCell; @@ -69,22 +69,23 @@ impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { const BOTTOM_VALUE: bool = false; } +type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorrowedLocals>; + /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. pub struct RequiresStorage<'mir, 'tcx> { body: ReadOnlyBodyAndCache<'mir, 'tcx>, - borrowed_locals: - RefCell>>, + borrowed_locals: RefCell>, } impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { pub fn new( body: ReadOnlyBodyAndCache<'mir, 'tcx>, - borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>, + borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>, ) -> Self { RequiresStorage { body, - borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, *body)), + borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)), } } @@ -111,11 +112,12 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } fn before_statement_effect(&self, sets: &mut GenKillSet, loc: Location) { - // If we borrow or assign to a place then it needs storage for that - // statement. - self.check_for_borrow(sets, loc); - let stmt = &self.body[loc.block].statements[loc.statement_index]; + + // If a place is borrowed in a statement, it needs storage for that statement. + self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc); + + // If a place is assigned to in a statement, it needs storage for that statement. match stmt.kind { StatementKind::StorageDead(l) => sets.kill(l), StatementKind::Assign(box (ref place, _)) @@ -138,12 +140,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } fn before_terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { - self.check_for_borrow(sets, loc); + let terminator = self.body[loc.block].terminator(); - if let TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } = - self.body[loc.block].terminator().kind - { - sets.gen(local); + // If a place is borrowed in a terminator, it needs storage for that terminator. + self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc); + + if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind { + sets.gen(place.local); } } @@ -179,14 +182,6 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals }; visitor.visit_location(self.body, loc); } - - /// Gen locals that are newly borrowed. This includes borrowing any part of - /// a local (we rely on this behavior of `HaveBeenBorrowedLocals`). - fn check_for_borrow(&self, sets: &mut GenKillSet, loc: Location) { - let mut borrowed_locals = self.borrowed_locals.borrow_mut(); - borrowed_locals.seek(loc); - borrowed_locals.each_gen_bit(|l| sets.gen(l)); - } } impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> { @@ -195,8 +190,7 @@ impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> { } struct MoveVisitor<'a, 'mir, 'tcx> { - borrowed_locals: - &'a RefCell>>, + borrowed_locals: &'a RefCell>, sets: &'a mut GenKillSet, } @@ -204,7 +198,7 @@ impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> { fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { let mut borrowed_locals = self.borrowed_locals.borrow_mut(); - borrowed_locals.seek(loc); + borrowed_locals.seek_before(loc); if !borrowed_locals.contains(*local) { self.sets.kill(*local); } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a6fc6573178..cd00274afcc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -49,9 +49,10 @@ //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. +use crate::dataflow::generic::{Analysis, ResultsCursor}; use crate::dataflow::{do_dataflow, DataflowResultsCursor, DebugFormatted}; use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation}; -use crate::dataflow::{HaveBeenBorrowedLocals, MaybeStorageLive, RequiresStorage}; +use crate::dataflow::{MaybeBorrowedLocals, MaybeStorageLive, RequiresStorage}; use crate::transform::no_landing_pads::no_landing_pads; use crate::transform::simplify; use crate::transform::{MirPass, MirSource}; @@ -471,17 +472,10 @@ fn locals_live_across_suspend_points( // Calculate the MIR locals which have been previously // borrowed (even if they are still active). - let borrowed_locals_analysis = HaveBeenBorrowedLocals::new(body_ref); - let borrowed_locals_results = do_dataflow( - tcx, - body_ref, - def_id, - &[], - &dead_unwinds, - borrowed_locals_analysis, - |bd, p| DebugFormatted::new(&bd.body().local_decls[p]), - ); - let mut borrowed_locals_cursor = DataflowResultsCursor::new(&borrowed_locals_results, body_ref); + let borrowed_locals_results = + MaybeBorrowedLocals::new().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint(); + + let mut borrowed_locals_cursor = ResultsCursor::new(body_ref, &borrowed_locals_results); // Calculate the MIR locals that we actually need to keep storage around // for. @@ -521,7 +515,7 @@ fn locals_live_across_suspend_points( // If a borrow is converted to a raw reference, we must also assume that it lives // forever. Note that the final liveness is still bounded by the storage liveness // of the local, which happens using the `intersect` operation below. - borrowed_locals_cursor.seek(loc); + borrowed_locals_cursor.seek_before(loc); liveness.outs[block].union(borrowed_locals_cursor.get()); } From d045a17c4b032a858323f6c9bea698ee2e5920b7 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:42:31 -0800 Subject: [PATCH 0082/1250] Use `MaybeMutBorrowedLocals` for const-checking --- .../transform/check_consts/resolver.rs | 2 +- .../transform/check_consts/validation.rs | 31 ++++++++----------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index b804dc4b5b6..3e14cc6d32a 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -15,7 +15,7 @@ use crate::dataflow::{self as old_dataflow, generic as dataflow}; /// `FlowSensitiveAnalysis`. /// /// This transfer does nothing when encountering an indirect assignment. Consumers should rely on -/// the `IndirectlyMutableLocals` dataflow pass to see if a `Local` may have become qualified via +/// the `MaybeMutBorrowedLocals` dataflow pass to see if a `Local` may have become qualified via /// an indirect assignment or function call. struct TransferFunction<'a, 'mir, 'tcx, Q> { item: &'a Item<'mir, 'tcx>, diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index e9715f682b0..9fef62325f2 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -15,17 +15,19 @@ use rustc_span::Span; use std::borrow::Cow; use std::ops::Deref; -use self::old_dataflow::IndirectlyMutableLocals; use super::ops::{self, NonConstOp}; use super::qualifs::{self, HasMutInterior, NeedsDrop}; use super::resolver::FlowSensitiveAnalysis; use super::{is_lang_panic_fn, ConstKind, Item, Qualif}; use crate::const_eval::{is_const_fn, is_unstable_const_fn}; -use crate::dataflow::{self as old_dataflow, generic as dataflow}; -use dataflow::Analysis; +use crate::dataflow::generic::{self as dataflow, Analysis}; +use crate::dataflow::MaybeMutBorrowedLocals; +// We are using `MaybeMutBorrowedLocals` as a proxy for whether an item may have been mutated +// through a pointer prior to the given point. This is okay even though `MaybeMutBorrowedLocals` +// kills locals upon `StorageDead` because a local will never be used after a `StorageDead`. pub type IndirectlyMutableResults<'mir, 'tcx> = - old_dataflow::DataflowResultsCursor<'mir, 'tcx, IndirectlyMutableLocals<'mir, 'tcx>>; + dataflow::ResultsCursor<'mir, 'tcx, MaybeMutBorrowedLocals<'mir, 'tcx>>; struct QualifCursor<'a, 'mir, 'tcx, Q: Qualif> { cursor: dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'a, 'mir, 'tcx, Q>>, @@ -58,7 +60,7 @@ pub struct Qualifs<'a, 'mir, 'tcx> { impl Qualifs<'a, 'mir, 'tcx> { fn indirectly_mutable(&mut self, local: Local, location: Location) -> bool { - self.indirectly_mutable.seek(location); + self.indirectly_mutable.seek_before(location); self.indirectly_mutable.get().contains(local) } @@ -134,22 +136,15 @@ impl Deref for Validator<'_, 'mir, 'tcx> { impl Validator<'a, 'mir, 'tcx> { pub fn new(item: &'a Item<'mir, 'tcx>) -> Self { + let Item { tcx, body, def_id, param_env, .. } = *item; + let needs_drop = QualifCursor::new(NeedsDrop, item); let has_mut_interior = QualifCursor::new(HasMutInterior, item); - let dead_unwinds = BitSet::new_empty(item.body.basic_blocks().len()); - let indirectly_mutable = old_dataflow::do_dataflow( - item.tcx, - &*item.body, - item.def_id, - &item.tcx.get_attrs(item.def_id), - &dead_unwinds, - old_dataflow::IndirectlyMutableLocals::new(item.tcx, *item.body, item.param_env), - |_, local| old_dataflow::DebugFormatted::new(&local), - ); - - let indirectly_mutable = - old_dataflow::DataflowResultsCursor::new(indirectly_mutable, *item.body); + let indirectly_mutable = MaybeMutBorrowedLocals::new_mut_only(tcx, *body, param_env) + .into_engine(tcx, *body, def_id) + .iterate_to_fixpoint() + .into_results_cursor(*body); let qualifs = Qualifs { needs_drop, has_mut_interior, indirectly_mutable }; From 6f167e9c5f421613ff3de37771b1352cd98dd4f7 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 12 Feb 2020 13:42:56 -0800 Subject: [PATCH 0083/1250] Remove ignore and add explanation of indirect mutation peek test --- src/test/ui/mir-dataflow/indirect-mutation-offset.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs index 884c83b6616..caa307e269f 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.rs +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.rs @@ -1,6 +1,11 @@ // compile-flags: -Zunleash-the-miri-inside-of-you -// ignore-test Temporarily ignored while this analysis is migrated to the new framework. +// This test demonstrates a shortcoming of the `MaybeMutBorrowedLocals` analysis. It does not +// handle code that takes a reference to one field of a struct, then use pointer arithmetic to +// transform it to another field of that same struct that may have interior mutability. For now, +// this is UB, but this may change in the future. See [rust-lang/unsafe-code-guidelines#134]. +// +// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 #![feature(core_intrinsics, rustc_attrs, const_raw_ptr_deref)] From 91b4a24219f33b7ad28b5ba147d50bc160c6f56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 13 Feb 2020 00:00:00 +0000 Subject: [PATCH 0084/1250] Enable use after scope detection in the new LLVM pass manager Implementation of 08a1c566a792dcf9657d293155f7ada87746bb65 for the new LLVM pass manager, support for which landed in the meantime. --- src/rustllvm/PassWrapper.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 15e2251d763..8cebcaccfaa 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -761,14 +761,14 @@ LLVMRustOptimizeWithNewPassManager( } if (SanitizerOptions->SanitizeAddress) { - // FIXME: Rust does not expose the UseAfterScope option. PipelineStartEPCallbacks.push_back([&](ModulePassManager &MPM) { MPM.addPass(RequireAnalysisPass()); }); OptimizerLastEPCallbacks.push_back( [SanitizerOptions](FunctionPassManager &FPM, PassBuilder::OptimizationLevel Level) { FPM.addPass(AddressSanitizerPass( - /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover)); + /*CompileKernel=*/false, SanitizerOptions->SanitizeRecover, + /*UseAfterScope=*/true)); } ); PipelineStartEPCallbacks.push_back( From 30d4f1b78d997fb555388cb8ebea474ffb85794c Mon Sep 17 00:00:00 2001 From: spunit262 <45582704+spunit262@users.noreply.github.com> Date: Wed, 12 Feb 2020 17:46:15 -0700 Subject: [PATCH 0085/1250] Don't give invalid suggestion on desugared span. --- .../diagnostics/mutability_errors.rs | 88 ++++++++++--------- .../dont-print-desugared-async.stderr | 5 +- src/test/ui/nll/dont-print-desugared.stderr | 5 +- 3 files changed, 47 insertions(+), 51 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index d91f6edc980..b0a82bc2ba5 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -329,40 +329,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if self.body.local_decls[local].is_user_variable() => { let local_decl = &self.body.local_decls[local]; - let suggestion = match local_decl.local_info { - LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::ImplicitSelf(_))) => { - Some(suggest_ampmut_self(self.infcx.tcx, local_decl)) - } - - LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( - mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByValue(_), - opt_ty_info, - .. - }, - ))) => Some(suggest_ampmut( - self.infcx.tcx, - self.body, - local, - local_decl, - opt_ty_info, - )), - - LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( - mir::VarBindingForm { - binding_mode: ty::BindingMode::BindByReference(_), - .. - }, - ))) => { - let pattern_span = local_decl.source_info.span; - suggest_ref_mut(self.infcx.tcx, pattern_span) - .map(|replacement| (pattern_span, replacement)) - } - - LocalInfo::User(ClearCrossCrate::Clear) => bug!("saw cleared local state"), - - _ => unreachable!(), - }; let (pointer_sigil, pointer_desc) = if local_decl.ty.is_region_ptr() { ("&", "reference") @@ -370,17 +336,53 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ("*const", "pointer") }; - if let Some((err_help_span, suggested_code)) = suggestion { - err.span_suggestion( - err_help_span, - &format!("consider changing this to be a mutable {}", pointer_desc), - suggested_code, - Applicability::MachineApplicable, - ); - } - match self.local_names[local] { Some(name) if !local_decl.from_compiler_desugaring() => { + let suggestion = match local_decl.local_info { + LocalInfo::User(ClearCrossCrate::Set( + mir::BindingForm::ImplicitSelf(_), + )) => Some(suggest_ampmut_self(self.infcx.tcx, local_decl)), + + LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( + mir::VarBindingForm { + binding_mode: ty::BindingMode::BindByValue(_), + opt_ty_info, + .. + }, + ))) => Some(suggest_ampmut( + self.infcx.tcx, + self.body, + local, + local_decl, + opt_ty_info, + )), + + LocalInfo::User(ClearCrossCrate::Set(mir::BindingForm::Var( + mir::VarBindingForm { + binding_mode: ty::BindingMode::BindByReference(_), + .. + }, + ))) => { + let pattern_span = local_decl.source_info.span; + suggest_ref_mut(self.infcx.tcx, pattern_span) + .map(|replacement| (pattern_span, replacement)) + } + + LocalInfo::User(ClearCrossCrate::Clear) => { + bug!("saw cleared local state") + } + + _ => unreachable!(), + }; + + if let Some((err_help_span, suggested_code)) = suggestion { + err.span_suggestion( + err_help_span, + &format!("consider changing this to be a mutable {}", pointer_desc), + suggested_code, + Applicability::MachineApplicable, + ); + } err.span_label( span, format!( 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 2bf1e77f09b..d80467c7fa8 100644 --- a/src/test/ui/async-await/dont-print-desugared-async.stderr +++ b/src/test/ui/async-await/dont-print-desugared-async.stderr @@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable --> $DIR/dont-print-desugared-async.rs:5:20 | LL | async fn async_fn(&ref mut s: &[i32]) {} - | -^^^^^^^^^ - | || - | |cannot borrow as mutable through `&` reference - | help: consider changing this to be a mutable reference: `&mut ref mut s` + | ^^^^^^^^^ cannot borrow as mutable through `&` reference error: aborting due to previous error diff --git a/src/test/ui/nll/dont-print-desugared.stderr b/src/test/ui/nll/dont-print-desugared.stderr index 45d7cbcdfbe..88773def8b7 100644 --- a/src/test/ui/nll/dont-print-desugared.stderr +++ b/src/test/ui/nll/dont-print-desugared.stderr @@ -2,10 +2,7 @@ error[E0596]: cannot borrow data in a `&` reference as mutable --> $DIR/dont-print-desugared.rs:4:10 | LL | for &ref mut x in s {} - | -^^^^^^^^^ - | || - | |cannot borrow as mutable through `&` reference - | help: consider changing this to be a mutable reference: `&mut ref mut x` + | ^^^^^^^^^ cannot borrow as mutable through `&` reference error[E0597]: `y` does not live long enough --> $DIR/dont-print-desugared.rs:17:16 From cec0ed0219c4e4961b9e7a33419d716a5ddf0e5d Mon Sep 17 00:00:00 2001 From: Andreas Jonson Date: Tue, 11 Feb 2020 22:37:16 +0100 Subject: [PATCH 0086/1250] add selfprofiling for new llvm passmanager --- Cargo.lock | 1 + src/librustc_codegen_llvm/Cargo.toml | 1 + src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/profiling.rs | 58 ++++++++++++++++++ src/librustc_codegen_llvm/back/write.rs | 21 ++++++- src/librustc_codegen_llvm/lib.rs | 1 + src/librustc_codegen_llvm/llvm/ffi.rs | 7 +++ src/librustc_data_structures/profiling.rs | 11 ++++ src/librustc_session/options.rs | 2 +- src/rustllvm/PassWrapper.cpp | 65 ++++++++++++++++++++- 10 files changed, 165 insertions(+), 4 deletions(-) create mode 100644 src/librustc_codegen_llvm/back/profiling.rs diff --git a/Cargo.lock b/Cargo.lock index 149f02b4b8c..f44644cffa6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3559,6 +3559,7 @@ dependencies = [ "flate2", "libc", "log", + "measureme", "rustc", "rustc-demangle", "rustc_attr", diff --git a/src/librustc_codegen_llvm/Cargo.toml b/src/librustc_codegen_llvm/Cargo.toml index e7c0ee5ea76..c5e862ffc17 100644 --- a/src/librustc_codegen_llvm/Cargo.toml +++ b/src/librustc_codegen_llvm/Cargo.toml @@ -14,6 +14,7 @@ doctest = false bitflags = "1.0" flate2 = "1.0" libc = "0.2" +measureme = "0.7.1" log = "0.4" rustc = { path = "../librustc" } rustc-demangle = "0.1" diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index e3d69fc5c76..d7297ed4176 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -593,7 +593,7 @@ pub(crate) fn run_pass_manager( } else { opt_level }; - write::optimize_with_new_llvm_pass_manager(module, config, opt_level, opt_stage); + write::optimize_with_new_llvm_pass_manager(cgcx, module, config, opt_level, opt_stage); debug!("lto done"); return; } diff --git a/src/librustc_codegen_llvm/back/profiling.rs b/src/librustc_codegen_llvm/back/profiling.rs new file mode 100644 index 00000000000..d56ddac699b --- /dev/null +++ b/src/librustc_codegen_llvm/back/profiling.rs @@ -0,0 +1,58 @@ +use measureme::{event_id::SEPARATOR_BYTE, EventId, StringComponent, StringId}; +use rustc_data_structures::profiling::{SelfProfiler, TimingGuard}; +use std::ffi::{c_void, CStr}; +use std::os::raw::c_char; +use std::sync::Arc; + +fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &str) -> EventId { + let pass_name = profiler.get_or_alloc_cached_string(pass_name); + let mut components = vec![StringComponent::Ref(pass_name)]; + // handle that LazyCallGraph::SCC is a comma separated list within parentheses + let parentheses: &[_] = &['(', ')']; + let trimed = ir_name.trim_matches(parentheses); + for part in trimed.split(", ") { + let demangled_ir_name = rustc_demangle::demangle(part).to_string(); + let ir_name = profiler.get_or_alloc_cached_string(demangled_ir_name); + components.push(StringComponent::Value(SEPARATOR_BYTE)); + components.push(StringComponent::Ref(ir_name)); + } + EventId::from_label(profiler.alloc_string(components.as_slice())) +} + +pub struct LlvmSelfProfiler<'a> { + profiler: Arc, + stack: Vec>, + llvm_pass_event_kind: StringId, +} + +impl<'a> LlvmSelfProfiler<'a> { + pub fn new(profiler: Arc) -> Self { + let llvm_pass_event_kind = profiler.alloc_string("LLVM Pass"); + Self { profiler, stack: Vec::default(), llvm_pass_event_kind } + } + + fn before_pass_callback(&'a mut self, pass_name: &str, ir_name: &str) { + let event_id = llvm_args_to_string_id(&self.profiler, pass_name, ir_name); + + self.stack.push(TimingGuard::start(&self.profiler, self.llvm_pass_event_kind, event_id)); + } + fn after_pass_callback(&mut self) { + self.stack.pop(); + } +} + +pub unsafe extern "C" fn selfprofile_before_pass_callback( + llvm_self_profiler: *mut c_void, + pass_name: *const c_char, + ir_name: *const c_char, +) { + let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>); + let pass_name = CStr::from_ptr(pass_name).to_str().expect("valid UTF-8"); + let ir_name = CStr::from_ptr(ir_name).to_str().expect("valid UTF-8"); + llvm_self_profiler.before_pass_callback(pass_name, ir_name); +} + +pub unsafe extern "C" fn selfprofile_after_pass_callback(llvm_self_profiler: *mut c_void) { + let llvm_self_profiler = &mut *(llvm_self_profiler as *mut LlvmSelfProfiler<'_>); + llvm_self_profiler.after_pass_callback(); +} diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 9008970847a..a215ef81bc9 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -1,6 +1,9 @@ use crate::attributes; use crate::back::bytecode; use crate::back::lto::ThinBuffer; +use crate::back::profiling::{ + selfprofile_after_pass_callback, selfprofile_before_pass_callback, LlvmSelfProfiler, +}; use crate::base; use crate::common; use crate::consts; @@ -348,6 +351,7 @@ pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool { } pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( + cgcx: &CodegenContext, module: &ModuleCodegen, config: &ModuleConfig, opt_level: config::OptLevel, @@ -372,6 +376,13 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( None }; + let llvm_selfprofiler = if cgcx.prof.llvm_recording_enabled() { + let mut llvm_profiler = LlvmSelfProfiler::new(cgcx.prof.get_self_profiler().unwrap()); + &mut llvm_profiler as *mut _ as *mut c_void + } else { + std::ptr::null_mut() + }; + // FIXME: NewPM doesn't provide a facility to pass custom InlineParams. // We would have to add upstream support for this first, before we can support // config.inline_threshold and our more aggressive default thresholds. @@ -394,6 +405,9 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( sanitizer_options.as_ref(), pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), + llvm_selfprofiler, + selfprofile_before_pass_callback, + selfprofile_after_pass_callback, ); } @@ -428,10 +442,15 @@ pub(crate) unsafe fn optimize( _ if cgcx.opts.cg.linker_plugin_lto.enabled() => llvm::OptStage::PreLinkThinLTO, _ => llvm::OptStage::PreLinkNoLTO, }; - optimize_with_new_llvm_pass_manager(module, config, opt_level, opt_stage); + optimize_with_new_llvm_pass_manager(cgcx, module, config, opt_level, opt_stage); return Ok(()); } + if cgcx.prof.llvm_recording_enabled() { + diag_handler + .warn("`-Z self-profile-events = llvm` requires `-Z new-llvm-pass-manager`"); + } + // Create the two optimizing pass managers. These mirror what clang // does, and are by populated by LLVM's default PassManagerBuilder. // Each manager has a different set of passes, but they also share diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index 7aaa70d6ec4..b1085ba1703 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -44,6 +44,7 @@ mod back { pub mod archive; pub mod bytecode; pub mod lto; + mod profiling; pub mod write; } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index f12bfe0e80a..808094eca91 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -709,6 +709,10 @@ extern "C" { pub type ModuleBuffer; } +pub type SelfProfileBeforePassCallback = + unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); +pub type SelfProfileAfterPassCallback = unsafe extern "C" fn(*mut c_void); + extern "C" { pub fn LLVMRustInstallFatalErrorHandler(); @@ -1945,6 +1949,9 @@ extern "C" { SanitizerOptions: Option<&SanitizerOptions>, PGOGenPath: *const c_char, PGOUsePath: *const c_char, + llvm_selfprofiler: *mut c_void, + begin_callback: SelfProfileBeforePassCallback, + end_callback: SelfProfileAfterPassCallback, ); pub fn LLVMRustPrintModule( M: &'a Module, diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index debda9f0a0a..1d0ac4f4907 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -127,6 +127,7 @@ bitflags::bitflags! { const QUERY_KEYS = 1 << 5; const FUNCTION_ARGS = 1 << 6; + const LLVM = 1 << 7; const DEFAULT = Self::GENERIC_ACTIVITIES.bits | Self::QUERY_PROVIDERS.bits | @@ -150,6 +151,7 @@ const EVENT_FILTERS_BY_NAME: &[(&str, EventFilter)] = &[ ("query-keys", EventFilter::QUERY_KEYS), ("function-args", EventFilter::FUNCTION_ARGS), ("args", EventFilter::ARGS), + ("llvm", EventFilter::LLVM), ]; /// Something that uniquely identifies a query invocation. @@ -364,6 +366,15 @@ impl SelfProfilerRef { pub fn enabled(&self) -> bool { self.profiler.is_some() } + + #[inline] + pub fn llvm_recording_enabled(&self) -> bool { + self.event_filter_mask.contains(EventFilter::LLVM) + } + #[inline] + pub fn get_self_profiler(&self) -> Option> { + self.profiler.clone() + } } pub struct SelfProfiler { diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index a794670d7b8..d3163fa3564 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -940,7 +940,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "specifies which kinds of events get recorded by the self profiler; for example: `-Z self-profile-events=default,query-keys` all options: none, all, default, generic-activity, query-provider, query-cache-hit - query-blocked, incr-cache-load, query-keys"), + query-blocked, incr-cache-load, query-keys, function-args, args, llvm"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emits a section containing stack size metadata"), plt: Option = (None, parse_opt_bool, [TRACKED], diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 15e2251d763..2c283149be8 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -640,6 +640,62 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Success; } +extern "C" typedef void (*LLVMRustSelfProfileBeforePassCallback)(void*, // LlvmSelfProfiler + const char*, // pass name + const char*); // IR name +extern "C" typedef void (*LLVMRustSelfProfileAfterPassCallback)(void*); // LlvmSelfProfiler + +#if LLVM_VERSION_GE(9, 0) + +std::string LLVMRustwrappedIrGetName(const llvm::Any &WrappedIr) { + if (any_isa(WrappedIr)) + return any_cast(WrappedIr)->getName().str(); + if (any_isa(WrappedIr)) + return any_cast(WrappedIr)->getName().str(); + if (any_isa(WrappedIr)) + return any_cast(WrappedIr)->getName().str(); + if (any_isa(WrappedIr)) + return any_cast(WrappedIr)->getName(); + return ""; +} + + +void LLVMSelfProfileInitializeCallbacks( + PassInstrumentationCallbacks& PIC, void* LlvmSelfProfiler, + LLVMRustSelfProfileBeforePassCallback BeforePassCallback, + LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { + PIC.registerBeforePassCallback([LlvmSelfProfiler, BeforePassCallback]( + StringRef Pass, llvm::Any Ir) { + std::string PassName = Pass.str(); + std::string IrName = LLVMRustwrappedIrGetName(Ir); + BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); + return true; + }); + + PIC.registerAfterPassCallback( + [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { + AfterPassCallback(LlvmSelfProfiler); + }); + + PIC.registerAfterPassInvalidatedCallback( + [LlvmSelfProfiler, AfterPassCallback](StringRef Pass) { + AfterPassCallback(LlvmSelfProfiler); + }); + + PIC.registerBeforeAnalysisCallback([LlvmSelfProfiler, BeforePassCallback]( + StringRef Pass, llvm::Any Ir) { + std::string PassName = Pass.str(); + std::string IrName = LLVMRustwrappedIrGetName(Ir); + BeforePassCallback(LlvmSelfProfiler, PassName.c_str(), IrName.c_str()); + }); + + PIC.registerAfterAnalysisCallback( + [LlvmSelfProfiler, AfterPassCallback](StringRef Pass, llvm::Any Ir) { + AfterPassCallback(LlvmSelfProfiler); + }); +} +#endif + enum class LLVMRustOptStage { PreLinkNoLTO, PreLinkThinLTO, @@ -666,7 +722,10 @@ LLVMRustOptimizeWithNewPassManager( bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls, LLVMRustSanitizerOptions *SanitizerOptions, - const char *PGOGenPath, const char *PGOUsePath) { + const char *PGOGenPath, const char *PGOUsePath, + void* LlvmSelfProfiler, + LLVMRustSelfProfileBeforePassCallback BeforePassCallback, + LLVMRustSelfProfileAfterPassCallback AfterPassCallback) { #if LLVM_VERSION_GE(9, 0) Module *TheModule = unwrap(ModuleRef); TargetMachine *TM = unwrap(TMRef); @@ -685,6 +744,10 @@ LLVMRustOptimizeWithNewPassManager( StandardInstrumentations SI; SI.registerCallbacks(PIC); + if (LlvmSelfProfiler){ + LLVMSelfProfileInitializeCallbacks(PIC,LlvmSelfProfiler,BeforePassCallback,AfterPassCallback); + } + Optional PGOOpt; if (PGOGenPath) { assert(!PGOUsePath); From 57a62f5335c1e8178802d00dfac94212726ee240 Mon Sep 17 00:00:00 2001 From: Jethro Beekman Date: Thu, 13 Feb 2020 10:16:28 +0100 Subject: [PATCH 0087/1250] Add comment to SGX entry code --- src/libstd/sys/sgx/abi/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libstd/sys/sgx/abi/entry.S b/src/libstd/sys/sgx/abi/entry.S index ed4db287229..1f06c9da3a9 100644 --- a/src/libstd/sys/sgx/abi/entry.S +++ b/src/libstd/sys/sgx/abi/entry.S @@ -151,6 +151,7 @@ elf_entry: pushfq andq $~0x40400, (%rsp) popfq +/* check for abort */ bt $0,.Laborted(%rip) jc .Lreentry_panic .endm From 4f17dce4dc722e56d5d5069e7317feb17c1de5cc Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 07:15:43 +0100 Subject: [PATCH 0088/1250] StripUnconfigured::in_cfg: simplify with slice patterns --- src/librustc_parse/config.rs | 52 +++++++++++------------------------- 1 file changed, 16 insertions(+), 36 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8dec64c579e..3c37501be41 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -347,7 +347,13 @@ impl<'a> StripUnconfigured<'a> { if !is_cfg(attr) { return true; } - + let meta_item = match validate_attr::parse_meta(self.sess, attr) { + Ok(meta_item) => meta_item, + Err(mut err) => { + err.emit(); + return true; + } + }; let error = |span, msg, suggestion: &str| { let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); if !suggestion.is_empty() { @@ -361,41 +367,15 @@ impl<'a> StripUnconfigured<'a> { err.emit(); true }; - - let meta_item = match validate_attr::parse_meta(self.sess, attr) { - Ok(meta_item) => meta_item, - Err(mut err) => { - err.emit(); - return true; - } - }; - let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() { - nested_meta_items - } else { - return error( - meta_item.span, - "`cfg` is not followed by parentheses", - "cfg(/* predicate */)", - ); - }; - - if nested_meta_items.is_empty() { - return error(meta_item.span, "`cfg` predicate is not specified", ""); - } else if nested_meta_items.len() > 1 { - return error( - nested_meta_items.last().unwrap().span(), - "multiple `cfg` predicates are specified", - "", - ); - } - - match nested_meta_items[0].meta_item() { - Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), - None => error( - nested_meta_items[0].span(), - "`cfg` predicate key cannot be a literal", - "", - ), + let span = meta_item.span; + match meta_item.meta_item_list() { + None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"), + Some([]) => error(span, "`cfg` predicate is not specified", ""), + Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""), + Some([single]) => match single.meta_item() { + Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), + None => error(single.span(), "`cfg` predicate key cannot be a literal", ""), + }, } }) } From b8b32a9be341761c3927843c27042febbe8ea39a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 07:42:19 +0100 Subject: [PATCH 0089/1250] simplify config::features --- src/librustc_parse/config.rs | 37 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 3c37501be41..3f544494704 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -207,30 +207,29 @@ pub fn features( edition: Edition, allow_features: &Option>, ) -> (ast::Crate, Features) { - let features; - { - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; + let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let unconfigured_attrs = krate.attrs.clone(); - let err_count = sess.span_diagnostic.err_count(); - if let Some(attrs) = strip_unconfigured.configure(krate.attrs) { - krate.attrs = attrs; - } else { - // the entire crate is unconfigured + let unconfigured_attrs = krate.attrs.clone(); + let diag = &sess.span_diagnostic; + let err_count = diag.err_count(); + let features = match strip_unconfigured.configure(krate.attrs) { + None => { + // The entire crate is unconfigured. krate.attrs = Vec::new(); krate.module.items = Vec::new(); - return (krate, Features::default()); + Features::default() } - - features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features); - - // Avoid reconfiguring malformed `cfg_attr`s - if err_count == sess.span_diagnostic.err_count() { - strip_unconfigured.features = Some(&features); - strip_unconfigured.configure(unconfigured_attrs); + Some(attrs) => { + krate.attrs = attrs; + let features = get_features(diag, &krate.attrs, edition, allow_features); + if err_count == diag.err_count() { + // Avoid reconfiguring malformed `cfg_attr`s. + strip_unconfigured.features = Some(&features); + strip_unconfigured.configure(unconfigured_attrs); + } + features } - } - + }; (krate, features) } From 64ea295fe92236e5e5162722f5242f5837af7ee1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:14:31 +0100 Subject: [PATCH 0090/1250] expand: extract error_derive_forbidden_on_non_adt --- src/librustc_expand/expand.rs | 44 +++++++++++++++++------------------ 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9..c7c7f62918d 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -451,28 +451,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; if !item.derive_allowed() { - let attr = attr::find_by_name(item.attrs(), sym::derive) - .expect("`derive` attribute should exist"); - let span = attr.span; - let mut err = self.cx.struct_span_err( - span, - "`derive` may only be applied to structs, enums and unions", - ); - if let ast::AttrStyle::Inner = attr.style { - let trait_list = derives - .iter() - .map(|t| pprust::path_to_string(t)) - .collect::>(); - let suggestion = format!("#[derive({})]", trait_list.join(", ")); - err.span_suggestion( - span, - "try an outer attribute", - suggestion, - // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT - Applicability::MaybeIncorrect, - ); - } - err.emit(); + self.error_derive_forbidden_on_non_adt(&derives, &item); } let mut item = self.fully_configure(item); @@ -521,6 +500,27 @@ impl<'a, 'b> MacroExpander<'a, 'b> { fragment_with_placeholders } + fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) { + let attr = + attr::find_by_name(item.attrs(), sym::derive).expect("`derive` attribute should exist"); + let span = attr.span; + let mut err = self + .cx + .struct_span_err(span, "`derive` may only be applied to structs, enums and unions"); + if let ast::AttrStyle::Inner = attr.style { + let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::>(); + let suggestion = format!("#[derive({})]", trait_list.join(", ")); + err.span_suggestion( + span, + "try an outer attribute", + suggestion, + // We don't 𝑘𝑛𝑜𝑤 that the following item is an ADT + Applicability::MaybeIncorrect, + ); + } + err.emit(); + } + fn resolve_imports(&mut self) { if self.monotonic { self.cx.resolver.resolve_imports(); From 0633a0e3801e4efc9ab07bf811e442bd379ce93a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 8 Feb 2020 22:21:20 +0100 Subject: [PATCH 0091/1250] remove Panic variant from InterpError --- src/librustc/mir/interpret/error.rs | 22 +++-- src/librustc/mir/interpret/mod.rs | 14 ---- src/librustc_mir/const_eval/error.rs | 21 +++-- src/librustc_mir/const_eval/machine.rs | 62 ++++++++++---- src/librustc_mir/interpret/intrinsics.rs | 26 ------ .../interpret/intrinsics/caller_location.rs | 12 +-- src/librustc_mir/transform/const_prop.rs | 83 +++++++++---------- 7 files changed, 117 insertions(+), 123 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 86e7bb28e00..e819dfbacd8 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -139,7 +139,6 @@ impl<'tcx> ConstEvalErr<'tcx> { lint_root: Option, ) -> Result<(), ErrorHandled> { let must_error = match self.error { - InterpError::MachineStop(_) => bug!("CTFE does not stop"), err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => { return Err(ErrorHandled::TooGeneric); } @@ -149,9 +148,18 @@ impl<'tcx> ConstEvalErr<'tcx> { }; trace!("reporting const eval failure at {:?}", self.span); + let err_msg = match &self.error { + InterpError::MachineStop(msg) => { + // A custom error (`ConstEvalErrKind` in `librustc_mir/interp/const_eval/error.rs`). + // Should be turned into a string by now. + msg.downcast_ref::().expect("invalid MachineStop payload").clone() + } + err => err.to_string(), + }; + let add_span_labels = |err: &mut DiagnosticBuilder<'_>| { if !must_error { - err.span_label(self.span, self.error.to_string()); + err.span_label(self.span, err_msg.clone()); } // Skip the last, which is just the environment of the constant. The stacktrace // is sometimes empty because we create "fake" eval contexts in CTFE to do work @@ -183,7 +191,7 @@ impl<'tcx> ConstEvalErr<'tcx> { ); } else { let mut err = if must_error { - struct_error(tcx, &self.error.to_string()) + struct_error(tcx, &err_msg) } else { struct_error(tcx, message) }; @@ -259,6 +267,9 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { } } +/// Information about a panic. +/// +/// FIXME: this is not actually an InterpError, and should probably be moved to another module. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum PanicInfo { Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, @@ -616,8 +627,6 @@ impl fmt::Debug for ResourceExhaustionInfo { } pub enum InterpError<'tcx> { - /// The program panicked. - Panic(PanicInfo), /// The program caused undefined behavior. UndefinedBehavior(UndefinedBehaviorInfo), /// The program did something the interpreter does not support (some of these *might* be UB @@ -650,8 +659,7 @@ impl fmt::Debug for InterpError<'_> { InvalidProgram(ref msg) => write!(f, "{:?}", msg), UndefinedBehavior(ref msg) => write!(f, "{:?}", msg), ResourceExhaustion(ref msg) => write!(f, "{:?}", msg), - Panic(ref msg) => write!(f, "{:?}", msg), - MachineStop(_) => write!(f, "machine caused execution to stop"), + MachineStop(_) => bug!("unhandled MachineStop"), } } } diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index 54e196f4b33..b4cfd860152 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -37,15 +37,6 @@ macro_rules! err_ub_format { ($($tt:tt)*) => { err_ub!(Ub(format!($($tt)*))) }; } -#[macro_export] -macro_rules! err_panic { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::Panic( - $crate::mir::interpret::PanicInfo::$($tt)* - ) - }; -} - #[macro_export] macro_rules! err_exhaust { ($($tt:tt)*) => { @@ -80,11 +71,6 @@ macro_rules! throw_ub_format { ($($tt:tt)*) => { throw_ub!(Ub(format!($($tt)*))) }; } -#[macro_export] -macro_rules! throw_panic { - ($($tt:tt)*) => { return Err(err_panic!($($tt)*).into()) }; -} - #[macro_export] macro_rules! throw_exhaust { ($($tt:tt)*) => { return Err(err_exhaust!($($tt)*).into()) }; diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index c2db3c31f85..e0e78546099 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -2,32 +2,39 @@ use std::error::Error; use std::fmt; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpErrorInfo, Machine}; +use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; + +/// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] -pub enum ConstEvalError { +pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, + Panic(PanicInfo), } -impl<'tcx> Into> for ConstEvalError { +// The errors become `MachineStop` with plain strings when being raised. +// `ConstEvalErr` (in `librustc/mir/interpret/error.rs`) knows to +// handle these. +impl<'tcx> Into> for ConstEvalErrKind { fn into(self) -> InterpErrorInfo<'tcx> { - err_unsup!(Unsupported(self.to_string())).into() + InterpError::MachineStop(Box::new(self.to_string())).into() } } -impl fmt::Display for ConstEvalError { +impl fmt::Display for ConstEvalErrKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use self::ConstEvalError::*; + use self::ConstEvalErrKind::*; match *self { NeedsRfc(ref msg) => { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } ConstAccessesStatic => write!(f, "constant accesses static"), + Panic(ref msg) => write!(f, "{:?}", msg), } } } -impl Error for ConstEvalError {} +impl Error for ConstEvalErrKind {} /// Turn an interpreter error into something to report to the user. /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 1aed91baba6..688eee05dda 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -9,10 +9,11 @@ use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::Span; +use rustc_span::symbol::Symbol; use crate::interpret::{ self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + Memory, MemoryKind, OpTy, PanicInfo, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -56,6 +57,32 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { self.dump_place(*dest); return Ok(true); } + + /// "Intercept" a function call to a panic-related function + /// because we have something special to do for it. + /// Returns `true` if an intercept happened. + pub fn hook_panic_fn( + &mut self, + span: Span, + instance: ty::Instance<'tcx>, + args: &[OpTy<'tcx>], + ) -> InterpResult<'tcx, bool> { + let def_id = instance.def_id(); + if Some(def_id) == self.tcx.lang_items().panic_fn() + || Some(def_id) == self.tcx.lang_items().begin_panic_fn() + { + // &'static str + assert!(args.len() == 1); + + let msg_place = self.deref_operand(args[0])?; + let msg = Symbol::intern(self.read_str(msg_place)?); + let span = self.find_closest_untracked_caller_location().unwrap_or(span); + let (file, line, col) = self.location_triple_for_span(span); + Err(ConstEvalErrKind::Panic(PanicInfo::Panic { msg, file, line, col }).into()) + } else { + Ok(false) + } + } } /// Number of steps until the detector even starts doing anything. @@ -212,7 +239,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Ok(body) => *body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { - return Err(ConstEvalError::NeedsRfc(format!( + return Err(ConstEvalErrKind::NeedsRfc(format!( "calling extern function `{}`", path )) @@ -246,7 +273,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } // An intrinsic that we do not support let intrinsic_name = ecx.tcx.item_name(instance.def_id()); - Err(ConstEvalError::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()) + Err(ConstEvalErrKind::NeedsRfc(format!("calling intrinsic `{}`", intrinsic_name)).into()) } fn assert_panic( @@ -256,7 +283,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _unwind: Option, ) -> InterpResult<'tcx> { use rustc::mir::interpret::PanicInfo::*; - Err(match msg { + // Convert `PanicInfo` to `PanicInfo`. + let err = match msg { BoundsCheck { ref len, ref index } => { let len = ecx .read_immediate(ecx.eval_operand(len, None)?) @@ -268,21 +296,21 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, .expect("can't eval index") .to_scalar()? .to_machine_usize(&*ecx)?; - err_panic!(BoundsCheck { len, index }) + BoundsCheck { len, index } } - Overflow(op) => err_panic!(Overflow(*op)), - OverflowNeg => err_panic!(OverflowNeg), - DivisionByZero => err_panic!(DivisionByZero), - RemainderByZero => err_panic!(RemainderByZero), - ResumedAfterReturn(generator_kind) => err_panic!(ResumedAfterReturn(*generator_kind)), - ResumedAfterPanic(generator_kind) => err_panic!(ResumedAfterPanic(*generator_kind)), + Overflow(op) => Overflow(*op), + OverflowNeg => OverflowNeg, + DivisionByZero => DivisionByZero, + RemainderByZero => RemainderByZero, + ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind), + ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind), Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), - } - .into()) + }; + Err(ConstEvalErrKind::Panic(err).into()) } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { - Err(ConstEvalError::NeedsRfc("pointer-to-integer cast".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("pointer-to-integer cast".to_string()).into()) } fn binary_ptr_op( @@ -291,7 +319,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _left: ImmTy<'tcx>, _right: ImmTy<'tcx>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { - Err(ConstEvalError::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } fn find_foreign_static( @@ -321,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, _ecx: &mut InterpCx<'mir, 'tcx, Self>, _dest: PlaceTy<'tcx>, ) -> InterpResult<'tcx> { - Err(ConstEvalError::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) + Err(ConstEvalErrKind::NeedsRfc("heap allocations via `box` keyword".to_string()).into()) } fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { @@ -355,7 +383,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, if memory_extra.can_access_statics { Ok(()) } else { - Err(ConstEvalError::ConstAccessesStatic.into()) + Err(ConstEvalErrKind::ConstAccessesStatic.into()) } } } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index f85da760ada..a83b5412790 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -376,32 +376,6 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Ok(true) } - /// "Intercept" a function call to a panic-related function - /// because we have something special to do for it. - /// Returns `true` if an intercept happened. - pub fn hook_panic_fn( - &mut self, - span: Span, - instance: ty::Instance<'tcx>, - args: &[OpTy<'tcx, M::PointerTag>], - ) -> InterpResult<'tcx, bool> { - let def_id = instance.def_id(); - if Some(def_id) == self.tcx.lang_items().panic_fn() - || Some(def_id) == self.tcx.lang_items().begin_panic_fn() - { - // &'static str - assert!(args.len() == 1); - - let msg_place = self.deref_operand(args[0])?; - let msg = Symbol::intern(self.read_str(msg_place)?); - let span = self.find_closest_untracked_caller_location().unwrap_or(span); - let (file, line, col) = self.location_triple_for_span(span); - throw_panic!(Panic { msg, file, line, col }) - } else { - return Ok(false); - } - } - pub fn exact_div( &mut self, a: ImmTy<'tcx, M::PointerTag>, diff --git a/src/librustc_mir/interpret/intrinsics/caller_location.rs b/src/librustc_mir/interpret/intrinsics/caller_location.rs index 0525108d2d1..566601f0cae 100644 --- a/src/librustc_mir/interpret/intrinsics/caller_location.rs +++ b/src/librustc_mir/interpret/intrinsics/caller_location.rs @@ -54,12 +54,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { location } - pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> { - let (file, line, column) = self.location_triple_for_span(span); - self.alloc_caller_location(file, line, column) - } - - pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) { + crate fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) { let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span); let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo()); ( @@ -68,4 +63,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { caller.col_display as u32 + 1, ) } + + pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> { + let (file, line, column) = self.location_triple_for_span(span); + self.alloc_caller_location(file, line, column) + } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index a7da4f7c164..43a6382646f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpResult, PanicInfo, Scalar}; +use rustc::mir::interpret::{InterpError, InterpResult, PanicInfo, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; @@ -25,7 +25,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::vec::IndexVec; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use syntax::ast::Mutability; use crate::const_eval::error_to_const_error; @@ -410,15 +410,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn use_ecx(&mut self, source_info: SourceInfo, f: F) -> Option + fn use_ecx(&mut self, f: F) -> Option where F: FnOnce(&mut Self) -> InterpResult<'tcx, T>, { - self.ecx.tcx.span = source_info.span; - // FIXME(eddyb) move this to the `Panic(_)` error case, so that - // `f(self)` is always called, and that the only difference when the - // scope's `local_data` is missing, is that the lint isn't emitted. - let lint_root = self.lint_root(source_info)?; let r = match f(self) { Ok(val) => Some(val), Err(error) => { @@ -447,20 +442,10 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | ResourceExhaustion(_) => { // Ignore these errors. } - Panic(_) => { - let diagnostic = error_to_const_error(&self.ecx, error); - diagnostic.report_as_lint( - self.ecx.tcx, - "this expression will panic at runtime", - lint_root, - None, - ); - } } None } }; - self.ecx.tcx.span = DUMMY_SP; r } @@ -504,37 +489,47 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option> { + fn eval_place(&mut self, place: &Place<'tcx>) -> Option> { trace!("eval_place(place={:?})", place); - self.use_ecx(source_info, |this| this.ecx.eval_place_to_op(place, None)) + self.use_ecx(|this| this.ecx.eval_place_to_op(place, None)) } fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option> { match *op { Operand::Constant(ref c) => self.eval_constant(c, source_info), - Operand::Move(ref place) | Operand::Copy(ref place) => { - self.eval_place(place, source_info) - } + Operand::Move(ref place) | Operand::Copy(ref place) => self.eval_place(place), } } + fn report_panic_as_lint(&self, source_info: SourceInfo, panic: PanicInfo) -> Option<()> { + // Somewhat convoluted way to re-use the CTFE error reporting code. + let lint_root = self.lint_root(source_info)?; + let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); + let mut diagnostic = error_to_const_error(&self.ecx, error.into()); + diagnostic.span = source_info.span; // fix the span + diagnostic.report_as_lint( + self.tcx.at(source_info.span), + "this expression will panic at runtime", + lint_root, + None, + ); + None + } + fn check_unary_op( &mut self, op: UnOp, arg: &Operand<'tcx>, source_info: SourceInfo, ) -> Option<()> { - self.use_ecx(source_info, |this| { + if self.use_ecx(|this| { let val = this.ecx.read_immediate(this.ecx.eval_operand(arg, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; - - if overflow { - assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - throw_panic!(OverflowNeg); - } - - Ok(()) - })?; + Ok(overflow) + })? { + assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); + self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; + } Some(()) } @@ -548,9 +543,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { place_layout: TyLayout<'tcx>, overflow_check: bool, ) -> Option<()> { - let r = self.use_ecx(source_info, |this| { - this.ecx.read_immediate(this.ecx.eval_operand(right, None)?) - })?; + let r = + self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; if op == BinOp::Shr || op == BinOp::Shl { let left_bits = place_layout.size.bits(); let right_size = r.layout.size; @@ -575,16 +569,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // in MIR. However, if overflow checking is disabled, then there won't be any // `Assert` statement and so we have to do additional checking here. if !overflow_check { - self.use_ecx(source_info, |this| { + if self.use_ecx(|this| { let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; - - if overflow { - throw_panic!(Overflow(op)); - } - - Ok(()) - })?; + Ok(overflow) + })? { + self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; + } } Some(()) @@ -642,7 +633,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { _ => {} } - self.use_ecx(source_info, |this| { + self.use_ecx(|this| { trace!("calling eval_rvalue_into_place(rvalue = {:?}, place = {:?})", rvalue, place); this.ecx.eval_rvalue_into_place(rvalue, place)?; Ok(()) @@ -675,7 +666,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // FIXME> figure out what tho do when try_read_immediate fails - let imm = self.use_ecx(source_info, |this| this.ecx.try_read_immediate(value)); + let imm = self.use_ecx(|this| this.ecx.try_read_immediate(value)); if let Some(Ok(imm)) = imm { match *imm { @@ -698,7 +689,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { if let ty::Tuple(substs) = ty { // Only do it if tuple is also a pair with two scalars if substs.len() == 2 { - let opt_ty1_ty2 = self.use_ecx(source_info, |this| { + let opt_ty1_ty2 = self.use_ecx(|this| { let ty1 = substs[0].expect_ty(); let ty2 = substs[1].expect_ty(); let ty_is_scalar = |ty| { From c5709ff6b779d88c0d432f6ed8731fde6e55c090 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 8 Feb 2020 23:01:36 +0100 Subject: [PATCH 0092/1250] const-prop: handle overflow_check consistently for all operators --- src/librustc_mir/transform/const_prop.rs | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 43a6382646f..5c6c003b3a6 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -541,7 +541,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { right: &Operand<'tcx>, source_info: SourceInfo, place_layout: TyLayout<'tcx>, - overflow_check: bool, ) -> Option<()> { let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; @@ -564,18 +563,14 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - // If overflow checking is enabled (like in debug mode by default), - // then we'll already catch overflow when we evaluate the `Assert` statement - // in MIR. However, if overflow checking is disabled, then there won't be any - // `Assert` statement and so we have to do additional checking here. - if !overflow_check { - if self.use_ecx(|this| { - let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; - let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; - Ok(overflow) - })? { - self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; - } + // The remaining operators are handled through `overflowing_binary_op`. + // FIXME: Why do we not also do this for `Shr` and `Shl`? + if self.use_ecx(|this| { + let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; + let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; + Ok(overflow) + })? { + self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; } Some(()) @@ -618,9 +613,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Additional checking: check for overflows on integer binary operations and report // them to the user as lints. - Rvalue::BinaryOp(op, left, right) => { + Rvalue::BinaryOp(op, left, right) if !overflow_check => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - self.check_binary_op(*op, left, right, source_info, place_layout, overflow_check)?; + self.check_binary_op(*op, left, right, source_info, place_layout)?; } // Do not try creating references (#67862) From f3ff02bdd85255ad75bae40aad53e520e37a8e4a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Feb 2020 16:51:36 +0100 Subject: [PATCH 0093/1250] remove PanicInfo::Panic variant that MIR does not use or need --- src/librustc/mir/interpret/error.rs | 9 ++------- src/librustc/mir/mod.rs | 6 ++---- src/librustc/mir/visit.rs | 2 +- src/librustc_mir/const_eval/error.rs | 10 ++++++++-- src/librustc_mir/const_eval/machine.rs | 7 +++---- 5 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index e819dfbacd8..da8c0bf266f 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -11,7 +11,6 @@ use hir::GeneratorKind; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_macros::HashStable; -use rustc_span::symbol::Symbol; use rustc_span::{Pos, Span}; use rustc_target::spec::abi::Abi; use std::{any::Any, env, fmt}; @@ -272,7 +271,6 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { /// FIXME: this is not actually an InterpError, and should probably be moved to another module. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] pub enum PanicInfo { - Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, BoundsCheck { len: O, index: O }, Overflow(mir::BinOp), OverflowNeg, @@ -288,7 +286,7 @@ pub type AssertMessage<'tcx> = PanicInfo>; impl PanicInfo { /// Getting a description does not require `O` to be printable, and does not /// require allocation. - /// The caller is expected to handle `Panic` and `BoundsCheck` separately. + /// The caller is expected to handle `BoundsCheck` separately. pub fn description(&self) -> &'static str { use PanicInfo::*; match self { @@ -307,7 +305,7 @@ impl PanicInfo { ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - Panic { .. } | BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + BoundsCheck { .. } => bug!("Unexpected PanicInfo"), } } } @@ -316,9 +314,6 @@ impl fmt::Debug for PanicInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use PanicInfo::*; match self { - Panic { ref msg, line, col, ref file } => { - write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) - } BoundsCheck { ref len, ref index } => { write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f6c7174649f..05011241557 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2671,8 +2671,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { BoundsCheck { ref len, ref index } => { BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } } - Panic { .. } - | Overflow(_) + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero @@ -2721,8 +2720,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { BoundsCheck { ref len, ref index } => { len.visit_with(visitor) || index.visit_with(visitor) } - Panic { .. } - | Overflow(_) + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2f094516a35..555beaa8ca7 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -539,7 +539,7 @@ macro_rules! make_mir_visitor { self.visit_operand(len, location); self.visit_operand(index, location); } - Panic { .. } | Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero | + Overflow(_) | OverflowNeg | DivisionByZero | RemainderByZero | ResumedAfterReturn(_) | ResumedAfterPanic(_) => { // Nothing to visit } diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index e0e78546099..edf0f0a7dbe 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,6 +1,8 @@ use std::error::Error; use std::fmt; +use rustc_span::Symbol; + use super::InterpCx; use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; @@ -9,7 +11,8 @@ use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, Pani pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, - Panic(PanicInfo), + AssertFailure(PanicInfo), + Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, } // The errors become `MachineStop` with plain strings when being raised. @@ -29,7 +32,10 @@ impl fmt::Display for ConstEvalErrKind { write!(f, "\"{}\" needs an rfc before being allowed inside constants", msg) } ConstAccessesStatic => write!(f, "constant accesses static"), - Panic(ref msg) => write!(f, "{:?}", msg), + AssertFailure(ref msg) => write!(f, "{:?}", msg), + Panic { msg, line, col, file } => { + write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col) + } } } } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 688eee05dda..e0f146c6dc0 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -13,7 +13,7 @@ use rustc_span::symbol::Symbol; use crate::interpret::{ self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PanicInfo, PlaceTy, Pointer, Scalar, + Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -78,7 +78,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { let msg = Symbol::intern(self.read_str(msg_place)?); let span = self.find_closest_untracked_caller_location().unwrap_or(span); let (file, line, col) = self.location_triple_for_span(span); - Err(ConstEvalErrKind::Panic(PanicInfo::Panic { msg, file, line, col }).into()) + Err(ConstEvalErrKind::Panic { msg, file, line, col }.into()) } else { Ok(false) } @@ -304,9 +304,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, RemainderByZero => RemainderByZero, ResumedAfterReturn(generator_kind) => ResumedAfterReturn(*generator_kind), ResumedAfterPanic(generator_kind) => ResumedAfterPanic(*generator_kind), - Panic { .. } => bug!("`Panic` variant cannot occur in MIR"), }; - Err(ConstEvalErrKind::Panic(err).into()) + Err(ConstEvalErrKind::AssertFailure(err).into()) } fn ptr_to_int(_mem: &Memory<'mir, 'tcx, Self>, _ptr: Pointer) -> InterpResult<'tcx, u64> { From 17a8cfd605fb8d43dc61496a522cf3b84988d69d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 9 Feb 2020 16:54:40 +0100 Subject: [PATCH 0094/1250] no need for hook_panic_fn to return a bool --- src/librustc_mir/const_eval/machine.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index e0f146c6dc0..7fd96ec2d1a 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -60,13 +60,13 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { /// "Intercept" a function call to a panic-related function /// because we have something special to do for it. - /// Returns `true` if an intercept happened. - pub fn hook_panic_fn( + /// If this returns successfully (`Ok`), the function should just be evaluated normally. + fn hook_panic_fn( &mut self, span: Span, instance: ty::Instance<'tcx>, args: &[OpTy<'tcx>], - ) -> InterpResult<'tcx, bool> { + ) -> InterpResult<'tcx> { let def_id = instance.def_id(); if Some(def_id) == self.tcx.lang_items().panic_fn() || Some(def_id) == self.tcx.lang_items().begin_panic_fn() @@ -80,7 +80,7 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { let (file, line, col) = self.location_triple_for_span(span); Err(ConstEvalErrKind::Panic { msg, file, line, col }.into()) } else { - Ok(false) + Ok(()) } } } @@ -225,13 +225,11 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } else { // Some functions we support even if they are non-const -- but avoid testing - // that for const fn! We certainly do *not* want to actually call the fn + // that for const fn! + ecx.hook_panic_fn(span, instance, args)?; + // We certainly do *not* want to actually call the fn // though, so be sure we return here. - return if ecx.hook_panic_fn(span, instance, args)? { - Ok(None) - } else { - throw_unsup_format!("calling non-const function `{}`", instance) - }; + throw_unsup_format!("calling non-const function `{}`", instance) } } // This is a const fn. Call it. From 6457b29104028bbb3af5efeefed7343d85576320 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Feb 2020 20:53:01 +0100 Subject: [PATCH 0095/1250] move PanicInfo to mir module --- src/librustc/mir/interpret/error.rs | 57 ------------------- src/librustc/mir/interpret/mod.rs | 6 +- src/librustc/mir/mod.rs | 57 ++++++++++++++++++- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_mir/borrow_check/invalidation.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- .../borrow_check/type_check/mod.rs | 2 +- src/librustc_mir/const_eval/error.rs | 3 +- src/librustc_mir/const_eval/machine.rs | 7 ++- src/librustc_mir/interpret/machine.rs | 6 +- src/librustc_mir/transform/const_prop.rs | 6 +- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir_build/build/expr/as_place.rs | 2 +- .../build/expr/as_rvalue.rs | 2 +- 15 files changed, 78 insertions(+), 80 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index da8c0bf266f..a7e769b8b96 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -7,7 +7,6 @@ use crate::ty::query::TyCtxtAt; use crate::ty::{self, layout, Ty}; use backtrace::Backtrace; -use hir::GeneratorKind; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_macros::HashStable; @@ -266,62 +265,6 @@ impl<'tcx> From> for InterpErrorInfo<'tcx> { } } -/// Information about a panic. -/// -/// FIXME: this is not actually an InterpError, and should probably be moved to another module. -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum PanicInfo { - BoundsCheck { len: O, index: O }, - Overflow(mir::BinOp), - OverflowNeg, - DivisionByZero, - RemainderByZero, - ResumedAfterReturn(GeneratorKind), - ResumedAfterPanic(GeneratorKind), -} - -/// Type for MIR `Assert` terminator error messages. -pub type AssertMessage<'tcx> = PanicInfo>; - -impl PanicInfo { - /// Getting a description does not require `O` to be printable, and does not - /// require allocation. - /// The caller is expected to handle `BoundsCheck` separately. - pub fn description(&self) -> &'static str { - use PanicInfo::*; - match self { - Overflow(mir::BinOp::Add) => "attempt to add with overflow", - Overflow(mir::BinOp::Sub) => "attempt to subtract with overflow", - Overflow(mir::BinOp::Mul) => "attempt to multiply with overflow", - Overflow(mir::BinOp::Div) => "attempt to divide with overflow", - Overflow(mir::BinOp::Rem) => "attempt to calculate the remainder with overflow", - OverflowNeg => "attempt to negate with overflow", - Overflow(mir::BinOp::Shr) => "attempt to shift right with overflow", - Overflow(mir::BinOp::Shl) => "attempt to shift left with overflow", - Overflow(op) => bug!("{:?} cannot overflow", op), - DivisionByZero => "attempt to divide by zero", - RemainderByZero => "attempt to calculate the remainder with a divisor of zero", - ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion", - ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", - ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", - ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - BoundsCheck { .. } => bug!("Unexpected PanicInfo"), - } - } -} - -impl fmt::Debug for PanicInfo { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use PanicInfo::*; - match self { - BoundsCheck { ref len, ref index } => { - write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) - } - _ => write!(f, "{}", self.description()), - } - } -} - /// Error information for when the program we executed turned out not to actually be a valid /// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp /// where we work on generic code or execution does not have all information available. diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index b4cfd860152..f0879bdd8ae 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -90,9 +90,9 @@ mod queries; mod value; pub use self::error::{ - struct_error, AssertMessage, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, - FrameInfo, InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, PanicInfo, - ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo, + struct_error, ConstEvalErr, ConstEvalRawResult, ConstEvalResult, ErrorHandled, FrameInfo, + InterpError, InterpErrorInfo, InterpResult, InvalidProgramInfo, ResourceExhaustionInfo, + UndefinedBehaviorInfo, UnsupportedOpInfo, }; pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef}; diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 05011241557..8d224b6d739 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2,7 +2,7 @@ //! //! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/index.html -use crate::mir::interpret::{GlobalAlloc, PanicInfo, Scalar}; +use crate::mir::interpret::{GlobalAlloc, Scalar}; use crate::mir::visit::MirVisitable; use crate::ty::adjustment::PointerCast; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -36,7 +36,6 @@ pub use syntax::ast::Mutability; use syntax::ast::Name; pub use self::cache::{BodyAndCache, ReadOnlyBodyAndCache}; -pub use self::interpret::AssertMessage; pub use self::query::*; pub use crate::read_only; @@ -1154,6 +1153,21 @@ pub enum TerminatorKind<'tcx> { }, } +/// Information about an assertion failure. +#[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] +pub enum PanicInfo { + BoundsCheck { len: O, index: O }, + Overflow(BinOp), + OverflowNeg, + DivisionByZero, + RemainderByZero, + ResumedAfterReturn(GeneratorKind), + ResumedAfterPanic(GeneratorKind), +} + +/// Type for MIR `Assert` terminator error messages. +pub type AssertMessage<'tcx> = PanicInfo>; + pub type Successors<'a> = iter::Chain, slice::Iter<'a, BasicBlock>>; pub type SuccessorsMut<'a> = @@ -1383,6 +1397,45 @@ impl<'tcx> BasicBlockData<'tcx> { } } +impl PanicInfo { + /// Getting a description does not require `O` to be printable, and does not + /// require allocation. + /// The caller is expected to handle `BoundsCheck` separately. + pub fn description(&self) -> &'static str { + use PanicInfo::*; + match self { + Overflow(BinOp::Add) => "attempt to add with overflow", + Overflow(BinOp::Sub) => "attempt to subtract with overflow", + Overflow(BinOp::Mul) => "attempt to multiply with overflow", + Overflow(BinOp::Div) => "attempt to divide with overflow", + Overflow(BinOp::Rem) => "attempt to calculate the remainder with overflow", + OverflowNeg => "attempt to negate with overflow", + Overflow(BinOp::Shr) => "attempt to shift right with overflow", + Overflow(BinOp::Shl) => "attempt to shift left with overflow", + Overflow(op) => bug!("{:?} cannot overflow", op), + DivisionByZero => "attempt to divide by zero", + RemainderByZero => "attempt to calculate the remainder with a divisor of zero", + ResumedAfterReturn(GeneratorKind::Gen) => "generator resumed after completion", + ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", + ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", + ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", + BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + } + } +} + +impl fmt::Debug for PanicInfo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use PanicInfo::*; + match self { + BoundsCheck { ref len, ref index } => { + write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) + } + _ => write!(f, "{}", self.description()), + } + } +} + impl<'tcx> Debug for TerminatorKind<'tcx> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { self.fmt_head(fmt)?; diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 555beaa8ca7..529ed71a6f3 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -533,7 +533,7 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)? AssertMessage<'tcx>, location: Location) { - use crate::mir::interpret::PanicInfo::*; + use crate::mir::PanicInfo::*; match msg { BoundsCheck { len, index } => { self.visit_operand(len, location); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 0a4610e9e49..835050fece6 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -11,7 +11,7 @@ use crate::MemFlags; use rustc::middle::lang_items; use rustc::mir; -use rustc::mir::interpret::PanicInfo; +use rustc::mir::PanicInfo; use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf}; use rustc::ty::{self, Instance, Ty, TypeFoldable}; use rustc_index::vec::Idx; diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 392f164d314..317b5edcb41 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -153,7 +153,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(location, cond); - use rustc::mir::interpret::PanicInfo; + use rustc::mir::PanicInfo; if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(location, len); self.consume_operand(location, index); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 88173137bd2..899529ce242 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -654,7 +654,7 @@ impl<'cx, 'tcx> dataflow::generic::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(loc, (cond, span), flow_state); - use rustc::mir::interpret::PanicInfo; + use rustc::mir::PanicInfo; if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 100fd7dc48d..bb074a81d2a 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -9,9 +9,9 @@ use rustc::infer::canonical::QueryRegionConstraints; use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; -use rustc::mir::interpret::PanicInfo; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; +use rustc::mir::PanicInfo; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index edf0f0a7dbe..5f05f439d92 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,10 +1,11 @@ use std::error::Error; use std::fmt; +use rustc::mir::PanicInfo; use rustc_span::Symbol; use super::InterpCx; -use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine, PanicInfo}; +use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine}; /// The CTFE machine has some custom error kinds. #[derive(Clone, Debug)] diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 7fd96ec2d1a..65cc53cac9d 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -8,12 +8,13 @@ use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; +use rustc::mir::AssertMessage; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use crate::interpret::{ - self, snapshot, AllocId, Allocation, AssertMessage, GlobalId, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, + self, snapshot, AllocId, Allocation, GlobalId, ImmTy, InterpCx, InterpResult, Memory, + MemoryKind, OpTy, PlaceTy, Pointer, Scalar, }; use super::error::*; @@ -280,7 +281,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { - use rustc::mir::interpret::PanicInfo::*; + use rustc::mir::PanicInfo::*; // Convert `PanicInfo` to `PanicInfo`. let err = match msg { BoundsCheck { ref len, ref index } => { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 3309e9b9b62..5291000d10b 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -11,8 +11,8 @@ use rustc_hir::def_id::DefId; use rustc_span::Span; use super::{ - AllocId, Allocation, AllocationExtra, AssertMessage, Frame, ImmTy, InterpCx, InterpResult, - Memory, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Scalar, + AllocId, Allocation, AllocationExtra, Frame, ImmTy, InterpCx, InterpResult, Memory, MemoryKind, + OpTy, Operand, PlaceTy, Pointer, Scalar, }; /// Data returned by Machine::stack_pop, @@ -171,7 +171,7 @@ pub trait Machine<'mir, 'tcx>: Sized { fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, span: Span, - msg: &AssertMessage<'tcx>, + msg: &mir::AssertMessage<'tcx>, unwind: Option, ) -> InterpResult<'tcx>; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 5c6c003b3a6..c8d832814c7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,13 +4,13 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpError, InterpResult, PanicInfo, Scalar}; +use rustc::mir::interpret::{InterpError, InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc::mir::{ read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant, - Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue, + Local, LocalDecl, LocalKind, Location, Operand, PanicInfo, Place, ReadOnlyBodyAndCache, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; @@ -198,7 +198,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _span: Span, - _msg: &rustc::mir::interpret::AssertMessage<'tcx>, + _msg: &rustc::mir::AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { bug!("panics terminators are not evaluated in ConstProp"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a6fc6573178..da19fb34927 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1022,7 +1022,7 @@ fn create_generator_resume_function<'tcx>( let mut cases = create_cases(body, &transform, Operation::Resume); - use rustc::mir::interpret::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; + use rustc::mir::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; // Jump to the entry point on the unresumed cases.insert(0, (UNRESUMED, BasicBlock::new(0))); diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index 907300d45aa..86f87790f23 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -5,7 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::interpret::PanicInfo::BoundsCheck; +use rustc::mir::PanicInfo::BoundsCheck; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 6f5c5f0dd4c..5722a8c1cd9 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -6,7 +6,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::interpret::PanicInfo; +use rustc::mir::PanicInfo; use rustc::mir::*; use rustc::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; From 55339f2eb7c186334216c35203f98540e8c8cb37 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 Feb 2020 11:27:33 +0100 Subject: [PATCH 0096/1250] small cleanup in ConstEvalErr::struct_generic --- src/librustc/mir/interpret/error.rs | 71 ++++++++++++++++------------- 1 file changed, 40 insertions(+), 31 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index a7e769b8b96..64d32690545 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -126,9 +126,15 @@ impl<'tcx> ConstEvalErr<'tcx> { } } - /// Sets the message passed in via `message` and adds span labels before handing control back - /// to `emit` to do any final processing. It's the caller's responsibility to call emit(), - /// stash(), etc. within the `emit` function to dispose of the diagnostic properly. + /// Create a diagnostic for this const eval error. + /// + /// Sets the message passed in via `message` and adds span labels with detailed error + /// information before handing control back to `emit` to do any final processing. + /// It's the caller's responsibility to call emit(), stash(), etc. within the `emit` + /// function to dispose of the diagnostic properly. + /// + /// If `lint_root.is_some()` report it as a lint, else report it as a hard error. + /// (Except that for some errors, we ignore all that -- see `must_error` below.) fn struct_generic( &self, tcx: TyCtxtAt<'tcx>, @@ -141,6 +147,7 @@ impl<'tcx> ConstEvalErr<'tcx> { return Err(ErrorHandled::TooGeneric); } err_inval!(TypeckError) => return Err(ErrorHandled::Reported), + // We must *always* hard error on these, even if the caller wants just a lint. err_inval!(Layout(LayoutError::SizeOverflow(_))) => true, _ => false, }; @@ -155,10 +162,11 @@ impl<'tcx> ConstEvalErr<'tcx> { err => err.to_string(), }; - let add_span_labels = |err: &mut DiagnosticBuilder<'_>| { - if !must_error { - err.span_label(self.span, err_msg.clone()); + let finish = |mut err: DiagnosticBuilder<'_>, span_msg: Option| { + if let Some(span_msg) = span_msg { + err.span_label(self.span, span_msg); } + // Add spans for the stacktrace. // Skip the last, which is just the environment of the constant. The stacktrace // is sometimes empty because we create "fake" eval contexts in CTFE to do work // on constant values. @@ -167,35 +175,36 @@ impl<'tcx> ConstEvalErr<'tcx> { err.span_label(frame_info.call_site, frame_info.to_string()); } } + // Let the caller finish the job. + emit(err) }; - if let (Some(lint_root), false) = (lint_root, must_error) { - let hir_id = self - .stacktrace - .iter() - .rev() - .filter_map(|frame| frame.lint_root) - .next() - .unwrap_or(lint_root); - tcx.struct_span_lint_hir( - rustc_session::lint::builtin::CONST_ERR, - hir_id, - tcx.span, - |lint| { - let mut err = lint.build(message); - add_span_labels(&mut err); - emit(err); - }, - ); + if must_error { + // The `message` makes little sense here, this is a more serious error than the + // caller thinks anyway. + finish(struct_error(tcx, &err_msg), None); } else { - let mut err = if must_error { - struct_error(tcx, &err_msg) + // Regular case. + if let Some(lint_root) = lint_root { + // Report as lint. + let hir_id = self + .stacktrace + .iter() + .rev() + .filter_map(|frame| frame.lint_root) + .next() + .unwrap_or(lint_root); + tcx.struct_span_lint_hir( + rustc_session::lint::builtin::CONST_ERR, + hir_id, + tcx.span, + |lint| finish(lint.build(message), Some(err_msg)), + ); } else { - struct_error(tcx, message) - }; - add_span_labels(&mut err); - emit(err); - }; + // Report as hard error. + finish(struct_error(tcx, message), Some(err_msg)); + } + } Ok(()) } } From 7e7d1c39edafcbce55ba08449689566e335545b7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 10 Feb 2020 15:58:10 +0100 Subject: [PATCH 0097/1250] improve comments: - comment for special handling of Shl/Shr - reference a PR --- src/librustc/mir/interpret/error.rs | 1 + src/librustc_mir/transform/const_prop.rs | 12 ++++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 64d32690545..e747eee30f9 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -182,6 +182,7 @@ impl<'tcx> ConstEvalErr<'tcx> { if must_error { // The `message` makes little sense here, this is a more serious error than the // caller thinks anyway. + // See . finish(struct_error(tcx, &err_msg), None); } else { // Regular case. diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index c8d832814c7..952dede4a15 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -527,6 +527,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; Ok(overflow) })? { + // `AssertKind` only has an `OverflowNeg` variant, to make sure that is + // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; } @@ -544,6 +546,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ) -> Option<()> { let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; + // Check for exceeding shifts *even if* we cannot evaluate the LHS. if op == BinOp::Shr || op == BinOp::Shl { let left_bits = place_layout.size.bits(); let right_size = r.layout.size; @@ -564,7 +567,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } // The remaining operators are handled through `overflowing_binary_op`. - // FIXME: Why do we not also do this for `Shr` and `Shl`? if self.use_ecx(|this| { let l = this.ecx.read_immediate(this.ecx.eval_operand(left, None)?)?; let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; @@ -603,9 +605,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // 2. Working around bugs in other parts of the compiler // - In this case, we'll return `None` from this function to stop evaluation. match rvalue { - // Additional checking: if overflow checks are disabled (which is usually the case in - // release mode), then we need to do additional checking here to give lints to the user - // if an overflow would occur. + // Additional checking: give lints to the user if an overflow would occur. + // If `overflow_check` is set, running const-prop on the `Assert` terminators + // will already generate the appropriate messages. Rvalue::UnaryOp(op, arg) if !overflow_check => { trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); self.check_unary_op(*op, arg, source_info)?; @@ -613,6 +615,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // Additional checking: check for overflows on integer binary operations and report // them to the user as lints. + // If `overflow_check` is set, running const-prop on the `Assert` terminators + // will already generate the appropriate messages. Rvalue::BinaryOp(op, left, right) if !overflow_check => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); self.check_binary_op(*op, left, right, source_info, place_layout)?; From ed2f22c5a973f4deffa4bd6efbbee0393ff91691 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 12 Feb 2020 19:40:31 +0100 Subject: [PATCH 0098/1250] rename PanicInfo -> AssertKind --- src/librustc/mir/mod.rs | 18 ++++++++--------- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 6 +++--- src/librustc_mir/borrow_check/invalidation.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 4 ++-- .../borrow_check/type_check/mod.rs | 4 ++-- src/librustc_mir/const_eval/error.rs | 4 ++-- src/librustc_mir/const_eval/machine.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 20 +++++++++---------- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir_build/build/expr/as_place.rs | 2 +- .../build/expr/as_rvalue.rs | 12 +++++------ 12 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8d224b6d739..4520d3a3333 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1155,7 +1155,7 @@ pub enum TerminatorKind<'tcx> { /// Information about an assertion failure. #[derive(Clone, RustcEncodable, RustcDecodable, HashStable, PartialEq)] -pub enum PanicInfo { +pub enum AssertKind { BoundsCheck { len: O, index: O }, Overflow(BinOp), OverflowNeg, @@ -1166,7 +1166,7 @@ pub enum PanicInfo { } /// Type for MIR `Assert` terminator error messages. -pub type AssertMessage<'tcx> = PanicInfo>; +pub type AssertMessage<'tcx> = AssertKind>; pub type Successors<'a> = iter::Chain, slice::Iter<'a, BasicBlock>>; @@ -1397,12 +1397,12 @@ impl<'tcx> BasicBlockData<'tcx> { } } -impl PanicInfo { +impl AssertKind { /// Getting a description does not require `O` to be printable, and does not /// require allocation. /// The caller is expected to handle `BoundsCheck` separately. pub fn description(&self) -> &'static str { - use PanicInfo::*; + use AssertKind::*; match self { Overflow(BinOp::Add) => "attempt to add with overflow", Overflow(BinOp::Sub) => "attempt to subtract with overflow", @@ -1419,14 +1419,14 @@ impl PanicInfo { ResumedAfterReturn(GeneratorKind::Async(_)) => "`async fn` resumed after completion", ResumedAfterPanic(GeneratorKind::Gen) => "generator resumed after panicking", ResumedAfterPanic(GeneratorKind::Async(_)) => "`async fn` resumed after panicking", - BoundsCheck { .. } => bug!("Unexpected PanicInfo"), + BoundsCheck { .. } => bug!("Unexpected AssertKind"), } } } -impl fmt::Debug for PanicInfo { +impl fmt::Debug for AssertKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - use PanicInfo::*; + use AssertKind::*; match self { BoundsCheck { ref len, ref index } => { write!(f, "index out of bounds: the len is {:?} but the index is {:?}", len, index) @@ -2719,7 +2719,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } } Assert { ref cond, expected, ref msg, target, cleanup } => { - use PanicInfo::*; + use AssertKind::*; let msg = match msg { BoundsCheck { ref len, ref index } => { BoundsCheck { len: len.fold_with(folder), index: index.fold_with(folder) } @@ -2768,7 +2768,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { } Assert { ref cond, ref msg, .. } => { if cond.visit_with(visitor) { - use PanicInfo::*; + use AssertKind::*; match msg { BoundsCheck { ref len, ref index } => { len.visit_with(visitor) || index.visit_with(visitor) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 529ed71a6f3..8330bbe0834 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -533,7 +533,7 @@ macro_rules! make_mir_visitor { fn super_assert_message(&mut self, msg: & $($mutability)? AssertMessage<'tcx>, location: Location) { - use crate::mir::PanicInfo::*; + use crate::mir::AssertKind::*; match msg { BoundsCheck { len, index } => { self.visit_operand(len, location); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 835050fece6..916c15eb1b6 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -11,7 +11,7 @@ use crate::MemFlags; use rustc::middle::lang_items; use rustc::mir; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::ty::layout::{self, FnAbiExt, HasTyCtxt, LayoutOf}; use rustc::ty::{self, Instance, Ty, TypeFoldable}; use rustc_index::vec::Idx; @@ -378,7 +378,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // checked operation, just a comparison with the minimum // value, so we have to check for the assert message. if !bx.check_overflow() { - if let PanicInfo::OverflowNeg = *msg { + if let AssertKind::OverflowNeg = *msg { const_cond = Some(expected); } } @@ -412,7 +412,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Put together the arguments to the panic entry point. let (lang_item, args) = match msg { - PanicInfo::BoundsCheck { ref len, ref index } => { + AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 317b5edcb41..0bead27050c 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -153,8 +153,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(location, cond); - use rustc::mir::PanicInfo; - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + use rustc::mir::AssertKind; + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(location, len); self.consume_operand(location, index); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 899529ce242..941534e68fc 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -654,8 +654,8 @@ impl<'cx, 'tcx> dataflow::generic::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt } TerminatorKind::Assert { ref cond, expected: _, ref msg, target: _, cleanup: _ } => { self.consume_operand(loc, (cond, span), flow_state); - use rustc::mir::PanicInfo; - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + use rustc::mir::AssertKind; + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { self.consume_operand(loc, (len, span), flow_state); self.consume_operand(loc, (index, span), flow_state); } diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index bb074a81d2a..5f7bf148e33 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -11,7 +11,7 @@ use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::mir::*; use rustc::traits::query::type_op; use rustc::traits::query::type_op::custom::CustomTypeOp; @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty); } - if let PanicInfo::BoundsCheck { ref len, ref index } = *msg { + if let AssertKind::BoundsCheck { ref len, ref index } = *msg { if len.ty(body, tcx) != tcx.types.usize { span_mirbug!(self, len, "bounds-check length non-usize {:?}", len) } diff --git a/src/librustc_mir/const_eval/error.rs b/src/librustc_mir/const_eval/error.rs index 5f05f439d92..63ad9ec8cae 100644 --- a/src/librustc_mir/const_eval/error.rs +++ b/src/librustc_mir/const_eval/error.rs @@ -1,7 +1,7 @@ use std::error::Error; use std::fmt; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc_span::Symbol; use super::InterpCx; @@ -12,7 +12,7 @@ use crate::interpret::{ConstEvalErr, InterpError, InterpErrorInfo, Machine}; pub enum ConstEvalErrKind { NeedsRfc(String), ConstAccessesStatic, - AssertFailure(PanicInfo), + AssertFailure(AssertKind), Panic { msg: Symbol, line: u32, col: u32, file: Symbol }, } diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 65cc53cac9d..e40436ccf0b 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -281,8 +281,8 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { - use rustc::mir::PanicInfo::*; - // Convert `PanicInfo` to `PanicInfo`. + use rustc::mir::AssertKind::*; + // Convert `AssertKind` to `AssertKind`. let err = match msg { BoundsCheck { ref len, ref index } => { let len = ecx diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 952dede4a15..09eb6e952ad 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -9,8 +9,8 @@ use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; use rustc::mir::{ - read_only, AggregateKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, Constant, - Local, LocalDecl, LocalKind, Location, Operand, PanicInfo, Place, ReadOnlyBodyAndCache, Rvalue, + read_only, AggregateKind, AssertKind, BasicBlock, BinOp, Body, BodyAndCache, ClearCrossCrate, + Constant, Local, LocalDecl, LocalKind, Location, Operand, Place, ReadOnlyBodyAndCache, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; @@ -501,7 +501,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn report_panic_as_lint(&self, source_info: SourceInfo, panic: PanicInfo) -> Option<()> { + fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind) -> Option<()> { // Somewhat convoluted way to re-use the CTFE error reporting code. let lint_root = self.lint_root(source_info)?; let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); @@ -530,7 +530,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // `AssertKind` only has an `OverflowNeg` variant, to make sure that is // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - self.report_panic_as_lint(source_info, PanicInfo::OverflowNeg)?; + self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?; } Some(()) @@ -572,7 +572,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; Ok(overflow) })? { - self.report_panic_as_lint(source_info, PanicInfo::Overflow(op))?; + self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?; } Some(()) @@ -910,11 +910,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { span, |lint| { let msg = match msg { - PanicInfo::Overflow(_) - | PanicInfo::OverflowNeg - | PanicInfo::DivisionByZero - | PanicInfo::RemainderByZero => msg.description().to_owned(), - PanicInfo::BoundsCheck { ref len, ref index } => { + AssertKind::Overflow(_) + | AssertKind::OverflowNeg + | AssertKind::DivisionByZero + | AssertKind::RemainderByZero => msg.description().to_owned(), + AssertKind::BoundsCheck { ref len, ref index } => { let len = self .eval_operand(len, source_info) .expect("len must be const"); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index da19fb34927..d5d9a8c83cd 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1022,7 +1022,7 @@ fn create_generator_resume_function<'tcx>( let mut cases = create_cases(body, &transform, Operation::Resume); - use rustc::mir::PanicInfo::{ResumedAfterPanic, ResumedAfterReturn}; + use rustc::mir::AssertKind::{ResumedAfterPanic, ResumedAfterReturn}; // Jump to the entry point on the unresumed cases.insert(0, (UNRESUMED, BasicBlock::new(0))); diff --git a/src/librustc_mir_build/build/expr/as_place.rs b/src/librustc_mir_build/build/expr/as_place.rs index 86f87790f23..d77cc49c94f 100644 --- a/src/librustc_mir_build/build/expr/as_place.rs +++ b/src/librustc_mir_build/build/expr/as_place.rs @@ -5,7 +5,7 @@ use crate::build::ForGuard::{OutsideGuard, RefWithinGuard}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::PanicInfo::BoundsCheck; +use rustc::mir::AssertKind::BoundsCheck; use rustc::mir::*; use rustc::ty::{self, CanonicalUserTypeAnnotation, Ty, TyCtxt, Variance}; use rustc_span::Span; diff --git a/src/librustc_mir_build/build/expr/as_rvalue.rs b/src/librustc_mir_build/build/expr/as_rvalue.rs index 5722a8c1cd9..dc97f321a36 100644 --- a/src/librustc_mir_build/build/expr/as_rvalue.rs +++ b/src/librustc_mir_build/build/expr/as_rvalue.rs @@ -6,7 +6,7 @@ use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::hair::*; use rustc::middle::region; -use rustc::mir::PanicInfo; +use rustc::mir::AssertKind; use rustc::mir::*; use rustc::ty::{self, Ty, UpvarSubsts}; use rustc_span::Span; @@ -86,7 +86,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block, Operand::Move(is_min), false, - PanicInfo::OverflowNeg, + AssertKind::OverflowNeg, expr_span, ); } @@ -294,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let val = tcx.mk_place_field(result_value.clone(), val_fld, ty); let of = tcx.mk_place_field(result_value, of_fld, bool_ty); - let err = PanicInfo::Overflow(op); + let err = AssertKind::Overflow(op); block = self.assert(block, Operand::Move(of), false, err, span); @@ -305,11 +305,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // and 2. there are two possible failure cases, divide-by-zero and overflow. let zero_err = if op == BinOp::Div { - PanicInfo::DivisionByZero + AssertKind::DivisionByZero } else { - PanicInfo::RemainderByZero + AssertKind::RemainderByZero }; - let overflow_err = PanicInfo::Overflow(op); + let overflow_err = AssertKind::Overflow(op); // Check for / 0 let is_zero = self.temp(bool_ty, span); From 851a701f90081fbc83fa151e9f272cea2a990779 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Wed, 8 Jan 2020 22:07:05 +0100 Subject: [PATCH 0099/1250] Reuse a Vec in mir simplification --- src/librustc_mir/transform/simplify.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index ddf8d73e548..d589c03761a 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -94,6 +94,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { self.strip_nops(); let mut start = START_BLOCK; + let mut new_stmts = vec![]; loop { let mut changed = false; @@ -114,7 +115,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { self.collapse_goto_chain(successor, &mut changed); } - let mut new_stmts = vec![]; let mut inner_changed = true; while inner_changed { inner_changed = false; @@ -124,7 +124,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } let data = &mut self.basic_blocks[bb]; - data.statements.extend(new_stmts); + data.statements.extend(new_stmts.drain(..)); data.terminator = Some(terminator); changed |= inner_changed; From dec8166abc6675627819723b10301e395f3876d5 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 30 Jan 2020 10:27:50 +0100 Subject: [PATCH 0100/1250] Use Vec::append --- src/librustc_mir/transform/simplify.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index d589c03761a..813091b7f95 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -124,7 +124,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } let data = &mut self.basic_blocks[bb]; - data.statements.extend(new_stmts.drain(..)); + data.statements.append(&mut new_stmts); data.terminator = Some(terminator); changed |= inner_changed; From 33513fad8089956adcbb5b9803f56de1a8e94b57 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 30 Jan 2020 10:35:50 +0100 Subject: [PATCH 0101/1250] Avoid an intermediate Vec in mir simplify --- src/librustc_mir/transform/simplify.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 813091b7f95..3a1ccb50465 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -94,7 +94,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { self.strip_nops(); let mut start = START_BLOCK; - let mut new_stmts = vec![]; loop { let mut changed = false; @@ -119,13 +118,11 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { while inner_changed { inner_changed = false; inner_changed |= self.simplify_branch(&mut terminator); - inner_changed |= self.merge_successor(&mut new_stmts, &mut terminator); + inner_changed |= self.merge_successor(bb, &mut terminator); changed |= inner_changed; } - let data = &mut self.basic_blocks[bb]; - data.statements.append(&mut new_stmts); - data.terminator = Some(terminator); + self.basic_blocks[bb].terminator = Some(terminator); changed |= inner_changed; } @@ -199,7 +196,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { // merge a block with 1 `goto` predecessor to its parent fn merge_successor( &mut self, - new_stmts: &mut Vec>, + merge_into: BasicBlock, terminator: &mut Terminator<'tcx>, ) -> bool { let target = match terminator.kind { @@ -216,7 +213,9 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { return false; } }; - new_stmts.extend(self.basic_blocks[target].statements.drain(..)); + + let (from, to) = self.basic_blocks.pick2_mut(target, merge_into); + to.statements.append(&mut from.statements); self.pred_count[target] = 0; true From 10f342abae4e9aafb02c3adaaa050f43eb0e2dd0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Feb 2020 11:16:54 +0100 Subject: [PATCH 0102/1250] miri: fix exact_div --- src/librustc_mir/interpret/intrinsics.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index f85da760ada..33070f7e656 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -410,8 +410,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> InterpResult<'tcx> { // Performs an exact division, resulting in undefined behavior where // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. - // First, check x % y != 0. - if self.binary_op(BinOp::Rem, a, b)?.to_bits()? != 0 { + // First, check x % y != 0 (or if that computation overflows). + let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?; + if overflow || res.to_bits(a.layout.size)? != 0 { // Then, check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); let b_scalar = b.to_scalar().unwrap(); @@ -421,6 +422,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { throw_ub_format!("exact_div: {} cannot be divided by {} without remainder", a, b,) } } + // `Rem` says this is all right, so we can let `Div` do its job. self.binop_ignore_overflow(BinOp::Div, a, b, dest) } } From acad03342412961536641d53628d7ccaa189279b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:25:49 +0100 Subject: [PATCH 0103/1250] expand: extract error_recursion_limit_reached --- src/librustc_expand/expand.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index c7c7f62918d..da966018409 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -606,21 +606,26 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { - if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { - 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( + fn error_recursion_limit_reached(&mut self) { + let expn_data = self.cx.current_expansion.id.expn_data(); + let suggested_limit = self.cx.ecfg.recursion_limit * 2; + self.cx + .struct_span_err( expn_data.call_site, &format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()), - ); - err.help(&format!( + ) + .help(&format!( "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate (`{}`)", suggested_limit, self.cx.ecfg.crate_name, - )); - err.emit(); - self.cx.trace_macros_diag(); - FatalError.raise(); + )) + .emit(); + self.cx.trace_macros_diag(); + FatalError.raise(); + } + + fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { + if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { + self.error_recursion_limit_reached(); } let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); From 7518492315346ac3821ad9264e08721a571742c8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 08:43:33 +0100 Subject: [PATCH 0104/1250] expand: extract error_wrong_fragment_kind --- src/librustc_expand/expand.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index da966018409..136cc1d94a0 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -623,6 +623,18 @@ impl<'a, 'b> MacroExpander<'a, 'b> { FatalError.raise(); } + /// A macro's expansion does not fit in this fragment kind. + /// For example, a non-type macro in a type position. + fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::Mac, span: Span) { + let msg = format!( + "non-{kind} macro in {kind} position: {path}", + kind = kind.name(), + path = pprust::path_to_string(&mac.path), + ); + self.cx.span_err(span, &msg); + self.cx.trace_macros_diag(); + } + fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { self.error_recursion_limit_reached(); @@ -643,13 +655,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { 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 = pprust::path_to_string(&mac.path), - ); - self.cx.span_err(span, &msg); - self.cx.trace_macros_diag(); + self.error_wrong_fragment_kind(fragment_kind, &mac, span); fragment_kind.dummy(span) }; self.cx.current_expansion.prior_type_ascription = prev; From fcce5fa6e7ba67db63674dc7369125875c7f39a2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 09:11:59 +0100 Subject: [PATCH 0105/1250] expand: simplify classify_* --- src/librustc_expand/expand.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 136cc1d94a0..91195d379d7 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1041,13 +1041,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } /// If `item` is an attr invocation, remove and return the macro attribute and derive traits. - fn classify_item( + fn classify_item( &mut self, - item: &mut T, - ) -> (Option, Vec, /* after_derive */ bool) - where - T: HasAttrs, - { + item: &mut impl HasAttrs, + ) -> (Option, Vec, /* after_derive */ bool) { let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false); item.visit_attrs(|mut attrs| { @@ -1061,9 +1058,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { /// Alternative to `classify_item()` that ignores `#[derive]` so invocations fallthrough /// to the unused-attributes lint (making it an error on statements and expressions /// is a breaking change) - fn classify_nonitem( + fn classify_nonitem( &mut self, - nonitem: &mut T, + nonitem: &mut impl HasAttrs, ) -> (Option, /* after_derive */ bool) { let (mut attr, mut after_derive) = (None, false); From dc6bd6a12347f27c937c19adfda542f694fb61c5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 09:59:37 +0100 Subject: [PATCH 0106/1250] expand: simplify flat_map_item --- src/librustc_expand/expand.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 91195d379d7..ee0b7fa00de 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1383,11 +1383,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, .. }) => { - if item.ident == Ident::invalid() { - return noop_flat_map_item(item, self); - } - + ast::ItemKind::Mod(ast::Mod { inner, .. }) if item.ident != Ident::invalid() => { let orig_directory_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); From ec434500157c47143a9b5600a7e34522c49f4e8e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 31 Dec 2019 10:06:52 +0100 Subject: [PATCH 0107/1250] expand: simplify flat_map_item wrt. inline module detection --- src/librustc_expand/expand.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index ee0b7fa00de..316dd02bd95 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1383,17 +1383,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, .. }) if item.ident != Ident::invalid() => { + ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) + if item.ident != Ident::invalid() => + { let orig_directory_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); module.mod_path.push(item.ident); - // Detect if this is an inline module (`mod m { ... }` as opposed to `mod m;`). - // In the non-inline case, `inner` is never the dummy span (cf. `parse_item_mod`). - // Thus, if `inner` is the dummy span, we know the module is inline. - let inline_module = item.span.contains(inner) || inner.is_dummy(); - - if inline_module { + if inline { if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { self.cx.current_expansion.directory_ownership = DirectoryOwnership::Owned { relative: None }; From 33ba83c3a0905c86a6b5182b3b3d35f2f6086e5b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 13 Feb 2020 11:26:09 +0100 Subject: [PATCH 0108/1250] fix typo --- src/librustc_mir/transform/const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 09eb6e952ad..5729cda64f7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -527,7 +527,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_unary_op(op, val)?; Ok(overflow) })? { - // `AssertKind` only has an `OverflowNeg` variant, to make sure that is + // `AssertKind` only has an `OverflowNeg` variant, so make sure that is // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?; From 2440998666cb9fe5f35c1de9ef44849b71870fc3 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Thu, 13 Feb 2020 11:44:12 +0100 Subject: [PATCH 0109/1250] perf(mir): Reserve enough space for the merged blocks before appending --- src/librustc_mir/transform/simplify.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 3a1ccb50465..d8de9f2180d 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -95,6 +95,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { let mut start = START_BLOCK; + let mut merged_blocks = Vec::new(); loop { let mut changed = false; @@ -118,10 +119,23 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { while inner_changed { inner_changed = false; inner_changed |= self.simplify_branch(&mut terminator); - inner_changed |= self.merge_successor(bb, &mut terminator); + inner_changed |= self.merge_successor(&mut merged_blocks, &mut terminator); changed |= inner_changed; } + let merged_block_count = + merged_blocks.iter().map(|&i| self.basic_blocks[i].statements.len()).sum(); + + if merged_block_count > 0 { + let mut statements = std::mem::take(&mut self.basic_blocks[bb].statements); + statements.reserve(merged_block_count); + for &from in &merged_blocks { + statements.append(&mut self.basic_blocks[from].statements); + } + self.basic_blocks[bb].statements = statements; + } + merged_blocks.clear(); + self.basic_blocks[bb].terminator = Some(terminator); changed |= inner_changed; @@ -196,7 +210,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { // merge a block with 1 `goto` predecessor to its parent fn merge_successor( &mut self, - merge_into: BasicBlock, + merged_blocks: &mut Vec, terminator: &mut Terminator<'tcx>, ) -> bool { let target = match terminator.kind { @@ -214,8 +228,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } }; - let (from, to) = self.basic_blocks.pick2_mut(target, merge_into); - to.statements.append(&mut from.statements); + merged_blocks.push(target); self.pred_count[target] = 0; true From f5bd9646be31d865a083193c21c7448d546ce07c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 13 Feb 2020 12:19:36 +0100 Subject: [PATCH 0110/1250] fix extra subslice lowering --- src/librustc_ast_lowering/pat.rs | 17 +++++++----- .../issue-69103-extra-binding-subslice.rs | 18 +++++++++++++ .../issue-69103-extra-binding-subslice.stderr | 26 +++++++++++++++++++ 3 files changed, 55 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs create mode 100644 src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs index 4c3c4ddac78..b42b12c4dd8 100644 --- a/src/librustc_ast_lowering/pat.rs +++ b/src/librustc_ast_lowering/pat.rs @@ -128,6 +128,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut slice = None; let mut prev_rest_span = None; + // Lowers `$bm $ident @ ..` to `$bm $ident @ _`. + let lower_rest_sub = |this: &mut Self, pat, bm, ident, sub| { + let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); + let node = this.lower_pat_ident(pat, bm, ident, lower_sub); + this.pat_with_node_id_of(pat, node) + }; + let mut iter = pats.iter(); // Lower all the patterns until the first occurrence of a sub-slice pattern. for pat in iter.by_ref() { @@ -142,9 +149,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Record, lower it to `$binding_mode $ident @ _`, and stop here. PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { prev_rest_span = Some(sub.span); - let lower_sub = |this: &mut Self| Some(this.pat_wild_with_node_id_of(sub)); - let node = self.lower_pat_ident(pat, bm, ident, lower_sub); - slice = Some(self.pat_with_node_id_of(pat, node)); + slice = Some(lower_rest_sub(self, pat, bm, ident, sub)); break; } // It was not a subslice pattern so lower it normally. @@ -157,9 +162,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // There was a previous subslice pattern; make sure we don't allow more. let rest_span = match pat.kind { PatKind::Rest => Some(pat.span), - PatKind::Ident(.., Some(ref sub)) if sub.is_rest() => { - // The `HirValidator` is merciless; add a `_` pattern to avoid ICEs. - after.push(self.pat_wild_with_node_id_of(pat)); + PatKind::Ident(ref bm, ident, Some(ref sub)) if sub.is_rest() => { + // #69103: Lower into `binding @ _` as above to avoid ICEs. + after.push(lower_rest_sub(self, pat, bm, ident, sub)); Some(sub.span) } _ => None, diff --git a/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs new file mode 100644 index 00000000000..061b0d675b3 --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.rs @@ -0,0 +1,18 @@ +// We used to not lower the extra `b @ ..` into `b @ _` which meant that no type +// was registered for the binding `b` although it passed through resolve. +// This resulted in an ICE (#69103). + +fn main() { + let [a @ .., b @ ..] = &mut [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + b; + + let [.., c @ ..] = [1, 2]; + //~^ ERROR `..` can only be used once per slice pattern + c; + + // This never ICEd, but let's make sure it won't regress either. + let (.., d @ ..) = (1, 2); + //~^ ERROR `..` patterns are not allowed here + d; +} diff --git a/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr new file mode 100644 index 00000000000..9432e2f0c9d --- /dev/null +++ b/src/test/ui/array-slice-vec/issue-69103-extra-binding-subslice.stderr @@ -0,0 +1,26 @@ +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:6:22 + | +LL | let [a @ .., b @ ..] = &mut [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` can only be used once per slice pattern + --> $DIR/issue-69103-extra-binding-subslice.rs:10:18 + | +LL | let [.., c @ ..] = [1, 2]; + | -- ^^ can only be used once per slice pattern + | | + | previously used here + +error: `..` patterns are not allowed here + --> $DIR/issue-69103-extra-binding-subslice.rs:15:18 + | +LL | let (.., d @ ..) = (1, 2); + | ^^ + | + = note: only allowed in tuple, tuple struct, and slice patterns + +error: aborting due to 3 previous errors + From cec2a9fad057f71fc640392ba3fa47602aea12f6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 3 Dec 2019 18:47:44 +0100 Subject: [PATCH 0111/1250] macro_legacy_warnings -> error --- src/librustc_expand/expand.rs | 11 ++-- src/librustc_expand/mbe/macro_rules.rs | 2 +- src/librustc_parse/parser/stmt.rs | 62 +++---------------- .../ui/missing/missing-semicolon-warning.rs | 12 ---- .../missing/missing-semicolon-warning.stderr | 24 ------- src/test/ui/parser/missing-semicolon.rs | 8 +++ src/test/ui/parser/missing-semicolon.stderr | 13 ++++ 7 files changed, 35 insertions(+), 97 deletions(-) delete mode 100644 src/test/ui/missing/missing-semicolon-warning.rs delete mode 100644 src/test/ui/missing/missing-semicolon-warning.stderr create mode 100644 src/test/ui/parser/missing-semicolon.rs create mode 100644 src/test/ui/parser/missing-semicolon.stderr diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9..6b1a41943ce 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -821,7 +821,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { span: Span, ) -> AstFragment { let mut parser = self.cx.new_parser_from_tts(toks); - match parse_ast_fragment(&mut parser, kind, false) { + match parse_ast_fragment(&mut parser, kind) { Ok(fragment) => { ensure_complete_parse(&mut parser, path, kind.name(), span); fragment @@ -840,7 +840,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { pub fn parse_ast_fragment<'a>( this: &mut Parser<'a>, kind: AstFragmentKind, - macro_legacy_warnings: bool, ) -> PResult<'a, AstFragment> { Ok(match kind { AstFragmentKind::Items => { @@ -873,11 +872,9 @@ pub fn parse_ast_fragment<'a>( } AstFragmentKind::Stmts => { let mut stmts = SmallVec::new(); - while this.token != token::Eof && - // won't make progress on a `}` - this.token != token::CloseDelim(token::Brace) - { - if let Some(stmt) = this.parse_full_stmt(macro_legacy_warnings)? { + // Won't make progress on a `}`. + while this.token != token::Eof && this.token != token::CloseDelim(token::Brace) { + if let Some(stmt) = this.parse_full_stmt()? { stmts.push(stmt); } } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 9e6edee265c..6a9f5459cb5 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -87,7 +87,7 @@ fn suggest_slice_pat(e: &mut DiagnosticBuilder<'_>, site_span: Span, parser: &Pa impl<'a> ParserAnyMacro<'a> { crate fn make(mut self: Box>, kind: AstFragmentKind) -> AstFragment { let ParserAnyMacro { site_span, macro_ident, ref mut parser, arm_span } = *self; - let fragment = panictry!(parse_ast_fragment(parser, kind, true).map_err(|mut e| { + let fragment = panictry!(parse_ast_fragment(parser, kind).map_err(|mut e| { if parser.token == token::Eof && e.message().ends_with(", found ``") { if !e.span.is_dummy() { // early end of macro arm (#52866) diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index e11cdd5dadb..928d2a40266 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -22,17 +22,14 @@ impl<'a> Parser<'a> { /// Parses a statement. This stops just before trailing semicolons on everything but items. /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed. pub fn parse_stmt(&mut self) -> PResult<'a, Option> { - Ok(self.parse_stmt_without_recovery(true).unwrap_or_else(|mut e| { + Ok(self.parse_stmt_without_recovery().unwrap_or_else(|mut e| { e.emit(); self.recover_stmt_(SemiColonMode::Break, BlockMode::Ignore); None })) } - fn parse_stmt_without_recovery( - &mut self, - macro_legacy_warnings: bool, - ) -> PResult<'a, Option> { + fn parse_stmt_without_recovery(&mut self) -> PResult<'a, Option> { maybe_whole!(self, NtStmt, |x| Some(x)); let attrs = self.parse_outer_attributes()?; @@ -74,7 +71,7 @@ impl<'a> Parser<'a> { let path = self.parse_path(PathStyle::Expr)?; if self.eat(&token::Not) { - return self.parse_stmt_mac(lo, attrs.into(), path, macro_legacy_warnings); + return self.parse_stmt_mac(lo, attrs.into(), path); } let expr = if self.check(&token::OpenDelim(token::Brace)) { @@ -137,7 +134,6 @@ impl<'a> Parser<'a> { lo: Span, attrs: AttrVec, path: ast::Path, - legacy_warnings: bool, ) -> PResult<'a, Option> { let args = self.parse_mac_args()?; let delim = args.delim(); @@ -150,30 +146,6 @@ impl<'a> Parser<'a> { let kind = if delim == token::Brace || self.token == token::Semi || self.token == token::Eof { - StmtKind::Mac(P((mac, style, attrs.into()))) - } - // We used to incorrectly stop parsing macro-expanded statements here. - // If the next token will be an error anyway but could have parsed with the - // earlier behavior, stop parsing here and emit a warning to avoid breakage. - else if legacy_warnings - && self.token.can_begin_expr() - && match self.token.kind { - // These can continue an expression, so we can't stop parsing and warn. - token::OpenDelim(token::Paren) - | token::OpenDelim(token::Bracket) - | token::BinOp(token::Minus) - | token::BinOp(token::Star) - | token::BinOp(token::And) - | token::BinOp(token::Or) - | token::AndAnd - | token::OrOr - | token::DotDot - | token::DotDotDot - | token::DotDotEq => false, - _ => true, - } - { - self.warn_missing_semicolon(); StmtKind::Mac(P((mac, style, attrs))) } else { // Since none of the above applied, this is an expression statement macro. @@ -334,7 +306,7 @@ impl<'a> Parser<'a> { // bar; // // which is valid in other languages, but not Rust. - match self.parse_stmt_without_recovery(false) { + match self.parse_stmt_without_recovery() { Ok(Some(stmt)) => { if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) || do_not_suggest_help @@ -393,7 +365,7 @@ impl<'a> Parser<'a> { if self.token == token::Eof { break; } - let stmt = match self.parse_full_stmt(false) { + let stmt = match self.parse_full_stmt() { Err(mut err) => { self.maybe_annotate_with_ascription(&mut err, false); err.emit(); @@ -413,11 +385,11 @@ impl<'a> Parser<'a> { } /// Parses a statement, including the trailing semicolon. - pub fn parse_full_stmt(&mut self, macro_legacy_warnings: bool) -> PResult<'a, Option> { + pub fn parse_full_stmt(&mut self) -> PResult<'a, Option> { // Skip looking for a trailing semicolon when we have an interpolated statement. maybe_whole!(self, NtStmt, |x| Some(x)); - let mut stmt = match self.parse_stmt_without_recovery(macro_legacy_warnings)? { + let mut stmt = match self.parse_stmt_without_recovery()? { Some(stmt) => stmt, None => return Ok(None), }; @@ -457,13 +429,8 @@ impl<'a> Parser<'a> { } } StmtKind::Local(..) => { - // We used to incorrectly allow a macro-expanded let statement to lack a semicolon. - if macro_legacy_warnings && self.token != token::Semi { - self.warn_missing_semicolon(); - } else { - self.expect_semi()?; - eat_semi = false; - } + self.expect_semi()?; + eat_semi = false; } _ => {} } @@ -475,17 +442,6 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - fn warn_missing_semicolon(&self) { - self.diagnostic() - .struct_span_warn(self.token.span, { - &format!("expected `;`, found {}", super::token_descr(&self.token)) - }) - .note({ - "this was erroneously allowed and will become a hard error in a future release" - }) - .emit(); - } - pub(super) fn mk_block(&self, stmts: Vec, rules: BlockCheckMode, span: Span) -> P { P(Block { stmts, id: DUMMY_NODE_ID, rules, span }) } diff --git a/src/test/ui/missing/missing-semicolon-warning.rs b/src/test/ui/missing/missing-semicolon-warning.rs deleted file mode 100644 index d962a52139e..00000000000 --- a/src/test/ui/missing/missing-semicolon-warning.rs +++ /dev/null @@ -1,12 +0,0 @@ -// build-pass (FIXME(62277): could be check-pass?) -#![allow(unused)] - -macro_rules! m { - ($($e1:expr),*; $($e2:expr),*) => { - $( let x = $e1 )*; //~ WARN expected `;` - $( println!("{}", $e2) )*; //~ WARN expected `;` - } -} - - -fn main() { m!(0, 0; 0, 0); } diff --git a/src/test/ui/missing/missing-semicolon-warning.stderr b/src/test/ui/missing/missing-semicolon-warning.stderr deleted file mode 100644 index ecaefd47de0..00000000000 --- a/src/test/ui/missing/missing-semicolon-warning.stderr +++ /dev/null @@ -1,24 +0,0 @@ -warning: expected `;`, found keyword `let` - --> $DIR/missing-semicolon-warning.rs:6:12 - | -LL | $( let x = $e1 )*; - | ^^^ -... -LL | fn main() { m!(0, 0; 0, 0); } - | --------------- in this macro invocation - | - = note: this was erroneously allowed and will become a hard error in a future release - = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -warning: expected `;`, found `println` - --> $DIR/missing-semicolon-warning.rs:7:12 - | -LL | $( println!("{}", $e2) )*; - | ^^^^^^^ -... -LL | fn main() { m!(0, 0; 0, 0); } - | --------------- in this macro invocation - | - = note: this was erroneously allowed and will become a hard error in a future release - = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - diff --git a/src/test/ui/parser/missing-semicolon.rs b/src/test/ui/parser/missing-semicolon.rs new file mode 100644 index 00000000000..a24dfa761a6 --- /dev/null +++ b/src/test/ui/parser/missing-semicolon.rs @@ -0,0 +1,8 @@ +macro_rules! m { + ($($e1:expr),*; $($e2:expr),*) => { + $( let x = $e1 )*; //~ ERROR expected one of `.`, `;`, `?`, or + $( println!("{}", $e2) )*; + } +} + +fn main() { m!(0, 0; 0, 0); } diff --git a/src/test/ui/parser/missing-semicolon.stderr b/src/test/ui/parser/missing-semicolon.stderr new file mode 100644 index 00000000000..26cb3d13d9c --- /dev/null +++ b/src/test/ui/parser/missing-semicolon.stderr @@ -0,0 +1,13 @@ +error: expected one of `.`, `;`, `?`, or an operator, found keyword `let` + --> $DIR/missing-semicolon.rs:3:12 + | +LL | $( let x = $e1 )*; + | ^^^ expected one of `.`, `;`, `?`, or an operator +... +LL | fn main() { m!(0, 0; 0, 0); } + | --------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + From 9fed2d587c9d9f28003e23255b863897bd22a8b2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 04:21:16 +0100 Subject: [PATCH 0112/1250] parser: extract common foreign item code for each kind --- src/librustc_parse/parser/item.rs | 88 ++++++++----------------------- 1 file changed, 21 insertions(+), 67 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ccd55c5c08a..0a8f3770862 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -740,7 +740,8 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); - let (name, kind, generics) = if self.eat_keyword(kw::Type) { + + let (ident, kind, generics) = if self.eat_keyword(kw::Type) { self.parse_assoc_ty()? } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; @@ -751,17 +752,9 @@ impl<'a> Parser<'a> { self.parse_assoc_const()? }; - Ok(AssocItem { - id: DUMMY_NODE_ID, - span: lo.to(self.prev_span), - ident: name, - attrs, - vis, - defaultness, - generics, - kind, - tokens: None, - }) + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, generics, kind, tokens: None }) } /// This parses the grammar: @@ -967,7 +960,7 @@ impl<'a> Parser<'a> { Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) } - /// Parses a foreign item. + /// Parses a foreign item (one in an `extern { ... }` block). pub fn parse_foreign_item(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtForeignItem, |ni| ni); @@ -975,27 +968,17 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - if self.check_keyword(kw::Type) { + let (ident, kind) = if self.check_keyword(kw::Type) { // FOREIGN TYPE ITEM - self.parse_item_foreign_type(vis, lo, attrs) + self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { // FOREIGN FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ForeignItemKind::Fn(sig, generics, body); - let span = lo.to(self.prev_span); - Ok(P(ast::ForeignItem { - ident, - attrs, - kind, - id: DUMMY_NODE_ID, - span, - vis, - tokens: None, - })) + (ident, ForeignItemKind::Fn(sig, generics, body)) } else if self.is_static_global() { // FOREIGN STATIC ITEM self.bump(); // `static` - self.parse_item_foreign_static(vis, lo, attrs) + self.parse_item_foreign_static()? } else if self.token.is_keyword(kw::Const) { // Treat `const` as `static` for error recovery, but don't add it to expected tokens. self.bump(); // `const` @@ -1007,66 +990,37 @@ impl<'a> Parser<'a> { Applicability::MachineApplicable, ) .emit(); - self.parse_item_foreign_static(vis, lo, attrs) + self.parse_item_foreign_static()? } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), &mut false)? { - let kind = ForeignItemKind::Macro(mac); - let span = lo.to(self.prev_span); - let ident = Ident::invalid(); - Ok(P(ForeignItem { ident, span, id: DUMMY_NODE_ID, attrs, vis, kind, tokens: None })) + (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { if !attrs.is_empty() { self.expected_item_err(&attrs)?; } - self.unexpected() - } + self.unexpected()? + }; + + let span = lo.to(self.prev_span); + Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) } /// Parses a static item from a foreign module. /// Assumes that the `static` keyword is already parsed. - fn parse_item_foreign_static( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let mutbl = self.parse_mutability(); let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Static(ty, mutbl), - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Static(ty, mutbl))) } /// Parses a type from a foreign module. - fn parse_item_foreign_type( - &mut self, - vis: ast::Visibility, - lo: Span, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { self.expect_keyword(kw::Type)?; - let ident = self.parse_ident()?; - let hi = self.token.span; self.expect_semi()?; - Ok(P(ast::ForeignItem { - ident, - attrs, - kind: ForeignItemKind::Ty, - id: DUMMY_NODE_ID, - span: lo.to(hi), - vis, - tokens: None, - })) + Ok((ident, ForeignItemKind::Ty)) } fn is_static_global(&mut self) -> bool { From 7737d0ffdef6f3d7395e80291e3143522f46b95b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 06:43:33 +0100 Subject: [PATCH 0113/1250] parser: unify item list parsing. as a consequence, `trait X { #![attr] }` becomes legal. --- src/librustc_ast_pretty/pprust.rs | 1 + src/librustc_expand/expand.rs | 2 +- src/librustc_parse/parser/item.rs | 102 ++++++++---------- src/test/pretty/trait-inner-attr.rs | 7 ++ src/test/ui/parser/attrs-after-extern-mod.rs | 10 +- .../ui/parser/attrs-after-extern-mod.stderr | 2 +- .../ui/parser/doc-before-extern-rbrace.rs | 4 +- .../ui/parser/doc-before-extern-rbrace.stderr | 7 +- .../ui/parser/doc-inside-trait-item.stderr | 2 +- src/test/ui/parser/duplicate-visibility.rs | 3 + .../ui/parser/duplicate-visibility.stderr | 2 +- src/test/ui/parser/inner-attr-in-trait-def.rs | 9 ++ 12 files changed, 80 insertions(+), 71 deletions(-) create mode 100644 src/test/pretty/trait-inner-attr.rs create mode 100644 src/test/ui/parser/inner-attr-in-trait-def.rs diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b1fa818d0a8..75938470b6f 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1269,6 +1269,7 @@ impl<'a> State<'a> { self.print_where_clause(&generics.where_clause); self.s.word(" "); self.bopen(); + self.print_inner_attributes(&item.attrs); for trait_item in trait_items { self.print_assoc_item(trait_item); } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 90692fe1ec9..0968e92c203 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -867,7 +867,7 @@ pub fn parse_ast_fragment<'a>( AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); while this.token != token::Eof { - items.push(this.parse_foreign_item()?); + items.push(this.parse_foreign_item(&mut false)?); } AstFragment::ForeignItems(items) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0a8f3770862..f4ca84b005b 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -515,7 +515,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let (impl_items, attrs) = self.parse_impl_body()?; + let (impl_items, attrs) = self.parse_item_list(|p, at_end| p.parse_impl_item(at_end))?; let item_kind = match ty_second { Some(ty_second) => { @@ -571,15 +571,21 @@ impl<'a> Parser<'a> { Ok((Ident::invalid(), item_kind, Some(attrs))) } - fn parse_impl_body(&mut self) -> PResult<'a, (Vec>, Vec)> { + fn parse_item_list( + &mut self, + mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, + ) -> PResult<'a, (Vec, Vec)> { self.expect(&token::OpenDelim(token::Brace))?; let attrs = self.parse_inner_attributes()?; - let mut impl_items = Vec::new(); + let mut items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { + if self.recover_doc_comment_before_brace() { + continue; + } let mut at_end = false; - match self.parse_impl_item(&mut at_end) { - Ok(impl_item) => impl_items.push(impl_item), + match parse_item(self, &mut at_end) { + Ok(item) => items.push(item), Err(mut err) => { err.emit(); if !at_end { @@ -589,7 +595,30 @@ impl<'a> Parser<'a> { } } } - Ok((impl_items, attrs)) + Ok((items, attrs)) + } + + /// Recover on a doc comment before `}`. + fn recover_doc_comment_before_brace(&mut self) -> bool { + if let token::DocComment(_) = self.token.kind { + if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { + struct_span_err!( + self.diagnostic(), + self.token.span, + E0584, + "found a documentation comment that doesn't document anything", + ) + .span_label(self.token.span, "this doc comment doesn't document anything") + .help( + "doc comments must come before what they document, maybe a \ + comment was intended with `//`?", + ) + .emit(); + self.bump(); + return true; + } + } + false } /// Parses defaultness (i.e., `default` or nothing). @@ -660,39 +689,8 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - self.expect(&token::OpenDelim(token::Brace))?; - let mut trait_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - if let token::DocComment(_) = self.token.kind { - if self.look_ahead(1, |tok| tok == &token::CloseDelim(token::Brace)) { - struct_span_err!( - self.diagnostic(), - self.token.span, - E0584, - "found a documentation comment that doesn't document anything", - ) - .help( - "doc comments must come before what they document, maybe a \ - comment was intended with `//`?", - ) - .emit(); - self.bump(); - continue; - } - } - let mut at_end = false; - match self.parse_trait_item(&mut at_end) { - Ok(item) => trait_items.push(item), - Err(mut e) => { - e.emit(); - if !at_end { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - break; - } - } - } - } - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, trait_items), None)) + let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_trait_item(at_end))?; + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items), Some(attrs))) } } @@ -942,26 +940,18 @@ impl<'a> Parser<'a> { &mut self, lo: Span, abi: Option, - visibility: Visibility, + vis: Visibility, mut attrs: Vec, ) -> PResult<'a, P> { - self.expect(&token::OpenDelim(token::Brace))?; - - attrs.extend(self.parse_inner_attributes()?); - - let mut foreign_items = vec![]; - while !self.eat(&token::CloseDelim(token::Brace)) { - foreign_items.push(self.parse_foreign_item()?); - } - - let prev_span = self.prev_span; - let m = ast::ForeignMod { abi, items: foreign_items }; - let invalid = Ident::invalid(); - Ok(self.mk_item(lo.to(prev_span), invalid, ItemKind::ForeignMod(m), visibility, attrs)) + let (items, iattrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + attrs.extend(iattrs); + let span = lo.to(self.prev_span); + let m = ast::ForeignMod { abi, items }; + Ok(self.mk_item(span, Ident::invalid(), ItemKind::ForeignMod(m), vis, attrs)) } /// Parses a foreign item (one in an `extern { ... }` block). - pub fn parse_foreign_item(&mut self) -> PResult<'a, P> { + pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { maybe_whole!(self, NtForeignItem, |ni| ni); let mut attrs = self.parse_outer_attributes()?; @@ -973,7 +963,7 @@ impl<'a> Parser<'a> { self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { // FOREIGN FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; + let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, |_| true)?; (ident, ForeignItemKind::Fn(sig, generics, body)) } else if self.is_static_global() { // FOREIGN STATIC ITEM @@ -991,7 +981,7 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), &mut false)? { + } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), at_end)? { (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { if !attrs.is_empty() { diff --git a/src/test/pretty/trait-inner-attr.rs b/src/test/pretty/trait-inner-attr.rs new file mode 100644 index 00000000000..bb4fb1459bd --- /dev/null +++ b/src/test/pretty/trait-inner-attr.rs @@ -0,0 +1,7 @@ +// pp-exact + +trait Foo { + #![allow(bar)] +} + +fn main() { } diff --git a/src/test/ui/parser/attrs-after-extern-mod.rs b/src/test/ui/parser/attrs-after-extern-mod.rs index 4bdd16471cd..ea899dca7b2 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.rs +++ b/src/test/ui/parser/attrs-after-extern-mod.rs @@ -1,13 +1,7 @@ -// Constants (static variables) can be used to match in patterns, but mutable -// statics cannot. This ensures that there's some form of error if this is -// attempted. +// Make sure there's an error when given `extern { ... #[attr] }`. -extern crate libc; +fn main() {} extern { - static mut rust_dbg_static_mut: libc::c_int; - pub fn rust_dbg_static_mut_check_four(); #[cfg(stage37)] //~ ERROR expected item after attributes } - -pub fn main() {} diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index cecdab4d631..a02e738a2c3 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,5 +1,5 @@ error: expected item after attributes - --> $DIR/attrs-after-extern-mod.rs:10:19 + --> $DIR/attrs-after-extern-mod.rs:6:19 | LL | #[cfg(stage37)] | ^ diff --git a/src/test/ui/parser/doc-before-extern-rbrace.rs b/src/test/ui/parser/doc-before-extern-rbrace.rs index 695d4da1dca..040206b80ff 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.rs +++ b/src/test/ui/parser/doc-before-extern-rbrace.rs @@ -1,4 +1,6 @@ +fn main() {} + extern { /// hi - //~^ ERROR expected item after doc comment + //~^ ERROR found a documentation comment that doesn't document anything } diff --git a/src/test/ui/parser/doc-before-extern-rbrace.stderr b/src/test/ui/parser/doc-before-extern-rbrace.stderr index 8cc9c916a7a..0edceb268a7 100644 --- a/src/test/ui/parser/doc-before-extern-rbrace.stderr +++ b/src/test/ui/parser/doc-before-extern-rbrace.stderr @@ -1,8 +1,11 @@ -error: expected item after doc comment - --> $DIR/doc-before-extern-rbrace.rs:2:5 +error[E0584]: found a documentation comment that doesn't document anything + --> $DIR/doc-before-extern-rbrace.rs:4:5 | LL | /// hi | ^^^^^^ this doc comment doesn't document anything + | + = help: doc comments must come before what they document, maybe a comment was intended with `//`? error: aborting due to previous error +For more information about this error, try `rustc --explain E0584`. diff --git a/src/test/ui/parser/doc-inside-trait-item.stderr b/src/test/ui/parser/doc-inside-trait-item.stderr index 261e27b6e0d..246255a0a46 100644 --- a/src/test/ui/parser/doc-inside-trait-item.stderr +++ b/src/test/ui/parser/doc-inside-trait-item.stderr @@ -2,7 +2,7 @@ error[E0584]: found a documentation comment that doesn't document anything --> $DIR/doc-inside-trait-item.rs:3:5 | LL | /// empty doc - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ this doc comment doesn't document anything | = help: doc comments must come before what they document, maybe a comment was intended with `//`? diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index a8f0b7d61b9..edbf508ecdb 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,4 +1,7 @@ // error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn` + +fn main() {} + extern { pub pub fn foo(); } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index cba4058e482..92cf3487969 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,5 +1,5 @@ error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:3:9 + --> $DIR/duplicate-visibility.rs:6:9 | LL | pub pub fn foo(); | ^^^ expected one of 8 possible tokens diff --git a/src/test/ui/parser/inner-attr-in-trait-def.rs b/src/test/ui/parser/inner-attr-in-trait-def.rs new file mode 100644 index 00000000000..8dba6b362cd --- /dev/null +++ b/src/test/ui/parser/inner-attr-in-trait-def.rs @@ -0,0 +1,9 @@ +// check-pass + +#![deny(non_camel_case_types)] + +fn main() {} + +trait foo_bar { + #![allow(non_camel_case_types)] +} From 511dfdb8b3d8c6d395b1b5a205c3464ae802509f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 07:00:19 +0100 Subject: [PATCH 0114/1250] parser: extract `recover_missing_kw_before_item` --- src/librustc_parse/parser/item.rs | 174 +++++++++++++++--------------- 1 file changed, 90 insertions(+), 84 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f4ca84b005b..acbae7dfd68 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -203,101 +203,107 @@ impl<'a> Parser<'a> { return Ok(Some(macro_def)); } - // Verify whether we have encountered a struct or method definition where the user forgot to - // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { - // Space between `pub` keyword and the identifier - // - // pub S {} - // ^^^ `sp` points here - let sp = self.prev_span.between(self.token.span); - let full_sp = self.prev_span.to(self.token.span); - let ident_sp = self.token.span; - if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { - // possible public struct definition where `struct` was forgotten - let ident = self.parse_ident().unwrap(); - let msg = format!("add `struct` here to parse `{}` as a public struct", ident); - let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + self.recover_missing_kw_before_item()?; + } + self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) + } + + /// Recover on encountering a struct or method definition where the user + /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. + fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { + // Space between `pub` keyword and the identifier + // + // pub S {} + // ^^^ `sp` points here + let sp = self.prev_span.between(self.token.span); + let full_sp = self.prev_span.to(self.token.span); + let ident_sp = self.token.span; + if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { + // possible public struct definition where `struct` was forgotten + let ident = self.parse_ident().unwrap(); + let msg = format!("add `struct` here to parse `{}` as a public struct", ident); + let mut err = self.struct_span_err(sp, "missing `struct` for struct definition"); + err.span_suggestion_short( + sp, + &msg, + " struct ".into(), + Applicability::MaybeIncorrect, // speculative + ); + return Err(err); + } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { + let ident = self.parse_ident().unwrap(); + self.bump(); // `(` + let kw_name = self.recover_first_param(); + self.consume_block(token::Paren, ConsumeClosingDelim::Yes); + let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { + self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.bump(); // `{` + ("fn", kw_name, false) + } else if self.check(&token::Colon) { + let kw = "struct"; + (kw, kw, false) + } else { + ("fn` or `struct", "function or struct", true) + }; + + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + let suggestion = + format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); err.span_suggestion_short( sp, - &msg, - " struct ".into(), - Applicability::MaybeIncorrect, // speculative + &suggestion, + format!(" {} ", kw), + Applicability::MachineApplicable, ); - return Err(err); - } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { - let ident = self.parse_ident().unwrap(); - self.bump(); // `(` - let kw_name = self.recover_first_param(); - self.consume_block(token::Paren, ConsumeClosingDelim::Yes); - let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) { - self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]); - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::OpenDelim(token::Brace)) { - self.bump(); // `{` - ("fn", kw_name, false) - } else if self.check(&token::Colon) { - let kw = "struct"; - (kw, kw, false) - } else { - ("fn` or `struct", "function or struct", true) - }; - - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - let suggestion = - format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name); - err.span_suggestion_short( - sp, - &suggestion, - format!(" {} ", kw), - Applicability::MachineApplicable, + } else { + if let Ok(snippet) = self.span_to_snippet(ident_sp) { + err.span_suggestion( + full_sp, + "if you meant to call a macro, try", + format!("{}!", snippet), + // this is the `ambiguous` conditional branch + Applicability::MaybeIncorrect, ); } else { - if let Ok(snippet) = self.span_to_snippet(ident_sp) { - err.span_suggestion( - full_sp, - "if you meant to call a macro, try", - format!("{}!", snippet), - // this is the `ambiguous` conditional branch - Applicability::MaybeIncorrect, - ); - } else { - err.help( - "if you meant to call a macro, remove the `pub` \ + err.help( + "if you meant to call a macro, remove the `pub` \ and add a trailing `!` after the identifier", - ); - } - } - return Err(err); - } else if self.look_ahead(1, |t| *t == token::Lt) { - let ident = self.parse_ident().unwrap(); - self.eat_to_tokens(&[&token::Gt]); - self.bump(); // `>` - let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { - ("fn", self.recover_first_param(), false) - } else if self.check(&token::OpenDelim(token::Brace)) { - ("struct", "struct", false) - } else { - ("fn` or `struct", "function or struct", true) - }; - let msg = format!("missing `{}` for {} definition", kw, kw_name); - let mut err = self.struct_span_err(sp, &msg); - if !ambiguous { - err.span_suggestion_short( - sp, - &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), - format!(" {} ", kw), - Applicability::MachineApplicable, ); } - return Err(err); } + return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); // `>` + let (kw, kw_name, ambiguous) = if self.eat(&token::OpenDelim(token::Paren)) { + ("fn", self.recover_first_param(), false) + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "function or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); + } + return Err(err); + } else { + Ok(()) } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) } pub(super) fn mk_item_with_info( From 73d5970cdc304c874cd6d7d594f3abb7317f1519 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 08:37:09 +0100 Subject: [PATCH 0115/1250] parser: introduce `parse_item_kind` as central `ItemInfo` logic. this also extracts macro item parsers. --- src/librustc_parse/parser/item.rs | 348 ++++++++---------- src/test/ui/pub/pub-restricted-error-fn.rs | 3 +- .../ui/pub/pub-restricted-error-fn.stderr | 14 +- 3 files changed, 168 insertions(+), 197 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index acbae7dfd68..9ba3be041b5 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -11,7 +11,7 @@ use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::BytePos; use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; -use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, StrLit, Unsafe}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; @@ -83,45 +83,60 @@ impl<'a> Parser<'a> { }); let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - if self.eat_keyword(kw::Use) { - // USE ITEM - let item_ = ItemKind::Use(P(self.parse_use_tree()?)); - self.expect_semi()?; + if let Some(info) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { + return Ok(Some(self.mk_item_with_info(attrs, lo, vis, info))); + } - let span = lo.to(self.prev_span); - let item = self.mk_item(span, Ident::invalid(), item_, vis, attrs); - return Ok(Some(item)); + // FAILURE TO PARSE ITEM + match vis.node { + VisibilityKind::Inherited => {} + _ => { + self.struct_span_err(vis.span, "unmatched visibility `pub`") + .span_label(vis.span, "the unmatched visibility") + .help("you likely meant to define an item, e.g., `pub fn foo() {}`") + .emit(); + } } - if self.check_fn_front_matter() { - // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, &mut attrs, |_| true)?; - let kind = ItemKind::Fn(sig, generics, body); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); + if !attributes_allowed && !attrs.is_empty() { + self.expected_item_err(&attrs)?; } + Ok(None) + } - if self.eat_keyword(kw::Extern) { + /// Parses one of the items allowed by the flags. + fn parse_item_kind( + &mut self, + attrs: &mut Vec, + macros_allowed: bool, + lo: Span, + vis: &Visibility, + ) -> PResult<'a, Option> { + let info = if self.eat_keyword(kw::Use) { + // USE ITEM + let tree = self.parse_use_tree()?; + self.expect_semi()?; + (Ident::invalid(), ItemKind::Use(P(tree)), None) + } else if self.check_fn_front_matter() { + // FUNCTION ITEM + let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; + (ident, ItemKind::Fn(sig, generics, body), None) + } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE - return Ok(Some(self.parse_item_extern_crate(lo, vis, attrs)?)); + self.parse_item_extern_crate()? + } else { + // EXTERN BLOCK + self.parse_item_foreign_mod()? } - // EXTERN BLOCK - let abi = self.parse_abi(); - return Ok(Some(self.parse_item_foreign_mod(lo, abi, vis, attrs)?)); - } - - if self.is_static_global() { + } else if self.is_static_global() { // STATIC ITEM - self.bump(); + self.bump(); // `static` let m = self.parse_mutability(); - let info = self.parse_item_const(Some(m))?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if let Const::Yes(const_span) = self.parse_constness() { + self.parse_item_const(Some(m))? + } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM if self.eat_keyword(kw::Mut) { let prev_span = self.prev_span; @@ -136,18 +151,13 @@ impl<'a> Parser<'a> { .emit(); } - let info = self.parse_item_const(None)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) { + self.parse_item_const(None)? + } else if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + { // UNSAFE TRAIT ITEM let unsafety = self.parse_unsafety(); - let info = self.parse_item_trait(lo, unsafety)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Impl) + self.parse_item_trait(lo, unsafety)? + } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { @@ -155,58 +165,48 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - let info = self.parse_item_impl(unsafety, defaultness)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Mod) { + self.parse_item_impl(unsafety, defaultness)? + } else if self.eat_keyword(kw::Mod) { // MODULE ITEM - let info = self.parse_item_mod(&attrs[..])?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Type) { + self.parse_item_mod(&attrs[..])? + } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; - let kind = ItemKind::TyAlias(ty, generics); - return self.mk_item_with_info(attrs, lo, vis, (ident, kind, None)); - } - - if self.eat_keyword(kw::Enum) { + (ident, ItemKind::TyAlias(ty, generics), None) + } else if self.eat_keyword(kw::Enum) { // ENUM ITEM - let info = self.parse_item_enum()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.check_keyword(kw::Trait) + self.parse_item_enum()? + } else if self.check_keyword(kw::Trait) || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - let info = self.parse_item_trait(lo, Unsafe::No)?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.eat_keyword(kw::Struct) { + self.parse_item_trait(lo, Unsafe::No)? + } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM - let info = self.parse_item_struct()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if self.is_union_item() { + self.parse_item_struct()? + } else if self.is_union_item() { // UNION ITEM - self.bump(); - let info = self.parse_item_union()?; - return self.mk_item_with_info(attrs, lo, vis, info); - } - - if let Some(macro_def) = self.eat_macro_def(&attrs, &vis, lo)? { - return Ok(Some(macro_def)); - } - - if vis.node.is_pub() && self.check_ident() && self.look_ahead(1, |t| *t != token::Not) { + self.bump(); // `union` + self.parse_item_union()? + } else if self.eat_keyword(kw::Macro) { + // MACROS 2.0 ITEM + self.parse_item_decl_macro(lo)? + } else if self.is_macro_rules_item() { + // MACRO_RULES ITEM + self.parse_item_macro_rules(vis)? + } else if vis.node.is_pub() + && self.check_ident() + && self.look_ahead(1, |t| *t != token::Not) + { self.recover_missing_kw_before_item()?; - } - self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, vis) + return Ok(None); + } else if macros_allowed && self.token.is_path_start() { + // MACRO INVOCATION ITEM + self.parse_item_macro(vis)? + } else { + return Ok(None); + }; + Ok(Some(info)) } /// Recover on encountering a struct or method definition where the user @@ -312,11 +312,11 @@ impl<'a> Parser<'a> { lo: Span, vis: Visibility, info: ItemInfo, - ) -> PResult<'a, Option>> { + ) -> P { let (ident, item, extra_attrs) = info; let span = lo.to(self.prev_span); let attrs = Self::maybe_append(attrs, extra_attrs); - Ok(Some(self.mk_item(span, ident, item, vis, attrs))) + self.mk_item(span, ident, item, vis, attrs) } fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { @@ -326,49 +326,20 @@ impl<'a> Parser<'a> { lhs } - /// This is the fall-through for parsing items. - fn parse_macro_use_or_failure( - &mut self, - attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, - lo: Span, - visibility: Visibility, - ) -> PResult<'a, Option>> { - if macros_allowed - && self.token.is_path_start() - && !(self.is_async_fn() && self.token.span.rust_2015()) - { - // MACRO INVOCATION ITEM - - let prev_span = self.prev_span; - self.complain_if_pub_macro(&visibility.node, prev_span); - - // Item macro - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; - let args = self.parse_mac_args()?; - if args.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - let hi = self.prev_span; - let mac = Mac { path, args, 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)); - } + /// Parses an item macro, e.g., `item!();`. + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + self.complain_if_pub_macro(&vis.node, vis.span); - // FAILURE TO PARSE ITEM - match visibility.node { - VisibilityKind::Inherited => {} - _ => return Err(self.struct_span_err(self.prev_span, "unmatched visibility `pub`")), + // Item macro + let path = self.parse_path(PathStyle::Mod)?; + self.expect(&token::Not)?; + let args = self.parse_mac_args()?; + if args.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(); } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } - Ok(None) + let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; + Ok((Ident::invalid(), ItemKind::Mac(mac), None)) } /// Emits an expected-item-after-attributes error. @@ -874,12 +845,7 @@ impl<'a> Parser<'a> { /// extern crate foo; /// extern crate bar as foo; /// ``` - fn parse_item_extern_crate( - &mut self, - lo: Span, - visibility: Visibility, - attrs: Vec, - ) -> PResult<'a, P> { + fn parse_item_extern_crate(&mut self) -> PResult<'a, ItemInfo> { // Accept `extern crate name-like-this` for better diagnostics let orig_name = self.parse_crate_name_with_dashes()?; let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? { @@ -888,9 +854,7 @@ impl<'a> Parser<'a> { (orig_name, None) }; self.expect_semi()?; - - let span = lo.to(self.prev_span); - Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs)) + Ok((item_name, ItemKind::ExternCrate(orig_name), None)) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { @@ -933,8 +897,7 @@ impl<'a> Parser<'a> { /// Parses `extern` for foreign ABIs modules. /// - /// `extern` is expected to have been - /// consumed before calling this method. + /// `extern` is expected to have been consumed before calling this method. /// /// # Examples /// @@ -942,18 +905,11 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod( - &mut self, - lo: Span, - abi: Option, - vis: Visibility, - mut attrs: Vec, - ) -> PResult<'a, P> { - let (items, iattrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; - attrs.extend(iattrs); - let span = lo.to(self.prev_span); - let m = ast::ForeignMod { abi, items }; - Ok(self.mk_item(span, Ident::invalid(), ItemKind::ForeignMod(m), vis, attrs)) + fn parse_item_foreign_mod(&mut self) -> PResult<'a, ItemInfo> { + let abi = self.parse_abi(); // ABI? + let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + let module = ast::ForeignMod { abi, items }; + Ok((Ident::invalid(), ItemKind::ForeignMod(module), Some(attrs))) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1386,64 +1342,72 @@ impl<'a> Parser<'a> { }) } - pub(super) fn eat_macro_def( - &mut self, - attrs: &[Attribute], - vis: &Visibility, - lo: Span, - ) -> PResult<'a, Option>> { - let (ident, def) = if self.eat_keyword(kw::Macro) { - let ident = self.parse_ident()?; + /// Parses a declarative macro 2.0 definition. + /// The `macro` keyword has already been parsed. + fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { + let ident = self.parse_ident()?; + let body = if self.check(&token::OpenDelim(token::Brace)) { + self.parse_mac_args()? + } else if self.check(&token::OpenDelim(token::Paren)) { + let params = self.parse_token_tree(); + let pspan = params.span(); let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? - } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); - let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { - return self.unexpected(); - }; - let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); - let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); - P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) + self.parse_token_tree() } else { return self.unexpected(); }; + let bspan = body.span(); + let tokens = TokenStream::new(vec![ + params.into(), + TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), + body.into(), + ]); + let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); + P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) + } else { + return self.unexpected(); + }; + + self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_span)); + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }), None)) + } - (ident, ast::MacroDef { body, legacy: false }) - } else if self.check_keyword(sym::macro_rules) + /// Is this unambiguously the start of a `macro_rules! foo` item defnition? + fn is_macro_rules_item(&mut self) -> bool { + self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) - { - let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis.node, prev_span); - self.bump(); - self.bump(); - - let ident = self.parse_ident()?; - let body = self.parse_mac_args()?; - if body.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - (ident, ast::MacroDef { body, legacy: true }) - } else { - return Ok(None); - }; + } - let span = lo.to(self.prev_span); + /// Parses a legacy `macro_rules! foo { ... }` declarative macro. + fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { + self.complain_if_pub_macro(&vis.node, vis.span); + self.expect_keyword(sym::macro_rules)?; // `macro_rules` + self.expect(&token::Not)?; // `!` - if !def.legacy { - self.sess.gated_spans.gate(sym::decl_macro, span); + let ident = self.parse_ident()?; + let body = self.parse_mac_args()?; + if body.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(); } - Ok(Some(self.mk_item(span, ident, ItemKind::MacroDef(def), vis.clone(), attrs.to_vec()))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }), None)) + } + + pub(super) fn eat_macro_def( + &mut self, + attrs: &[Attribute], + vis: &Visibility, + lo: Span, + ) -> PResult<'a, Option>> { + let info = if self.eat_keyword(kw::Macro) { + self.parse_item_decl_macro(lo)? + } else if self.is_macro_rules_item() { + self.parse_item_macro_rules(vis)? + } else { + return Ok(None); + }; + Ok(Some(self.mk_item_with_info(attrs.to_vec(), lo, vis.clone(), info))) } fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs index 56ee02f517c..3f8904fbe79 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.rs +++ b/src/test/ui/pub/pub-restricted-error-fn.rs @@ -1,3 +1,2 @@ -#![feature(pub_restricted)] - pub(crate) () fn foo() {} //~ unmatched visibility +//~^ ERROR expected item, found `(` diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index fcff5334890..c5acb92dcd4 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,8 +1,16 @@ error: unmatched visibility `pub` - --> $DIR/pub-restricted-error-fn.rs:3:10 + --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} - | ^ + | ^^^^^^^^^^ the unmatched visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: expected item, found `(` + --> $DIR/pub-restricted-error-fn.rs:1:12 + | +LL | pub(crate) () fn foo() {} + | ^ expected item -error: aborting due to previous error +error: aborting due to 2 previous errors From 20ba6875e695dd985ba7f8974cc10c665f687670 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 11:35:36 +0100 Subject: [PATCH 0116/1250] parser_item_mod: avoid cloning outer attributes --- src/librustc_parse/config.rs | 11 +++-------- src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/module.rs | 26 ++++++++++++-------------- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 8dec64c579e..1c479295af3 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -562,14 +562,9 @@ fn is_cfg(attr: &Attribute) -> bool { /// Process the potential `cfg` attributes on a module. /// Also determine if the module should be included in this configuration. -pub fn process_configure_mod( - sess: &ParseSess, - cfg_mods: bool, - attrs: &[Attribute], -) -> (bool, Vec) { +pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { // Don't perform gated feature checking. let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let mut attrs = attrs.to_owned(); - strip_unconfigured.process_cfg_attrs(&mut attrs); - (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs) + strip_unconfigured.process_cfg_attrs(attrs); + !cfg_mods || strip_unconfigured.in_cfg(&attrs) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 9ba3be041b5..38e87cfbc07 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -168,7 +168,7 @@ impl<'a> Parser<'a> { self.parse_item_impl(unsafety, defaultness)? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM - self.parse_item_mod(&attrs[..])? + self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 0c8fad03d86..36a1e87956f 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -40,36 +40,34 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { - let (in_cfg, outer_attrs) = - crate::config::process_configure_mod(self.sess, self.cfg_mods, outer_attrs); + pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); let id_span = self.token.span; let id = self.parse_ident()?; - if self.eat(&token::Semi) { + let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &outer_attrs, id_span)?; - let (module, attrs) = - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)?; - Ok((id, ItemKind::Mod(module), Some(attrs))) + self.submod_path(id, &attrs, id_span)?; + self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? } else { - let placeholder = ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }; - Ok((id, ItemKind::Mod(placeholder), None)) + (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } } else { let old_directory = self.directory.clone(); - self.push_directory(id, &outer_attrs); + self.push_directory(id, &attrs); self.expect(&token::OpenDelim(token::Brace))?; let mod_inner_lo = self.token.span; - let attrs = self.parse_inner_attributes()?; + let inner_attrs = self.parse_inner_attributes()?; let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; self.directory = old_directory; - Ok((id, ItemKind::Mod(module), Some(attrs))) - } + (module, inner_attrs) + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module), None)) } /// Given a termination token, parses all of the items in a module. From c2026030b5d761a83d62c7e198057b119addcfd1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 12:09:21 +0100 Subject: [PATCH 0117/1250] parser: remove `Option>` in `ItemInfo`. --- src/librustc_parse/parser/item.rs | 107 +++++++++++++--------------- src/librustc_parse/parser/module.rs | 2 +- 2 files changed, 50 insertions(+), 59 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 38e87cfbc07..745d125b58c 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -22,7 +22,7 @@ use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree}; use log::debug; use std::mem; -pub(super) type ItemInfo = (Ident, ItemKind, Option>); +pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { pub fn parse_item(&mut self) -> PResult<'a, Option>> { @@ -85,8 +85,8 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - if let Some(info) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(self.mk_item_with_info(attrs, lo, vis, info))); + if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { + return Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis, attrs))); } // FAILURE TO PARSE ITEM @@ -118,18 +118,18 @@ impl<'a> Parser<'a> { // USE ITEM let tree = self.parse_use_tree()?; self.expect_semi()?; - (Ident::invalid(), ItemKind::Use(P(tree)), None) + (Ident::invalid(), ItemKind::Use(P(tree))) } else if self.check_fn_front_matter() { // FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; - (ident, ItemKind::Fn(sig, generics, body), None) + (ident, ItemKind::Fn(sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE self.parse_item_extern_crate()? } else { // EXTERN BLOCK - self.parse_item_foreign_mod()? + self.parse_item_foreign_mod(attrs)? } } else if self.is_static_global() { // STATIC ITEM @@ -156,7 +156,7 @@ impl<'a> Parser<'a> { { // UNSAFE TRAIT ITEM let unsafety = self.parse_unsafety(); - self.parse_item_trait(lo, unsafety)? + self.parse_item_trait(attrs, lo, unsafety)? } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) @@ -165,14 +165,14 @@ impl<'a> Parser<'a> { let defaultness = self.parse_defaultness(); let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; - self.parse_item_impl(unsafety, defaultness)? + self.parse_item_impl(attrs, unsafety, defaultness)? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM let (ident, ty, generics) = self.parse_type_alias()?; - (ident, ItemKind::TyAlias(ty, generics), None) + (ident, ItemKind::TyAlias(ty, generics)) } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? @@ -180,7 +180,7 @@ impl<'a> Parser<'a> { || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) { // TRAIT ITEM - self.parse_item_trait(lo, Unsafe::No)? + self.parse_item_trait(attrs, lo, Unsafe::No)? } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? @@ -306,26 +306,6 @@ impl<'a> Parser<'a> { } } - pub(super) fn mk_item_with_info( - &self, - attrs: Vec, - lo: Span, - vis: Visibility, - info: ItemInfo, - ) -> P { - let (ident, item, extra_attrs) = info; - let span = lo.to(self.prev_span); - let attrs = Self::maybe_append(attrs, extra_attrs); - self.mk_item(span, ident, item, vis, attrs) - } - - fn maybe_append(mut lhs: Vec, mut rhs: Option>) -> Vec { - if let Some(ref mut rhs) = rhs { - lhs.append(rhs); - } - lhs - } - /// Parses an item macro, e.g., `item!();`. fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { self.complain_if_pub_macro(&vis.node, vis.span); @@ -339,7 +319,7 @@ impl<'a> Parser<'a> { } let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok((Ident::invalid(), ItemKind::Mac(mac), None)) + Ok((Ident::invalid(), ItemKind::Mac(mac))) } /// Emits an expected-item-after-attributes error. @@ -428,16 +408,21 @@ impl<'a> Parser<'a> { /// Parses an implementation item, `impl` keyword is already parsed. /// - /// impl<'a, T> TYPE { /* impl items */ } - /// impl<'a, T> TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } - /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` + /// impl<'a, T> TYPE { /* impl items */ } + /// impl<'a, T> TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> !TRAIT for TYPE { /* impl items */ } + /// impl<'a, T> const TRAIT for TYPE { /* impl items */ } + /// ``` /// /// We actually parse slightly more relaxed grammar for better error reporting and recovery. - /// `impl` GENERICS `const`? `!`? TYPE `for`? (TYPE | `..`) (`where` PREDICATES)? `{` BODY `}` - /// `impl` GENERICS `const`? `!`? TYPE (`where` PREDICATES)? `{` BODY `}` + /// ``` + /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}" + /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}" + /// ``` fn parse_item_impl( &mut self, + attrs: &mut Vec, unsafety: Unsafe, defaultness: Defaultness, ) -> PResult<'a, ItemInfo> { @@ -492,7 +477,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let (impl_items, attrs) = self.parse_item_list(|p, at_end| p.parse_impl_item(at_end))?; + let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?; let item_kind = match ty_second { Some(ty_second) => { @@ -545,15 +530,16 @@ impl<'a> Parser<'a> { } }; - Ok((Ident::invalid(), item_kind, Some(attrs))) + Ok((Ident::invalid(), item_kind)) } fn parse_item_list( &mut self, + attrs: &mut Vec, mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, - ) -> PResult<'a, (Vec, Vec)> { + ) -> PResult<'a, Vec> { self.expect(&token::OpenDelim(token::Brace))?; - let attrs = self.parse_inner_attributes()?; + attrs.append(&mut self.parse_inner_attributes()?); let mut items = Vec::new(); while !self.eat(&token::CloseDelim(token::Brace)) { @@ -572,7 +558,7 @@ impl<'a> Parser<'a> { } } } - Ok((items, attrs)) + Ok(items) } /// Recover on a doc comment before `}`. @@ -624,7 +610,12 @@ impl<'a> Parser<'a> { } /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait(&mut self, lo: Span, unsafety: Unsafe) -> PResult<'a, ItemInfo> { + fn parse_item_trait( + &mut self, + attrs: &mut Vec, + lo: Span, + unsafety: Unsafe, + ) -> PResult<'a, ItemInfo> { // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -662,12 +653,12 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::trait_alias, whole_span); - Ok((ident, ItemKind::TraitAlias(tps, bounds), None)) + Ok((ident, ItemKind::TraitAlias(tps, bounds))) } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_trait_item(at_end))?; - Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items), Some(attrs))) + let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?; + Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } @@ -854,7 +845,7 @@ impl<'a> Parser<'a> { (orig_name, None) }; self.expect_semi()?; - Ok((item_name, ItemKind::ExternCrate(orig_name), None)) + Ok((item_name, ItemKind::ExternCrate(orig_name))) } fn parse_crate_name_with_dashes(&mut self) -> PResult<'a, ast::Ident> { @@ -905,11 +896,11 @@ impl<'a> Parser<'a> { /// extern "C" {} /// extern {} /// ``` - fn parse_item_foreign_mod(&mut self) -> PResult<'a, ItemInfo> { + fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let (items, attrs) = self.parse_item_list(|p, at_end| p.parse_foreign_item(at_end))?; + let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?; let module = ast::ForeignMod { abi, items }; - Ok((Ident::invalid(), ItemKind::ForeignMod(module), Some(attrs))) + Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). @@ -1016,7 +1007,7 @@ impl<'a> Parser<'a> { Some(m) => ItemKind::Static(ty, m, e), None => ItemKind::Const(ty, e), }; - Ok((id, item, None)) + Ok((id, item)) } /// We were supposed to parse `:` but instead, we're already at `=`. @@ -1069,7 +1060,7 @@ impl<'a> Parser<'a> { let enum_definition = EnumDef { variants: variants.into_iter().filter_map(|v| v).collect() }; - Ok((id, ItemKind::Enum(enum_definition, generics), None)) + Ok((id, ItemKind::Enum(enum_definition, generics))) } fn parse_enum_variant(&mut self) -> PResult<'a, Option> { @@ -1163,7 +1154,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Struct(vdata, generics), None)) + Ok((class_name, ItemKind::Struct(vdata, generics))) } /// Parses `union Foo { ... }`. @@ -1187,7 +1178,7 @@ impl<'a> Parser<'a> { return Err(err); }; - Ok((class_name, ItemKind::Union(vdata, generics), None)) + Ok((class_name, ItemKind::Union(vdata, generics))) } pub(super) fn is_union_item(&self) -> bool { @@ -1369,7 +1360,7 @@ impl<'a> Parser<'a> { }; self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }), None)) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }))) } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? @@ -1391,7 +1382,7 @@ impl<'a> Parser<'a> { self.report_invalid_macro_expansion_item(); } - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }), None)) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } pub(super) fn eat_macro_def( @@ -1400,14 +1391,14 @@ impl<'a> Parser<'a> { vis: &Visibility, lo: Span, ) -> PResult<'a, Option>> { - let info = if self.eat_keyword(kw::Macro) { + let (ident, kind) = if self.eat_keyword(kw::Macro) { self.parse_item_decl_macro(lo)? } else if self.is_macro_rules_item() { self.parse_item_macro_rules(vis)? } else { return Ok(None); }; - Ok(Some(self.mk_item_with_info(attrs.to_vec(), lo, vis.clone(), info))) + Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis.clone(), attrs.to_vec()))) } fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 36a1e87956f..754923ae55e 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -67,7 +67,7 @@ impl<'a> Parser<'a> { (module, inner_attrs) }; attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module), None)) + Ok((id, ItemKind::Mod(module))) } /// Given a termination token, parses all of the items in a module. From fd64b3bcdfcc844b9b25318106917937f7b17b94 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 12:31:51 +0100 Subject: [PATCH 0118/1250] parser: make `eat_macro_def` redundant. --- src/librustc_parse/parser/item.rs | 35 ++++++++----------------------- src/librustc_parse/parser/stmt.rs | 10 +++------ 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 745d125b58c..27b3d501751 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -86,7 +86,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis, attrs))); + return Ok(Some(P(self.mk_item(lo, ident, kind, vis, attrs)))); } // FAILURE TO PARSE ITEM @@ -942,9 +942,7 @@ impl<'a> Parser<'a> { } self.unexpected()? }; - - let span = lo.to(self.prev_span); - Ok(P(ast::ForeignItem { ident, attrs, kind, id: DUMMY_NODE_ID, span, vis, tokens: None })) + Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) } /// Parses a static item from a foreign module. @@ -1364,7 +1362,7 @@ impl<'a> Parser<'a> { } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? - fn is_macro_rules_item(&mut self) -> bool { + pub(super) fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) @@ -1385,22 +1383,6 @@ impl<'a> Parser<'a> { Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } - pub(super) fn eat_macro_def( - &mut self, - attrs: &[Attribute], - vis: &Visibility, - lo: Span, - ) -> PResult<'a, Option>> { - let (ident, kind) = if self.eat_keyword(kw::Macro) { - self.parse_item_decl_macro(lo)? - } else if self.is_macro_rules_item() { - self.parse_item_macro_rules(vis)? - } else { - return Ok(None); - }; - Ok(Some(self.mk_item(lo.to(self.prev_span), ident, kind, vis.clone(), attrs.to_vec()))) - } - fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { match *vis { VisibilityKind::Inherited => {} @@ -1496,15 +1478,16 @@ impl<'a> Parser<'a> { Ok(true) } - fn mk_item( + fn mk_item( &self, - span: Span, + lo: Span, ident: Ident, - kind: ItemKind, + kind: K, vis: Visibility, attrs: Vec, - ) -> P { - P(Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None }) + ) -> Item { + let span = lo.to(self.prev_span); + Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None } } } diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index e97af0dc00c..b111b45e709 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -7,10 +7,10 @@ use crate::maybe_whole; use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; -use rustc_span::source_map::{respan, BytePos, Span}; +use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use syntax::ast; -use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle, VisibilityKind}; +use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; use syntax::ptr::P; use syntax::token::{self, TokenKind}; @@ -55,11 +55,6 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - let mac_vis = respan(lo, VisibilityKind::Inherited); - if let Some(macro_def) = self.eat_macro_def(&attrs, &mac_vis, lo)? { - return Ok(Some(self.mk_stmt(lo.to(self.prev_span), StmtKind::Item(macro_def)))); - } - // Starts like a simple path, being careful to avoid contextual keywords // such as a union items, item with `crate` visibility or auto trait items. // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts @@ -70,6 +65,7 @@ impl<'a> Parser<'a> { && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path. && !self.is_auto_trait_item() && !self.is_async_fn() + && !self.is_macro_rules_item() { let path = self.parse_path(PathStyle::Expr)?; From 15e07a6a11bc5ed86e33403eb4b7d718d1636855 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 13:37:23 +0100 Subject: [PATCH 0119/1250] parser: fuse `trait` parsing & layer with `is_path_start_item` --- src/librustc_parse/parser/item.rs | 46 +++++++++++++++++-------------- src/librustc_parse/parser/stmt.rs | 16 +---------- 2 files changed, 27 insertions(+), 35 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 27b3d501751..6de82d8f9be 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -152,11 +152,9 @@ impl<'a> Parser<'a> { } self.parse_item_const(None)? - } else if self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) - { - // UNSAFE TRAIT ITEM - let unsafety = self.parse_unsafety(); - self.parse_item_trait(attrs, lo, unsafety)? + } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { + // TRAIT ITEM + self.parse_item_trait(attrs, lo)? } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) @@ -176,11 +174,6 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? - } else if self.check_keyword(kw::Trait) - || (self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait])) - { - // TRAIT ITEM - self.parse_item_trait(attrs, lo, Unsafe::No)? } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? @@ -209,6 +202,15 @@ impl<'a> Parser<'a> { Ok(Some(info)) } + /// When parsing a statement, would the start of a path be an item? + pub(super) fn is_path_start_item(&mut self) -> bool { + self.is_crate_vis() // no: `crate::b`, yes: `crate $item` + || self.is_union_item() // no: `union::b`, yes: `union U { .. }` + || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` + || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` + || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` + } + /// Recover on encountering a struct or method definition where the user /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { @@ -338,7 +340,7 @@ impl<'a> Parser<'a> { Err(err) } - pub(super) fn is_async_fn(&self) -> bool { + fn is_async_fn(&self) -> bool { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } @@ -609,13 +611,17 @@ impl<'a> Parser<'a> { } } - /// Parses `auto? trait Foo { ... }` or `trait Foo = Bar;`. - fn parse_item_trait( - &mut self, - attrs: &mut Vec, - lo: Span, - unsafety: Unsafe, - ) -> PResult<'a, ItemInfo> { + /// Is this an `(unsafe auto? | auto) trait` item? + fn check_auto_or_unsafe_trait_item(&mut self) -> bool { + // auto trait + self.check_keyword(kw::Auto) && self.is_keyword_ahead(1, &[kw::Trait]) + // unsafe auto trait + || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Trait, kw::Auto]) + } + + /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`. + fn parse_item_trait(&mut self, attrs: &mut Vec, lo: Span) -> PResult<'a, ItemInfo> { + let unsafety = self.parse_unsafety(); // Parse optional `auto` prefix. let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No }; @@ -1179,7 +1185,7 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - pub(super) fn is_union_item(&self) -> bool { + fn is_union_item(&self) -> bool { self.token.is_keyword(kw::Union) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) } @@ -1362,7 +1368,7 @@ impl<'a> Parser<'a> { } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? - pub(super) fn is_macro_rules_item(&mut self) -> bool { + fn is_macro_rules_item(&mut self) -> bool { self.check_keyword(sym::macro_rules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index b111b45e709..439d0368d09 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -61,11 +61,7 @@ impl<'a> Parser<'a> { // like a path (1 token), but it fact not a path. if self.token.is_path_start() && !self.token.is_qpath_start() - && !self.is_union_item() // `union::b::c` - path, `union U { ... }` - not a path. - && !self.is_crate_vis() // `crate::b::c` - path, `crate struct S;` - not a path. - && !self.is_auto_trait_item() - && !self.is_async_fn() - && !self.is_macro_rules_item() + && !self.is_path_start_item() // Confirm we don't steal syntax from `parse_item_`. { let path = self.parse_path(PathStyle::Expr)?; @@ -295,16 +291,6 @@ impl<'a> Parser<'a> { } } - fn is_auto_trait_item(&self) -> bool { - // auto trait - (self.token.is_keyword(kw::Auto) && - self.is_keyword_ahead(1, &[kw::Trait])) - || // unsafe auto trait - (self.token.is_keyword(kw::Unsafe) && - self.is_keyword_ahead(1, &[kw::Auto]) && - self.is_keyword_ahead(2, &[kw::Trait])) - } - /// Parses a block. No inner attributes are allowed. pub fn parse_block(&mut self) -> PResult<'a, P> { maybe_whole!(self, NtBlock, |x| x); From 46d3ef58a8a184b5a76098b2ac0e66792a6def25 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 31 Jan 2020 14:23:12 +0100 Subject: [PATCH 0120/1250] parser: extract `recover_const_mut`. --- src/librustc_parse/parser/item.rs | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 6de82d8f9be..f13898d7024 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -138,19 +138,7 @@ impl<'a> Parser<'a> { self.parse_item_const(Some(m))? } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM - if self.eat_keyword(kw::Mut) { - let prev_span = self.prev_span; - self.struct_span_err(prev_span, "const globals cannot be mutable") - .span_label(prev_span, "cannot be mutable") - .span_suggestion( - const_span, - "you might want to declare a static instead", - "static".to_owned(), - Applicability::MaybeIncorrect, - ) - .emit(); - } - + self.recover_const_mut(const_span); self.parse_item_const(None)? } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM @@ -987,6 +975,22 @@ impl<'a> Parser<'a> { } } + /// Recover on `const mut` with `const` already eaten. + fn recover_const_mut(&mut self, const_span: Span) { + if self.eat_keyword(kw::Mut) { + let span = self.prev_span; + self.struct_span_err(span, "const globals cannot be mutable") + .span_label(span, "cannot be mutable") + .span_suggestion( + const_span, + "you might want to declare a static instead", + "static".to_owned(), + Applicability::MaybeIncorrect, + ) + .emit(); + } + } + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// From aaaf0ba072815d275820d8ac85ece6eeb9182321 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 1 Feb 2020 06:18:10 +0100 Subject: [PATCH 0121/1250] parser: misc small item related improvements & cleanups. --- src/librustc_parse/parser/item.rs | 258 ++++++++---------- src/librustc_parse/parser/mod.rs | 5 + src/librustc_parse/parser/stmt.rs | 18 +- src/test/ui/issues/issue-58856-2.stderr | 4 +- src/test/ui/issues/issue-60075.stderr | 2 +- src/test/ui/macros/issue-54441.rs | 3 +- src/test/ui/macros/issue-54441.stderr | 16 +- src/test/ui/parser/attr-before-eof.stderr | 4 +- .../ui/parser/attr-dangling-in-mod.stderr | 4 +- .../ui/parser/attrs-after-extern-mod.stderr | 4 +- src/test/ui/parser/default.rs | 3 +- src/test/ui/parser/default.stderr | 6 +- src/test/ui/parser/doc-before-attr.stderr | 6 +- src/test/ui/parser/duplicate-visibility.rs | 3 +- .../ui/parser/duplicate-visibility.stderr | 6 +- src/test/ui/parser/issue-19398.rs | 3 +- src/test/ui/parser/issue-19398.stderr | 13 +- src/test/ui/parser/issue-20711-2.rs | 3 +- src/test/ui/parser/issue-20711-2.stderr | 8 +- src/test/ui/parser/issue-20711.rs | 3 +- src/test/ui/parser/issue-20711.stderr | 8 +- src/test/ui/parser/issue-32446.stderr | 4 +- src/test/ui/parser/issue-41155.stderr | 4 +- ...-58094-missing-right-square-bracket.stderr | 4 +- src/test/ui/parser/macro/pub-item-macro.rs | 11 +- .../ui/parser/macro/pub-item-macro.stderr | 12 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../missing-close-brace-in-impl-trait.rs | 6 +- .../missing-close-brace-in-impl-trait.stderr | 25 +- .../missing-close-brace-in-trait.rs | 2 +- .../missing-close-brace-in-trait.stderr | 6 +- src/test/ui/parser/pub-method-macro.rs | 3 +- src/test/ui/parser/pub-method-macro.stderr | 2 +- .../ui/parser/removed-syntax-static-fn.rs | 2 +- .../ui/parser/removed-syntax-static-fn.stderr | 13 +- .../ui/pub/pub-restricted-error-fn.stderr | 4 +- 36 files changed, 233 insertions(+), 249 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index f13898d7024..af9700ee81e 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -8,8 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::BytePos; -use syntax::ast::{self, AttrKind, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; +use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; @@ -90,18 +89,18 @@ impl<'a> Parser<'a> { } // FAILURE TO PARSE ITEM - match vis.node { - VisibilityKind::Inherited => {} - _ => { - self.struct_span_err(vis.span, "unmatched visibility `pub`") - .span_label(vis.span, "the unmatched visibility") - .help("you likely meant to define an item, e.g., `pub fn foo() {}`") - .emit(); - } + if let VisibilityKind::Inherited = vis.node { + } else { + let vs = pprust::vis_to_string(&vis); + let vs = vs.trim_end(); + self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) + .span_label(vis.span, "the unmatched visibility") + .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) + .emit(); } - if !attributes_allowed && !attrs.is_empty() { - self.expected_item_err(&attrs)?; + if !attributes_allowed { + self.recover_attrs_no_item(&attrs)?; } Ok(None) } @@ -165,7 +164,7 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::Struct) { // STRUCT ITEM self.parse_item_struct()? - } else if self.is_union_item() { + } else if self.is_kw_followed_by_ident(kw::Union) { // UNION ITEM self.bump(); // `union` self.parse_item_union()? @@ -175,15 +174,12 @@ impl<'a> Parser<'a> { } else if self.is_macro_rules_item() { // MACRO_RULES ITEM self.parse_item_macro_rules(vis)? - } else if vis.node.is_pub() - && self.check_ident() - && self.look_ahead(1, |t| *t != token::Not) - { + } else if vis.node.is_pub() && self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; return Ok(None); } else if macros_allowed && self.token.is_path_start() { // MACRO INVOCATION ITEM - self.parse_item_macro(vis)? + (Ident::invalid(), ItemKind::Mac(self.parse_item_macro(vis)?)) } else { return Ok(None); }; @@ -193,12 +189,17 @@ impl<'a> Parser<'a> { /// When parsing a statement, would the start of a path be an item? pub(super) fn is_path_start_item(&mut self) -> bool { self.is_crate_vis() // no: `crate::b`, yes: `crate $item` - || self.is_union_item() // no: `union::b`, yes: `union U { .. }` + || self.is_kw_followed_by_ident(kw::Union) // no: `union::b`, yes: `union U { .. }` || self.check_auto_or_unsafe_trait_item() // no: `auto::b`, yes: `auto trait X { .. }` || self.is_async_fn() // no(2015): `async::b`, yes: `async fn` || self.is_macro_rules_item() // no: `macro_rules::b`, yes: `macro_rules! mac` } + /// Are we sure this could not possibly be a macro invocation? + fn isnt_macro_invocation(&mut self) -> bool { + self.check_ident() && self.look_ahead(1, |t| *t != token::Not && *t != token::ModSep) + } + /// Recover on encountering a struct or method definition where the user /// forgot to add the `struct` or `fn` keyword after writing `pub`: `pub S {}`. fn recover_missing_kw_before_item(&mut self) -> PResult<'a, ()> { @@ -297,33 +298,33 @@ impl<'a> Parser<'a> { } /// Parses an item macro, e.g., `item!();`. - fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); - - // Item macro - let path = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; - let args = self.parse_mac_args()?; - if args.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } - - let mac = Mac { path, args, prior_type_ascription: self.last_type_ascription }; - Ok((Ident::invalid(), ItemKind::Mac(mac))) - } - - /// Emits an expected-item-after-attributes error. - fn expected_item_err(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { - let message = match attrs.last() { - Some(&Attribute { kind: AttrKind::DocComment(_), .. }) => { - "expected item after doc comment" - } - _ => "expected item after attributes", + fn parse_item_macro(&mut self, vis: &Visibility) -> PResult<'a, Mac> { + let path = self.parse_path(PathStyle::Mod)?; // `foo::bar` + self.expect(&token::Not)?; // `!` + let args = self.parse_mac_args()?; // `( .. )` or `[ .. ]` (followed by `;`), or `{ .. }`. + self.eat_semi_for_macro_if_needed(&args); + self.complain_if_pub_macro(vis, false); + Ok(Mac { path, args, prior_type_ascription: self.last_type_ascription }) + } + + /// Recover if we parsed attributes and expected an item but there was none. + fn recover_attrs_no_item(&mut self, attrs: &[Attribute]) -> PResult<'a, ()> { + let (start, end) = match attrs { + [] => return Ok(()), + [x0] => (x0, x0), + [x0, .., xn] => (x0, xn), }; - - let mut err = self.struct_span_err(self.prev_span, message); - if attrs.last().unwrap().is_doc_comment() { - err.span_label(self.prev_span, "this doc comment doesn't document anything"); + let msg = if end.is_doc_comment() { + "expected item after doc comment" + } else { + "expected item after attributes" + }; + let mut err = self.struct_span_err(end.span, msg); + if end.is_doc_comment() { + err.span_label(end.span, "this doc comment doesn't document anything"); + } + if let [.., penultimate, _] = attrs { + err.span_label(start.span.to(penultimate.span), "other attributes here"); } Err(err) } @@ -332,38 +333,19 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl` or `extern` block. + /// Parses a macro invocation inside a `trait`, `impl`, or `extern` block. fn parse_assoc_macro_invoc( &mut self, item_kind: &str, - vis: Option<&Visibility>, + vis: &Visibility, at_end: &mut bool, ) -> PResult<'a, Option> { - if self.token.is_path_start() && !(self.is_async_fn() && self.token.span.rust_2015()) { - let prev_span = self.prev_span; - let path = self.parse_path(PathStyle::Mod)?; - - if path.segments.len() == 1 { - if !self.eat(&token::Not) { - return Err(self.missing_assoc_item_kind_err(item_kind, prev_span)); - } - } else { - self.expect(&token::Not)?; - } - - if let Some(vis) = vis { - self.complain_if_pub_macro(&vis.node, prev_span); - } - + if self.isnt_macro_invocation() { + Err(self.missing_assoc_item_kind_err(item_kind, self.prev_span)) + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(vis)?; *at_end = true; - - // eat a matched-delimiter token tree: - let args = self.parse_mac_args()?; - if args.need_semicolon() { - self.expect_semi()?; - } - - Ok(Some(Mac { path, args, prior_type_ascription: self.last_type_ascription })) + Ok(Some(mac)) } else { Ok(None) } @@ -389,7 +371,7 @@ impl<'a> Parser<'a> { // | ^ missing `fn`, `type`, or `const` // pub path( // ^^ `sp` below will point to this - let sp = prev_span.between(self.prev_span); + let sp = prev_span.between(self.token.span); let mut err = self .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); err.span_label(sp, expected_kinds); @@ -706,10 +688,13 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; (ident, AssocItemKind::Fn(sig, body), generics) - } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", Some(&vis), at_end)? { + } else if self.check_keyword(kw::Const) { + self.parse_assoc_const()? + } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", &vis, at_end)? { (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { - self.parse_assoc_const()? + self.recover_attrs_no_item(&attrs)?; + self.unexpected()? }; let span = lo.to(self.prev_span); @@ -813,7 +798,7 @@ impl<'a> Parser<'a> { fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token.kind { - token::Ident(name, false) if name == kw::Underscore => { + token::Ident(name @ kw::Underscore, false) => { let span = self.token.span; self.bump(); Ok(Ident::new(name, span)) @@ -928,12 +913,10 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", Some(&vis), at_end)? { + } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", &vis, at_end)? { (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { - if !attrs.is_empty() { - self.expected_item_err(&attrs)?; - } + self.recover_attrs_no_item(&attrs)?; self.unexpected()? }; Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) @@ -1189,11 +1172,6 @@ impl<'a> Parser<'a> { Ok((class_name, ItemKind::Union(vdata, generics))) } - fn is_union_item(&self) -> bool { - self.token.is_keyword(kw::Union) - && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn parse_record_struct_body( &mut self, ) -> PResult<'a, (Vec, /* recovered */ bool)> { @@ -1343,24 +1321,26 @@ impl<'a> Parser<'a> { /// Parses a declarative macro 2.0 definition. /// The `macro` keyword has already been parsed. + /// ``` + /// MacBody = "{" TOKEN_STREAM "}" ; + /// MacParams = "(" TOKEN_STREAM ")" ; + /// DeclMac = "macro" Ident MacParams? MacBody ; + /// ``` fn parse_item_decl_macro(&mut self, lo: Span) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_mac_args()? + self.parse_mac_args()? // `MacBody` } else if self.check(&token::OpenDelim(token::Paren)) { - let params = self.parse_token_tree(); + let params = self.parse_token_tree(); // `MacParams` let pspan = params.span(); - let body = if self.check(&token::OpenDelim(token::Brace)) { - self.parse_token_tree() - } else { + if !self.check(&token::OpenDelim(token::Brace)) { return self.unexpected(); - }; + } + let body = self.parse_token_tree(); // `MacBody` + // Convert `MacParams MacBody` into `{ MacParams => MacBody }`. let bspan = body.span(); - let tokens = TokenStream::new(vec![ - params.into(), - TokenTree::token(token::FatArrow, pspan.between(bspan)).into(), - body.into(), - ]); + let arrow = TokenTree::token(token::FatArrow, pspan.between(bspan)); // `=>` + let tokens = TokenStream::new(vec![params.into(), arrow.into(), body.into()]); let dspan = DelimSpan::from_pair(pspan.shrink_to_lo(), bspan.shrink_to_hi()); P(MacArgs::Delimited(dspan, MacDelimiter::Brace, tokens)) } else { @@ -1380,65 +1360,68 @@ impl<'a> Parser<'a> { /// Parses a legacy `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.complain_if_pub_macro(&vis.node, vis.span); self.expect_keyword(sym::macro_rules)?; // `macro_rules` self.expect(&token::Not)?; // `!` let ident = self.parse_ident()?; let body = self.parse_mac_args()?; - if body.need_semicolon() && !self.eat(&token::Semi) { - self.report_invalid_macro_expansion_item(); - } + self.eat_semi_for_macro_if_needed(&body); + self.complain_if_pub_macro(vis, true); Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) } - fn complain_if_pub_macro(&self, vis: &VisibilityKind, sp: Span) { - match *vis { - VisibilityKind::Inherited => {} - _ => { - let mut err = if self.token.is_keyword(sym::macro_rules) { - let mut err = - self.struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); - err.span_suggestion( - sp, - "try exporting the macro", - "#[macro_export]".to_owned(), - Applicability::MaybeIncorrect, // speculative - ); - err - } else { - let mut err = - self.struct_span_err(sp, "can't qualify macro invocation with `pub`"); - err.help("try adjusting the macro to put `pub` inside the invocation"); - err - }; - err.emit(); - } + /// Item macro invocations or `macro_rules!` definitions need inherited visibility. + /// If that's not the case, emit an error. + fn complain_if_pub_macro(&self, vis: &Visibility, macro_rules: bool) { + if let VisibilityKind::Inherited = vis.node { + return; + } + + let vstr = pprust::vis_to_string(vis); + let vstr = vstr.trim_end(); + if macro_rules { + let msg = format!("can't qualify macro_rules invocation with `{}`", vstr); + self.struct_span_err(vis.span, &msg) + .span_suggestion( + vis.span, + "try exporting the macro", + "#[macro_export]".to_owned(), + Applicability::MaybeIncorrect, // speculative + ) + .emit(); + } else { + self.struct_span_err(vis.span, "can't qualify macro invocation with `pub`") + .span_suggestion( + vis.span, + "remove the visibility", + String::new(), + Applicability::MachineApplicable, + ) + .help(&format!("try adjusting the macro to put `{}` inside the invocation", vstr)) + .emit(); } } - fn report_invalid_macro_expansion_item(&self) { - let has_close_delim = self - .sess - .source_map() - .span_to_snippet(self.prev_span) - .map(|s| s.ends_with(")") || s.ends_with("]")) - .unwrap_or(false); + fn eat_semi_for_macro_if_needed(&mut self, args: &MacArgs) { + if args.need_semicolon() && !self.eat(&token::Semi) { + self.report_invalid_macro_expansion_item(args); + } + } + fn report_invalid_macro_expansion_item(&self, args: &MacArgs) { let mut err = self.struct_span_err( self.prev_span, "macros that expand to items must be delimited with braces or followed by a semicolon", ); - - // To avoid ICE, we shouldn't emit actual suggestions when it hasn't closing delims - if has_close_delim { + if self.unclosed_delims.is_empty() { + let DelimSpan { open, close } = match args { + MacArgs::Empty | MacArgs::Eq(..) => unreachable!(), + MacArgs::Delimited(dspan, ..) => *dspan, + }; err.multipart_suggestion( "change the delimiters to curly braces", - vec![ - (self.prev_span.with_hi(self.prev_span.lo() + BytePos(1)), '{'.to_string()), - (self.prev_span.with_lo(self.prev_span.hi() - BytePos(1)), '}'.to_string()), - ], + vec![(open, "{".to_string()), (close, '}'.to_string())], Applicability::MaybeIncorrect, ); } else { @@ -1449,14 +1432,13 @@ impl<'a> Parser<'a> { Applicability::HasPlaceholders, ); } - err.span_suggestion( self.prev_span.shrink_to_hi(), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, - ) - .emit(); + ); + err.emit(); } /// Checks if current token is one of tokens which cannot be nested like `kw::Enum`. In case diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 4716d722778..79944dc35e5 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -572,6 +572,11 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw) { self.unexpected() } else { Ok(()) } } + /// Is the given keyword `kw` followed by a non-reserved identifier? + fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { + self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) + } + fn check_or_expected(&mut self, ok: bool, typ: TokenType) -> bool { if ok { true diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 439d0368d09..742fc4802fd 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -8,7 +8,7 @@ use crate::DirectoryOwnership; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym}; use syntax::ast; use syntax::ast::{AttrStyle, AttrVec, Attribute, Mac, MacStmtStyle}; use syntax::ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; @@ -55,13 +55,11 @@ impl<'a> Parser<'a> { return self.recover_stmt_local(lo, attrs.into(), msg, "let"); } - // Starts like a simple path, being careful to avoid contextual keywords - // such as a union items, item with `crate` visibility or auto trait items. - // Our goal here is to parse an arbitrary path `a::b::c` but not something that starts - // like a path (1 token), but it fact not a path. - if self.token.is_path_start() - && !self.token.is_qpath_start() - && !self.is_path_start_item() // Confirm we don't steal syntax from `parse_item_`. + // Starts like a simple path, being careful to avoid contextual keywords, + // e.g., `union`, items with `crate` visibility, or `auto trait` items. + // We aim to parse an arbitrary path `a::b` but not something that starts like a path + // (1 token), but it fact not a path. Also, we avoid stealing syntax from `parse_item_`. + if self.token.is_path_start() && !self.token.is_qpath_start() && !self.is_path_start_item() { let path = self.parse_path(PathStyle::Expr)?; @@ -191,10 +189,6 @@ impl<'a> Parser<'a> { } } - fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { - self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) - } - fn recover_stmt_local( &mut self, lo: Span, diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 01d70d861e2..6221b90b31d 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -7,11 +7,11 @@ LL | fn how_are_you(&self -> Empty { | | help: `)` may belong here | unclosed delimiter -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `)` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `)` --> $DIR/issue-58856-2.rs:11:1 | LL | } - | - expected one of 10 possible tokens + | - expected one of 11 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index 60eb99b46b7..b2beb73503b 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index afdf76b7b58..a70163df1cb 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,6 +1,7 @@ macro_rules! m { + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration () => { - let //~ ERROR expected + let }; } diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index c94355f4716..761e7aec723 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,13 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `extern`, `fn`, `pub`, `static`, `type`, or `unsafe`, found keyword `let` - --> $DIR/issue-54441.rs:3:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/issue-54441.rs:1:1 | -LL | let - | ^^^ expected one of 9 possible tokens -... -LL | m!(); - | ----- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) +LL | / macro_rules! m { +LL | | +LL | | () => { +LL | | let + | |________^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/attr-before-eof.stderr b/src/test/ui/parser/attr-before-eof.stderr index eb5daf84981..a2acb94372b 100644 --- a/src/test/ui/parser/attr-before-eof.stderr +++ b/src/test/ui/parser/attr-before-eof.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-before-eof.rs:3:16 + --> $DIR/attr-before-eof.rs:3:1 | LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attr-dangling-in-mod.stderr b/src/test/ui/parser/attr-dangling-in-mod.stderr index d896b61ce49..1c892eac08f 100644 --- a/src/test/ui/parser/attr-dangling-in-mod.stderr +++ b/src/test/ui/parser/attr-dangling-in-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attr-dangling-in-mod.rs:6:14 + --> $DIR/attr-dangling-in-mod.rs:6:1 | LL | #[foo = "bar"] - | ^ + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index a02e738a2c3..6060f3afe1e 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,8 +1,8 @@ error: expected item after attributes - --> $DIR/attrs-after-extern-mod.rs:6:19 + --> $DIR/attrs-after-extern-mod.rs:6:5 | LL | #[cfg(stage37)] - | ^ + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 17cd06864bf..65ecb1ebbe9 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -19,7 +19,8 @@ impl Foo for u16 { } impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` - default pub fn foo() -> T { T::default() } //~ ERROR expected one of + default pub fn foo() -> T { T::default() } + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index dde36cf8dde..ede9e471518 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/default.rs:22:13 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/default.rs:22:12 | LL | default pub fn foo() -> T { T::default() } - | ^^^ expected one of `async`, `const`, `extern`, `fn`, `type`, or `unsafe` + | ^ missing `fn`, `type`, or `const` error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 diff --git a/src/test/ui/parser/doc-before-attr.stderr b/src/test/ui/parser/doc-before-attr.stderr index 0fae44ce5c8..14fd01af2f9 100644 --- a/src/test/ui/parser/doc-before-attr.stderr +++ b/src/test/ui/parser/doc-before-attr.stderr @@ -1,8 +1,10 @@ error: expected item after attributes - --> $DIR/doc-before-attr.rs:4:16 + --> $DIR/doc-before-attr.rs:4:1 | +LL | /// hi + | ------ other attributes here LL | #[derive(Debug)] - | ^ + | ^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index edbf508ecdb..1d271fa64b0 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -1,7 +1,6 @@ -// error-pattern: expected one of `(`, `async`, `const`, `extern`, `fn` - fn main() {} extern { pub pub fn foo(); + //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 92cf3487969..36a3a1ed5a0 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `extern`, `fn`, `static`, `type`, or `unsafe`, found keyword `pub` - --> $DIR/duplicate-visibility.rs:6:9 +error: missing `fn`, `type`, or `static` for extern-item declaration + --> $DIR/duplicate-visibility.rs:4:8 | LL | pub pub fn foo(); - | ^^^ expected one of 8 possible tokens + | ^ missing `fn`, `type`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 2158a2fd6c1..982a6be23ac 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,6 @@ trait T { - extern "Rust" unsafe fn foo(); //~ ERROR expected one of `async`, `const` + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + extern "Rust" unsafe fn foo(); } fn main() {} diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 201a6b2d66a..2bd6ac3a4b3 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `extern` - --> $DIR/issue-19398.rs:2:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/issue-19398.rs:1:10 | -LL | trait T { - | - expected one of 10 possible tokens -LL | extern "Rust" unsafe fn foo(); - | ^^^^^^ unexpected token +LL | trait T { + | __________^ +LL | | +LL | | extern "Rust" unsafe fn foo(); + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711-2.rs b/src/test/ui/parser/issue-20711-2.rs index 0063a334182..168c7e76162 100644 --- a/src/test/ui/parser/issue-20711-2.rs +++ b/src/test/ui/parser/issue-20711-2.rs @@ -4,6 +4,7 @@ impl Foo { fn foo() {} #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr index ee484890fad..10ef31584de 100644 --- a/src/test/ui/parser/issue-20711-2.stderr +++ b/src/test/ui/parser/issue-20711-2.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711-2.rs:7:1 +error: expected item after attributes + --> $DIR/issue-20711-2.rs:6:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711.rs b/src/test/ui/parser/issue-20711.rs index dc216167b8a..020bb79d6e7 100644 --- a/src/test/ui/parser/issue-20711.rs +++ b/src/test/ui/parser/issue-20711.rs @@ -2,6 +2,7 @@ struct Foo; impl Foo { #[stable(feature = "rust1", since = "1.0.0")] -} //~ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or + //~^ ERROR expected item after attributes +} fn main() {} diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr index 152c9f1c689..66768de5694 100644 --- a/src/test/ui/parser/issue-20711.stderr +++ b/src/test/ui/parser/issue-20711.stderr @@ -1,10 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}` - --> $DIR/issue-20711.rs:5:1 +error: expected item after attributes + --> $DIR/issue-20711.rs:4:5 | LL | #[stable(feature = "rust1", since = "1.0.0")] - | - expected one of 9 possible tokens -LL | } - | ^ unexpected token + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 1a97f54160b..25c1efe35ae 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 10 possible tokens + | ^^^ expected one of 11 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index 0e191eb7e0a..327bc65818f 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found `}` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, `unsafe`, or identifier, found `}` --> $DIR/issue-41155.rs:5:1 | LL | pub - | - expected one of 8 possible tokens + | - expected one of 9 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr index 00f6652b311..8a44ee761ed 100644 --- a/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr +++ b/src/test/ui/parser/issue-58094-missing-right-square-bracket.stderr @@ -7,10 +7,10 @@ LL | #[Ѕ | unclosed delimiter error: expected item after attributes - --> $DIR/issue-58094-missing-right-square-bracket.rs:4:4 + --> $DIR/issue-58094-missing-right-square-bracket.rs:4:1 | LL | #[Ѕ - | ^ + | ^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/macro/pub-item-macro.rs b/src/test/ui/parser/macro/pub-item-macro.rs index bae90227c62..f5f8a01e6a4 100644 --- a/src/test/ui/parser/macro/pub-item-macro.rs +++ b/src/test/ui/parser/macro/pub-item-macro.rs @@ -1,12 +1,15 @@ // Issue #14660 -macro_rules! priv_x { () => { - static x: u32 = 0; -}} +macro_rules! priv_x { + () => { + static x: u32 = 0; + }; +} macro_rules! pub_x { () => { pub priv_x!(); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation }} mod foo { diff --git a/src/test/ui/parser/macro/pub-item-macro.stderr b/src/test/ui/parser/macro/pub-item-macro.stderr index 49644cf6a0e..4ff96532e03 100644 --- a/src/test/ui/parser/macro/pub-item-macro.stderr +++ b/src/test/ui/parser/macro/pub-item-macro.stderr @@ -1,8 +1,8 @@ error: can't qualify macro invocation with `pub` - --> $DIR/pub-item-macro.rs:8:5 + --> $DIR/pub-item-macro.rs:10:5 | LL | pub priv_x!(); - | ^^^ + | ^^^ help: remove the visibility ... LL | pub_x!(); | --------- in this macro invocation @@ -11,16 +11,16 @@ LL | pub_x!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0603]: static `x` is private - --> $DIR/pub-item-macro.rs:17:23 + --> $DIR/pub-item-macro.rs:20:23 | LL | let y: u32 = foo::x; | ^ this static is private | note: the static `x` is defined here - --> $DIR/pub-item-macro.rs:4:5 + --> $DIR/pub-item-macro.rs:5:9 | -LL | static x: u32 = 0; - | ^^^^^^^^^^^^^^^^^^ +LL | static x: u32 = 0; + | ^^^^^^^^^^^^^^^^^^ ... LL | pub_x!(); | --------- in this macro invocation diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 5a89b5b936f..9d05e85bcc0 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or identifier, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 9 possible tokens + | ^^ expected one of 10 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index 9f02a7a997b..592215030f5 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -1,12 +1,14 @@ +fn main() {} + impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} +//~^ ERROR missing `fn`, `type`, or `const` -trait T { //~ ERROR expected one of +trait T { fn foo(&self); } pub(crate) struct Bar(); -fn main() {} //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index a23cfeac58f..1ec54525105 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing-close-brace-in-impl-trait.rs:12:52 + --> $DIR/missing-close-brace-in-impl-trait.rs:14:52 | LL | impl T for () { | - unclosed delimiter @@ -7,23 +7,18 @@ LL | impl T for () { LL | | ^ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `trait` - --> $DIR/missing-close-brace-in-impl-trait.rs:5:1 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 | -LL | impl T for () { - | - unclosed delimiter -LL | -LL | fn foo(&self) {} - | - - | | - | expected one of 10 possible tokens - | help: `}` may belong here -LL | -LL | trait T { - | ^^^^^ unexpected token +LL | fn foo(&self) {} + | _________________^ +LL | | +LL | | +LL | | trait T { + | |_ missing `fn`, `type`, or `const` error[E0405]: cannot find trait `T` in this scope - --> $DIR/missing-close-brace-in-impl-trait.rs:1:6 + --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 | LL | impl T for () { | ^ not found in this scope diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index 5ec5d45bbe7..077e3347194 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -3,7 +3,7 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR expected one of +//~^ ERROR missing `fn`, `type`, or `const` impl T for Bar { fn foo(&self) {} diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 21364012782..1bb153c461d 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: expected one of `async`, `const`, `default`, `extern`, `fn`, `type`, or `unsafe`, found keyword `struct` - --> $DIR/missing-close-brace-in-trait.rs:5:12 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/missing-close-brace-in-trait.rs:5:11 | LL | pub(crate) struct Bar(); - | ^^^^^^ expected one of 7 possible tokens + | ^ missing `fn`, `type`, or `const` error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 diff --git a/src/test/ui/parser/pub-method-macro.rs b/src/test/ui/parser/pub-method-macro.rs index f04af1a0d65..0183bdcf622 100644 --- a/src/test/ui/parser/pub-method-macro.rs +++ b/src/test/ui/parser/pub-method-macro.rs @@ -15,7 +15,8 @@ mod bleh { impl S { pub defn!(f); //~ ERROR can't qualify macro invocation with `pub` - //~^ HELP try adjusting the macro to put `pub` inside the invocation + //~^ HELP remove the visibility + //~| HELP try adjusting the macro to put `pub` inside the invocation } } diff --git a/src/test/ui/parser/pub-method-macro.stderr b/src/test/ui/parser/pub-method-macro.stderr index 7b0fe493461..7c7a909267a 100644 --- a/src/test/ui/parser/pub-method-macro.stderr +++ b/src/test/ui/parser/pub-method-macro.stderr @@ -2,7 +2,7 @@ error: can't qualify macro invocation with `pub` --> $DIR/pub-method-macro.rs:17:9 | LL | pub defn!(f); - | ^^^ + | ^^^ help: remove the visibility | = help: try adjusting the macro to put `pub` inside the invocation diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs index 0caddb9855d..9e12222f3fd 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.rs +++ b/src/test/ui/parser/removed-syntax-static-fn.rs @@ -1,8 +1,8 @@ struct S; impl S { + //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration static fn f() {} - //~^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, } fn main() {} diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index dfadefee23c..5edf88026fb 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -1,10 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found keyword `static` - --> $DIR/removed-syntax-static-fn.rs:4:5 +error: missing `fn`, `type`, or `const` for associated-item declaration + --> $DIR/removed-syntax-static-fn.rs:3:9 | -LL | impl S { - | - expected one of 10 possible tokens -LL | static fn f() {} - | ^^^^^^ unexpected token +LL | impl S { + | _________^ +LL | | +LL | | static fn f() {} + | |____^ missing `fn`, `type`, or `const` error: aborting due to previous error diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index c5acb92dcd4..c0168b02da6 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,10 +1,10 @@ -error: unmatched visibility `pub` +error: unmatched visibility `pub(crate)` --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} | ^^^^^^^^^^ the unmatched visibility | - = help: you likely meant to define an item, e.g., `pub fn foo() {}` + = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` error: expected item, found `(` --> $DIR/pub-restricted-error-fn.rs:1:12 From ad72c3abb9a7f9746d6ccc381e69ba88fb15b5cd Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 1 Feb 2020 10:26:11 +0100 Subject: [PATCH 0122/1250] parser: inline parse_assoc_macro_invoc --- src/librustc_parse/parser/item.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index af9700ee81e..500aaaf43b9 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -333,24 +333,6 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Parses a macro invocation inside a `trait`, `impl`, or `extern` block. - fn parse_assoc_macro_invoc( - &mut self, - item_kind: &str, - vis: &Visibility, - at_end: &mut bool, - ) -> PResult<'a, Option> { - if self.isnt_macro_invocation() { - Err(self.missing_assoc_item_kind_err(item_kind, self.prev_span)) - } else if self.token.is_path_start() { - let mac = self.parse_item_macro(vis)?; - *at_end = true; - Ok(Some(mac)) - } else { - Ok(None) - } - } - fn missing_assoc_item_kind_err( &self, item_type: &str, @@ -690,7 +672,11 @@ impl<'a> Parser<'a> { (ident, AssocItemKind::Fn(sig, body), generics) } else if self.check_keyword(kw::Const) { self.parse_assoc_const()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("associated", &vis, at_end)? { + } else if self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) } else { self.recover_attrs_no_item(&attrs)?; @@ -913,7 +899,11 @@ impl<'a> Parser<'a> { ) .emit(); self.parse_item_foreign_static()? - } else if let Some(mac) = self.parse_assoc_macro_invoc("extern", &vis, at_end)? { + } else if self.isnt_macro_invocation() { + return Err(self.missing_assoc_item_kind_err("extern", self.prev_span)); + } else if self.token.is_path_start() { + let mac = self.parse_item_macro(&vis)?; + *at_end = true; (Ident::invalid(), ForeignItemKind::Macro(mac)) } else { self.recover_attrs_no_item(&attrs)?; From 4706c38e17349793b2713947f81cfa1fd1f75ba3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 12 Feb 2020 19:46:05 +0100 Subject: [PATCH 0123/1250] Use HirId in TraitCandidate. --- src/librustc/ich/impls_hir.rs | 1 - src/librustc/ty/context.rs | 1 + src/librustc/ty/mod.rs | 20 +++++++++++++++++++- src/librustc_hir/hir.rs | 4 ++-- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/lib.rs | 4 ++-- src/librustc_typeck/check/method/probe.rs | 15 ++++++--------- 7 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 1a763e43d55..eadc9ddeee6 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -270,7 +270,6 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { let import_keys = import_ids .iter() - .map(|node_id| hcx.node_to_hir_id(*node_id)) .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id)) .collect(); (hcx.def_path_hash(*def_id), import_keys) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2adf7086417..1a071905523 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1161,6 +1161,7 @@ impl<'tcx> TyCtxt<'tcx> { for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); + let v = v.into_iter().map(|tc| tc.node_to_hir_id(&hir.definitions())).collect(); map.insert(hir_id.local_id, StableVec::new(v)); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2bda99e6d20..a561d48844b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::{Constness, GlobMap, Node, TraitMap}; +use rustc_hir::{Constness, GlobMap, Node}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; @@ -46,6 +46,7 @@ use rustc_target::abi::Align; use syntax::ast::{self, Ident, Name}; use syntax::node_id::{NodeId, NodeMap, NodeSet}; +use smallvec::SmallVec; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -122,6 +123,23 @@ mod sty; // Data types +#[derive(Clone, Debug)] +pub struct TraitCandidate { + pub def_id: DefId, + pub import_ids: SmallVec<[NodeId; 1]>, +} + +impl TraitCandidate { + fn node_to_hir_id(self, definitions: &hir_map::Definitions) -> hir::TraitCandidate { + let TraitCandidate { def_id, import_ids } = self; + let import_ids = + import_ids.into_iter().map(|node_id| definitions.node_to_hir_id(node_id)).collect(); + hir::TraitCandidate { def_id, import_ids } + } +} + +pub type TraitMap = NodeMap>; + pub struct ResolverOutputs { pub definitions: hir_map::Definitions, pub cstore: Box, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index c2ddaf7df31..0667bd3f4a2 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -16,7 +16,7 @@ use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; -use syntax::ast::{self, AsmDialect, CrateSugar, Ident, Name, NodeId}; +use syntax::ast::{self, AsmDialect, CrateSugar, Ident, Name}; use syntax::ast::{AttrVec, Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, UintTy}; pub use syntax::ast::{BorrowKind, ImplPolarity, IsAuto}; pub use syntax::ast::{CaptureBy, Movability, Mutability}; @@ -2610,7 +2610,7 @@ pub type CaptureModeMap = NodeMap; #[derive(Clone, Debug)] pub struct TraitCandidate { pub def_id: DefId, - pub import_ids: SmallVec<[NodeId; 1]>, + pub import_ids: SmallVec<[HirId; 1]>, } // Trait method resolution diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 58ff7f44789..ea865a5590a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,13 +11,13 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; +use rustc::ty::TraitCandidate; use rustc::{bug, lint, span_bug}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; -use rustc_hir::TraitCandidate; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2e63c3e1706..cfe100dc588 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -22,7 +22,7 @@ use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; -use rustc::ty::{self, DefIdTree, ResolverOutputs}; +use rustc::ty::{self, DefIdTree, ResolverOutputs, TraitMap}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; @@ -32,8 +32,8 @@ use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::GlobMap; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; -use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 760b6487045..8f0fbc2d60c 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -902,13 +902,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { for trait_candidate in applicable_traits.iter() { let trait_did = trait_candidate.def_id; if duplicates.insert(trait_did) { - let import_ids = trait_candidate - .import_ids - .iter() - .map(|node_id| self.fcx.tcx.hir().node_to_hir_id(*node_id)) - .collect(); - let result = - self.assemble_extension_candidates_for_trait(import_ids, trait_did); + let result = self.assemble_extension_candidates_for_trait( + &trait_candidate.import_ids, + trait_did, + ); result?; } } @@ -920,7 +917,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let mut duplicates = FxHashSet::default(); for trait_info in suggest::all_traits(self.tcx) { if duplicates.insert(trait_info.def_id) { - self.assemble_extension_candidates_for_trait(smallvec![], trait_info.def_id)?; + self.assemble_extension_candidates_for_trait(&smallvec![], trait_info.def_id)?; } } Ok(()) @@ -959,7 +956,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { fn assemble_extension_candidates_for_trait( &mut self, - import_ids: SmallVec<[hir::HirId; 1]>, + import_ids: &SmallVec<[hir::HirId; 1]>, trait_def_id: DefId, ) -> Result<(), MethodError<'tcx>> { debug!("assemble_extension_candidates_for_trait(trait_def_id={:?})", trait_def_id); From 2a899e2a2f3eb442af7637f3b9fce529f8441978 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Thu, 13 Feb 2020 16:47:51 +0100 Subject: [PATCH 0124/1250] Make TraitCandidate generic. --- src/librustc/ty/context.rs | 5 ++++- src/librustc/ty/mod.rs | 22 ++-------------------- src/librustc_hir/hir.rs | 17 ++++++++++++++--- src/librustc_resolve/late.rs | 6 +++--- src/librustc_resolve/lib.rs | 6 +++--- 5 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 1a071905523..b2eb122bfee 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1161,7 +1161,10 @@ impl<'tcx> TyCtxt<'tcx> { for (k, v) in resolutions.trait_map { let hir_id = hir.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); - let v = v.into_iter().map(|tc| tc.node_to_hir_id(&hir.definitions())).collect(); + let v = v + .into_iter() + .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id))) + .collect(); map.insert(hir_id.local_id, StableVec::new(v)); } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a561d48844b..ad51c60ab01 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -35,7 +35,7 @@ use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::{Constness, GlobMap, Node}; +use rustc_hir::{Constness, GlobMap, Node, TraitMap}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; @@ -46,7 +46,6 @@ use rustc_target::abi::Align; use syntax::ast::{self, Ident, Name}; use syntax::node_id::{NodeId, NodeMap, NodeSet}; -use smallvec::SmallVec; use std::cell::RefCell; use std::cmp::{self, Ordering}; use std::fmt; @@ -123,28 +122,11 @@ mod sty; // Data types -#[derive(Clone, Debug)] -pub struct TraitCandidate { - pub def_id: DefId, - pub import_ids: SmallVec<[NodeId; 1]>, -} - -impl TraitCandidate { - fn node_to_hir_id(self, definitions: &hir_map::Definitions) -> hir::TraitCandidate { - let TraitCandidate { def_id, import_ids } = self; - let import_ids = - import_ids.into_iter().map(|node_id| definitions.node_to_hir_id(node_id)).collect(); - hir::TraitCandidate { def_id, import_ids } - } -} - -pub type TraitMap = NodeMap>; - pub struct ResolverOutputs { pub definitions: hir_map::Definitions, pub cstore: Box, pub extern_crate_map: NodeMap, - pub trait_map: TraitMap, + pub trait_map: TraitMap, pub maybe_unused_trait_imports: NodeSet, pub maybe_unused_extern_crates: Vec<(NodeId, Span)>, pub export_map: ExportMap, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 0667bd3f4a2..80b379218a5 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2608,13 +2608,24 @@ pub type CaptureModeMap = NodeMap; // has length > 0 if the trait is found through an chain of imports, starting with the // import/use statement in the scope where the trait is used. #[derive(Clone, Debug)] -pub struct TraitCandidate { +pub struct TraitCandidate { pub def_id: DefId, - pub import_ids: SmallVec<[HirId; 1]>, + pub import_ids: SmallVec<[ID; 1]>, +} + +impl TraitCandidate { + pub fn map_import_ids(self, f: F) -> TraitCandidate + where + F: Fn(ID) -> T, + { + let TraitCandidate { def_id, import_ids } = self; + let import_ids = import_ids.into_iter().map(f).collect(); + TraitCandidate { def_id, import_ids } + } } // Trait method resolution -pub type TraitMap = NodeMap>; +pub type TraitMap = NodeMap>>; // Map from the NodeId of a glob import to a list of items which are actually // imported. diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index ea865a5590a..bcf558d1563 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,13 +11,13 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; -use rustc::ty::TraitCandidate; use rustc::{bug, lint, span_bug}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::DiagnosticId; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; +use rustc_hir::TraitCandidate; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -2078,7 +2078,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { &mut self, mut ident: Ident, ns: Namespace, - ) -> Vec { + ) -> Vec> { debug!("(getting traits containing item) looking for '{}'", ident.name); let mut found_traits = Vec::new(); @@ -2123,7 +2123,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, ns: Namespace, module: Module<'a>, - found_traits: &mut Vec, + found_traits: &mut Vec>, ) { assert!(ns == TypeNS || ns == ValueNS); let mut traits = module.traits.borrow_mut(); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index cfe100dc588..4278bf867f3 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -22,7 +22,7 @@ use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; -use rustc::ty::{self, DefIdTree, ResolverOutputs, TraitMap}; +use rustc::ty::{self, DefIdTree, ResolverOutputs}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::ptr_key::PtrKey; @@ -32,8 +32,8 @@ use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_hir::GlobMap; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; +use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; @@ -865,7 +865,7 @@ pub struct Resolver<'a> { /// `CrateNum` resolutions of `extern crate` items. extern_crate_map: NodeMap, export_map: ExportMap, - trait_map: TraitMap, + trait_map: TraitMap, /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items From 1e1b6ad1084783b4d6b21e9c6e79f114991f3dab Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 12 Feb 2020 15:20:29 -0800 Subject: [PATCH 0125/1250] Update books. --- src/bootstrap/test.rs | 82 ++++++++++++++++++++++++---------- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- src/doc/rustdoc/book.toml | 4 ++ src/tools/rustbook/src/main.rs | 34 +++++++++++--- src/tools/tidy/src/lib.rs | 1 + 9 files changed, 95 insertions(+), 36 deletions(-) create mode 100644 src/doc/rustdoc/book.toml diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1580091488f..43561fa4f2f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1264,15 +1264,15 @@ impl Step for Compiletest { } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] -struct DocTest { +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +struct BookTest { compiler: Compiler, - path: &'static str, + path: PathBuf, name: &'static str, is_ext_doc: bool, } -impl Step for DocTest { +impl Step for BookTest { type Output = (); const ONLY_HOSTS: bool = true; @@ -1280,12 +1280,59 @@ impl Step for DocTest { run.never() } - /// Runs `rustdoc --test` for all documentation in `src/doc`. + /// Runs the documentation tests for a book in `src/doc`. /// - /// This will run all tests in our markdown documentation (e.g., the book) - /// located in `src/doc`. The `rustdoc` that's run is the one that sits next to - /// `compiler`. + /// This uses the `rustdoc` that sits next to `compiler`. fn run(self, builder: &Builder<'_>) { + // External docs are different from local because: + // - Some books need pre-processing by mdbook before being tested. + // - They need to save their state to toolstate. + // - They are only tested on the "checktools" builders. + // + // The local docs are tested by default, and we don't want to pay the + // cost of building mdbook, so they use `rustdoc --test` directly. + // Also, the unstable book is special because SUMMARY.md is generated, + // so it is easier to just run `rustdoc` on its files. + if self.is_ext_doc { + self.run_ext_doc(builder); + } else { + self.run_local_doc(builder); + } + } +} + +impl BookTest { + /// This runs the equivalent of `mdbook test` (via the rustbook wrapper) + /// which in turn runs `rustdoc --test` on each file in the book. + fn run_ext_doc(self, builder: &Builder<'_>) { + let compiler = self.compiler; + + builder.ensure(compile::Std { compiler, target: compiler.host }); + + // mdbook just executes a binary named "rustdoc", so we need to update + // PATH so that it points to our rustdoc. + let mut rustdoc_path = builder.rustdoc(compiler); + rustdoc_path.pop(); + let old_path = env::var_os("PATH").unwrap_or_default(); + let new_path = env::join_paths(iter::once(rustdoc_path).chain(env::split_paths(&old_path))) + .expect("could not add rustdoc to PATH"); + + let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); + let path = builder.src.join(&self.path); + rustbook_cmd.env("PATH", new_path).arg("test").arg(path); + builder.add_rust_test_threads(&mut rustbook_cmd); + builder.info(&format!("Testing rustbook {}", self.path.display())); + let _time = util::timeit(&builder); + let toolstate = if try_run(builder, &mut rustbook_cmd) { + ToolState::TestPass + } else { + ToolState::TestFail + }; + builder.save_toolstate(self.name, toolstate); + } + + /// This runs `rustdoc --test` on all `.md` files in the path. + fn run_local_doc(self, builder: &Builder<'_>) { let compiler = self.compiler; builder.ensure(compile::Std { compiler, target: compiler.host }); @@ -1294,7 +1341,6 @@ impl Step for DocTest { // tests for all files that end in `*.md` let mut stack = vec![builder.src.join(self.path)]; let _time = util::timeit(&builder); - let mut files = Vec::new(); while let Some(p) = stack.pop() { if p.is_dir() { @@ -1306,25 +1352,13 @@ impl Step for DocTest { continue; } - // The nostarch directory in the book is for no starch, and so isn't - // guaranteed to builder. We don't care if it doesn't build, so skip it. - if p.to_str().map_or(false, |p| p.contains("nostarch")) { - continue; - } - files.push(p); } files.sort(); - let mut toolstate = ToolState::TestPass; for file in files { - if !markdown_test(builder, compiler, &file) { - toolstate = ToolState::TestFail; - } - } - if self.is_ext_doc { - builder.save_toolstate(self.name, toolstate); + markdown_test(builder, compiler, &file); } } } @@ -1353,9 +1387,9 @@ macro_rules! test_book { } fn run(self, builder: &Builder<'_>) { - builder.ensure(DocTest { + builder.ensure(BookTest { compiler: self.compiler, - path: $path, + path: PathBuf::from($path), name: $book_name, is_ext_doc: !$default, }); diff --git a/src/doc/book b/src/doc/book index 87dd6843678..6fb3705e523 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit 87dd6843678575f8dda962f239d14ef4be14b352 +Subproject commit 6fb3705e5230311b096d47f7e2c91f9ce24393d0 diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 1a2390247ad..37f9e684841 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 1a2390247ad6d08160e0dd74f40a01a9578659c2 +Subproject commit 37f9e6848411188a1062ead1bd8ebe4b8aa16899 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 4d78994915a..b2e1092bf67 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 4d78994915af1bde9a95c04a8c27d8dca066232a +Subproject commit b2e1092bf67bd4d7686c4553f186edbb7f5f92db diff --git a/src/doc/reference b/src/doc/reference index 11e893fc135..64239df6d17 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 11e893fc1357bc688418ddf1087c2b7aa25d154d +Subproject commit 64239df6d173562b9deb4f012e4c3e6e960c4754 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 1c2bd024d13..32facd5522d 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 1c2bd024d13f8011307e13386cf1fea2180352b5 +Subproject commit 32facd5522ddbbf37baf01e4e4b6562bc55c071a diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml new file mode 100644 index 00000000000..ba30c107667 --- /dev/null +++ b/src/doc/rustdoc/book.toml @@ -0,0 +1,4 @@ +[book] +authors = ["The Rust Project Developers"] +src = "src" +title = "The rustdoc book" diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 023f5aa1e28..ca4bf4ea662 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -25,6 +25,11 @@ fn main() { .arg_from_usage(d_message) .arg_from_usage(dir_message), ) + .subcommand( + SubCommand::with_name("test") + .about("Tests that a book's Rust code samples compile") + .arg_from_usage(dir_message), + ) .subcommand( SubCommand::with_name("linkcheck") .about("Run linkcheck with mdBook 3") @@ -36,13 +41,12 @@ fn main() { match matches.subcommand() { ("build", Some(sub_matches)) => { if let Err(e) = build(sub_matches) { - eprintln!("Error: {}", e); - - for cause in e.iter().skip(1) { - eprintln!("\tCaused By: {}", cause); - } - - ::std::process::exit(101); + handle_error(e); + } + } + ("test", Some(sub_matches)) => { + if let Err(e) = test(sub_matches) { + handle_error(e); } } ("linkcheck", Some(sub_matches)) => { @@ -146,6 +150,12 @@ pub fn build(args: &ArgMatches<'_>) -> Result3<()> { Ok(()) } +fn test(args: &ArgMatches<'_>) -> Result3<()> { + let book_dir = get_book_dir(args); + let mut book = MDBook::load(&book_dir)?; + book.test(vec![]) +} + fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf { if let Some(dir) = args.value_of("dir") { // Check if path is relative from current dir, or absolute... @@ -155,3 +165,13 @@ fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf { env::current_dir().unwrap() } } + +fn handle_error(error: mdbook::errors::Error) -> ! { + eprintln!("Error: {}", error); + + for cause in error.iter().skip(1) { + eprintln!("\tCaused By: {}", cause); + } + + ::std::process::exit(101); +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index c8c61b6fb50..be1e598d8d4 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -58,6 +58,7 @@ fn filter_dirs(path: &Path) -> bool { "src/tools/rls", "src/tools/rust-installer", "src/tools/rustfmt", + "src/doc/book", // Filter RLS output directories "target/rls", ]; From 026dec550002356ea52a0800db5de0f361631f56 Mon Sep 17 00:00:00 2001 From: Drew Ripberger Date: Thu, 13 Feb 2020 11:14:21 -0500 Subject: [PATCH 0126/1250] Spelling error "represening" to "representing" --- src/librustc_lexer/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 969ce9b06e8..25334461a11 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -35,7 +35,7 @@ impl Token { } } -/// Enum represening common lexeme types. +/// Enum representing common lexeme types. #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum TokenKind { // Multi-char tokens: From 4810c4712f9edc4c378142ace1b868fc2fd1eeea Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 13 Feb 2020 09:50:20 -0800 Subject: [PATCH 0127/1250] Add shared script for linkchecking books. --- src/tools/linkchecker/linkcheck.sh | 113 +++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100755 src/tools/linkchecker/linkcheck.sh diff --git a/src/tools/linkchecker/linkcheck.sh b/src/tools/linkchecker/linkcheck.sh new file mode 100755 index 00000000000..bbccc17e494 --- /dev/null +++ b/src/tools/linkchecker/linkcheck.sh @@ -0,0 +1,113 @@ +#!/bin/sh +# +# This is a script that can be used in each book's CI to validate links using +# the same tool as rust-lang/rust. +# +# This requires the rust-docs rustup component to be installed in the nightly +# toolchain. +# +# Usage: +# ./linkcheck.sh +# +# Options: +# +# -i "Iterative" mode. The script will not clean up after it is done so +# you can inspect the result, and re-run more quickly. +# +# --all Check all books. This can help make sure you don't break links +# from other books into your book. + +set -e + +if [ ! -f book.toml ] && [ ! -f src/SUMMARY.md ] +then + echo "Run command in root directory of the book." + exit 1 +fi + +html_dir="$(rustc +nightly --print sysroot)/share/doc/rust/html" + +if [ ! -d "$html_dir" ] +then + echo "HTML docs are missing from sysroot: $html_dir" + echo "Make sure the nightly rust-docs rustup component is installed." + exit 1 +fi + +book_name="" +# Iterative will avoid cleaning up, so you can quickly run it repeatedly. +iterative=0 +# If "1", test all books, else only this book. +all_books=0 + +while [ "$1" != "" ] +do + case "$1" in + -i) + iterative=1 + ;; + --all) + all_books=1 + ;; + *) + if [ -n "$book_name" ] + then + echo "only one argument allowed" + exit 1 + fi + book_name="$1" + ;; + esac + shift +done + +if [ -z "$book_name" ] +then + echo "usage: $0 " + exit 1 +fi + +if [ ! -d "$html_dir/$book_name" ] +then + echo "book name \"$book_name\" not found in sysroot \"$html_dir\"" + exit 1 +fi + +if [ "$iterative" = "0" ] +then + echo "Cleaning old directories..." + rm -rf linkcheck linkchecker +fi + +if [ ! -e "linkchecker/main.rs" ] || [ "$iterative" = "0" ] +then + echo "Downloading linkchecker source..." + mkdir linkchecker + curl -o linkchecker/Cargo.toml \ + https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/Cargo.toml + curl -o linkchecker/main.rs \ + https://raw.githubusercontent.com/rust-lang/rust/master/src/tools/linkchecker/main.rs +fi + +echo "Building book \"$book_name\"..." +mdbook build + +cp -R "$html_dir" linkcheck +rm -rf "linkcheck/$book_name" +cp -R book "linkcheck/$book_name" + +if [ "$all_books" = "1" ] +then + check_path="linkcheck" +else + check_path="linkcheck/$book_name" +fi +echo "Running linkchecker on \"$check_path\"..." +cargo run --manifest-path=linkchecker/Cargo.toml -- "$check_path" + +if [ "$iterative" = "0" ] +then + rm -rf linkcheck linkchecker +fi + +echo "Link check completed successfully!" From 23cb749bbb5c57e85a89b72a76299df1aef464e7 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 13 Feb 2020 11:53:07 -0600 Subject: [PATCH 0128/1250] don't error on network failures --- src/tools/rustbook/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 023f5aa1e28..226779ad0c0 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -115,6 +115,8 @@ pub fn linkcheck( eprintln!("Timeout for link `{}`", link.link.uri); } else if err.is_server_error() { eprintln!("Server error for link `{}`", link.link.uri); + } else if !err.is_http() { + eprintln!("Non-HTTP-related error for link: {} {}", link.link.uri, err); } else { is_real_error = true; } From 0e652c550711b301086b8f5ead2f6c90418fe7a1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 12 Feb 2020 17:24:32 +0100 Subject: [PATCH 0129/1250] Move resolve_instance to rustc_ty. --- Cargo.lock | 1 + src/librustc/ty/instance.rs | 143 ++++------------------------ src/librustc/ty/mod.rs | 1 + src/librustc_interface/callbacks.rs | 1 + src/librustc_ty/Cargo.toml | 1 + src/librustc_ty/instance.rs | 136 ++++++++++++++++++++++++++ src/librustc_ty/lib.rs | 1 + 7 files changed, 161 insertions(+), 123 deletions(-) create mode 100644 src/librustc_ty/instance.rs diff --git a/Cargo.lock b/Cargo.lock index 149f02b4b8c..007a7521290 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4123,6 +4123,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_span", + "rustc_target", ] [[package]] diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 335953fc41e..332fd0bf46f 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -1,12 +1,11 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::middle::lang_items::DropInPlaceFnLangItem; -use crate::traits; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; +use rustc_data_structures::AtomicRef; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_macros::HashStable; -use rustc_target::spec::abi::Abi; use std::fmt; @@ -263,45 +262,7 @@ impl<'tcx> Instance<'tcx> { def_id: DefId, substs: SubstsRef<'tcx>, ) -> Option> { - debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); - let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { - debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); - let item = tcx.associated_item(def_id); - resolve_associated_item(tcx, &item, param_env, trait_def_id, substs) - } else { - let ty = tcx.type_of(def_id); - let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty); - - let def = match item_type.kind { - ty::FnDef(..) - if { - let f = item_type.fn_sig(tcx); - f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic - } => - { - debug!(" => intrinsic"); - ty::InstanceDef::Intrinsic(def_id) - } - _ => { - if Some(def_id) == tcx.lang_items().drop_in_place_fn() { - let ty = substs.type_at(0); - if ty.needs_drop(tcx, param_env.with_reveal_all()) { - debug!(" => nontrivial drop glue"); - ty::InstanceDef::DropGlue(def_id, Some(ty)) - } else { - debug!(" => trivial drop glue"); - ty::InstanceDef::DropGlue(def_id, None) - } - } else { - debug!(" => free item"); - ty::InstanceDef::Item(def_id) - } - } - }; - Some(Instance { def: def, substs: substs }) - }; - debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result); - result + (*RESOLVE_INSTANCE)(tcx, param_env, def_id, substs) } pub fn resolve_for_fn_ptr( @@ -398,88 +359,6 @@ impl<'tcx> Instance<'tcx> { } } -fn resolve_associated_item<'tcx>( - tcx: TyCtxt<'tcx>, - trait_item: &ty::AssocItem, - param_env: ty::ParamEnv<'tcx>, - trait_id: DefId, - rcvr_substs: SubstsRef<'tcx>, -) -> Option> { - let def_id = trait_item.def_id; - debug!( - "resolve_associated_item(trait_item={:?}, \ - param_env={:?}, \ - trait_id={:?}, \ - rcvr_substs={:?})", - def_id, param_env, trait_id, rcvr_substs - ); - - let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); - - // Now that we know which impl is being used, we can dispatch to - // the actual function: - match vtbl { - traits::VtableImpl(impl_data) => { - let (def_id, substs) = - traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data); - - let resolved_item = tcx.associated_item(def_id); - - // Since this is a trait item, we need to see if the item is either a trait default item - // or a specialization because we can't resolve those unless we can `Reveal::All`. - // NOTE: This should be kept in sync with the similar code in - // `rustc::traits::project::assemble_candidates_from_impls()`. - let eligible = if !resolved_item.defaultness.is_default() { - true - } else if param_env.reveal == traits::Reveal::All { - !trait_ref.needs_subst() - } else { - false - }; - - if !eligible { - return None; - } - - let substs = tcx.erase_regions(&substs); - Some(ty::Instance::new(def_id, substs)) - } - traits::VtableGenerator(generator_data) => Some(Instance { - def: ty::InstanceDef::Item(generator_data.generator_def_id), - substs: generator_data.substs, - }), - traits::VtableClosure(closure_data) => { - let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); - Some(Instance::resolve_closure( - tcx, - closure_data.closure_def_id, - closure_data.substs, - trait_closure_kind, - )) - } - traits::VtableFnPointer(ref data) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), - substs: rcvr_substs, - }), - traits::VtableObject(ref data) => { - let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); - Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) - } - traits::VtableBuiltin(..) => { - if tcx.lang_items().clone_trait().is_some() { - Some(Instance { - def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), - substs: rcvr_substs, - }) - } else { - None - } - } - traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None, - } -} - fn needs_fn_once_adapter_shim( actual_closure_kind: ty::ClosureKind, trait_closure_kind: ty::ClosureKind, @@ -512,3 +391,21 @@ fn needs_fn_once_adapter_shim( (ty::ClosureKind::FnMut, _) | (ty::ClosureKind::FnOnce, _) => Err(()), } } + +fn resolve_instance_default( + _tcx: TyCtxt<'tcx>, + _param_env: ty::ParamEnv<'tcx>, + _def_id: DefId, + _substs: SubstsRef<'tcx>, +) -> Option> { + unimplemented!() +} + +pub static RESOLVE_INSTANCE: AtomicRef< + for<'tcx> fn( + TyCtxt<'tcx>, + ty::ParamEnv<'tcx>, + DefId, + SubstsRef<'tcx>, + ) -> Option>, +> = AtomicRef::new(&(resolve_instance_default as _)); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 2bda99e6d20..04e8c0c38d7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -83,6 +83,7 @@ pub use self::context::{ CtxtInterners, GeneratorInteriorTypeCause, GlobalCtxt, Lift, TypeckTables, }; +pub use self::instance::RESOLVE_INSTANCE; pub use self::instance::{Instance, InstanceDef}; pub use self::trait_def::TraitDef; diff --git a/src/librustc_interface/callbacks.rs b/src/librustc_interface/callbacks.rs index 803e8958572..7c8e682e9fb 100644 --- a/src/librustc_interface/callbacks.rs +++ b/src/librustc_interface/callbacks.rs @@ -58,4 +58,5 @@ pub fn setup_callbacks() { rustc_span::SPAN_DEBUG.swap(&(span_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); rustc_hir::def_id::DEF_ID_DEBUG.swap(&(def_id_debug as fn(_, &mut fmt::Formatter<'_>) -> _)); TRACK_DIAGNOSTICS.swap(&(track_diagnostic as fn(&_))); + rustc::ty::RESOLVE_INSTANCE.swap(&(rustc_ty::instance::resolve_instance as _)); } diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml index fb0d93fe5eb..52606e5fdfe 100644 --- a/src/librustc_ty/Cargo.toml +++ b/src/librustc_ty/Cargo.toml @@ -14,3 +14,4 @@ rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_hir = { path = "../librustc_hir" } rustc_span = { path = "../librustc_span" } +rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs new file mode 100644 index 00000000000..66f189a5d97 --- /dev/null +++ b/src/librustc_ty/instance.rs @@ -0,0 +1,136 @@ +use rustc::traits; +use rustc::ty::subst::SubstsRef; +use rustc::ty::{self, Instance, TyCtxt, TypeFoldable}; +use rustc_hir::def_id::DefId; +use rustc_target::spec::abi::Abi; + +use log::debug; + +pub fn resolve_instance<'tcx>( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, +) -> Option> { + debug!("resolve(def_id={:?}, substs={:?})", def_id, substs); + let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { + debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); + let item = tcx.associated_item(def_id); + resolve_associated_item(tcx, &item, param_env, trait_def_id, substs) + } else { + let ty = tcx.type_of(def_id); + let item_type = tcx.subst_and_normalize_erasing_regions(substs, param_env, &ty); + + let def = match item_type.kind { + ty::FnDef(..) + if { + let f = item_type.fn_sig(tcx); + f.abi() == Abi::RustIntrinsic || f.abi() == Abi::PlatformIntrinsic + } => + { + debug!(" => intrinsic"); + ty::InstanceDef::Intrinsic(def_id) + } + _ => { + if Some(def_id) == tcx.lang_items().drop_in_place_fn() { + let ty = substs.type_at(0); + if ty.needs_drop(tcx, param_env.with_reveal_all()) { + debug!(" => nontrivial drop glue"); + ty::InstanceDef::DropGlue(def_id, Some(ty)) + } else { + debug!(" => trivial drop glue"); + ty::InstanceDef::DropGlue(def_id, None) + } + } else { + debug!(" => free item"); + ty::InstanceDef::Item(def_id) + } + } + }; + Some(Instance { def: def, substs: substs }) + }; + debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result); + result +} + +fn resolve_associated_item<'tcx>( + tcx: TyCtxt<'tcx>, + trait_item: &ty::AssocItem, + param_env: ty::ParamEnv<'tcx>, + trait_id: DefId, + rcvr_substs: SubstsRef<'tcx>, +) -> Option> { + let def_id = trait_item.def_id; + debug!( + "resolve_associated_item(trait_item={:?}, \ + param_env={:?}, \ + trait_id={:?}, \ + rcvr_substs={:?})", + def_id, param_env, trait_id, rcvr_substs + ); + + let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); + + // Now that we know which impl is being used, we can dispatch to + // the actual function: + match vtbl { + traits::VtableImpl(impl_data) => { + let (def_id, substs) = + traits::find_associated_item(tcx, param_env, trait_item, rcvr_substs, &impl_data); + + let resolved_item = tcx.associated_item(def_id); + + // Since this is a trait item, we need to see if the item is either a trait default item + // or a specialization because we can't resolve those unless we can `Reveal::All`. + // NOTE: This should be kept in sync with the similar code in + // `rustc::traits::project::assemble_candidates_from_impls()`. + let eligible = if !resolved_item.defaultness.is_default() { + true + } else if param_env.reveal == traits::Reveal::All { + !trait_ref.needs_subst() + } else { + false + }; + + if !eligible { + return None; + } + + let substs = tcx.erase_regions(&substs); + Some(ty::Instance::new(def_id, substs)) + } + traits::VtableGenerator(generator_data) => Some(Instance { + def: ty::InstanceDef::Item(generator_data.generator_def_id), + substs: generator_data.substs, + }), + traits::VtableClosure(closure_data) => { + let trait_closure_kind = tcx.fn_trait_kind_from_lang_item(trait_id).unwrap(); + Some(Instance::resolve_closure( + tcx, + closure_data.closure_def_id, + closure_data.substs, + trait_closure_kind, + )) + } + traits::VtableFnPointer(ref data) => Some(Instance { + def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), + substs: rcvr_substs, + }), + traits::VtableObject(ref data) => { + let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); + Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) + } + traits::VtableBuiltin(..) => { + if tcx.lang_items().clone_trait().is_some() { + Some(Instance { + def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), + substs: rcvr_substs, + }) + } else { + None + } + } + traits::VtableAutoImpl(..) | traits::VtableParam(..) | traits::VtableTraitAlias(..) => None, + } +} diff --git a/src/librustc_ty/lib.rs b/src/librustc_ty/lib.rs index 7eef19b94e4..f9ee4e20d27 100644 --- a/src/librustc_ty/lib.rs +++ b/src/librustc_ty/lib.rs @@ -17,6 +17,7 @@ extern crate log; use rustc::ty::query::Providers; mod common_traits; +pub mod instance; mod needs_drop; mod ty; From 859302302100d21443315e5ffa1faf6dbeb3eaaf Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 15 Dec 2019 16:42:30 +0000 Subject: [PATCH 0130/1250] Don't instantiate so many copies of `drop_in_place` --- src/librustc/ty/instance.rs | 25 ++++++++++++++++--- src/librustc_mir/monomorphize/partitioning.rs | 13 +++++++--- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 335953fc41e..fd4fa71e163 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -54,7 +54,10 @@ pub enum InstanceDef<'tcx> { call_once: DefId, }, - /// `drop_in_place::; None` for empty drop glue. + /// `core::ptr::drop_in_place::`. + /// The `DefId` is for `core::ptr::drop_in_place`. + /// The `Option>` is either `Some(T)`, or `None` for empty drop + /// glue. DropGlue(DefId, Option>), ///`::clone` shim. @@ -177,11 +180,25 @@ impl<'tcx> InstanceDef<'tcx> { if self.requires_inline(tcx) { return true; } - if let ty::InstanceDef::DropGlue(..) = *self { - // Drop glue wants to be instantiated at every codegen + if let ty::InstanceDef::DropGlue(.., Some(ty)) = *self { + // Drop glue generally wants to be instantiated at every codegen // unit, but without an #[inline] hint. We should make this // available to normal end-users. - return true; + if tcx.sess.opts.incremental.is_none() { + return true; + } + // When compiling with incremental, we can generate a *lot* of + // codegen units. Including drop glue into all of them has a + // considerable compile time cost. + // + // We include enums without destructors to allow, say, optimizing + // drops of `Option::None` before LTO. We also respect the intent of + // `#[inline]` on `Drop::drop` implementations. + return ty.ty_adt_def().map_or(true, |adt_def| { + adt_def.destructor(tcx).map_or(adt_def.is_enum(), |dtor| { + tcx.codegen_fn_attrs(dtor.did).requests_inline() + }) + }); } tcx.codegen_fn_attrs(self.def_id()).requests_inline() } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index de45808a481..9b81d69ce69 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -680,13 +680,20 @@ fn characteristic_def_id_of_mono_item<'tcx>( if tcx.trait_of_item(def_id).is_some() { let self_ty = instance.substs.type_at(0); - // This is an implementation of a trait method. + // This is a default implementation of a trait method. return characteristic_def_id_of_type(self_ty).or(Some(def_id)); } if let Some(impl_def_id) = tcx.impl_of_method(def_id) { - // This is a method within an inherent impl, find out what the - // self-type is: + if tcx.sess.opts.incremental.is_some() + && tcx.trait_id_of_impl(impl_def_id) == tcx.lang_items().drop_trait() + { + // Put `Drop::drop` into the same cgu as `drop_in_place` + // since `drop_in_place` is the only thing that can + // call it. + return None; + } + // This is a method within an impl, find out what the self-type is: let impl_self_ty = tcx.subst_and_normalize_erasing_regions( instance.substs, ty::ParamEnv::reveal_all(), From a113609bdf0f05a3f32ab2f19bed38bde0d7063a Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Mon, 30 Dec 2019 22:46:07 +0000 Subject: [PATCH 0131/1250] keyword docs for else and inkeyword docs for else and in. --- src/libstd/keyword_docs.rs | 61 ++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 7901c8197b5..2d8bea6ffaf 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -234,12 +234,55 @@ mod crate_keyword {} #[doc(keyword = "else")] // -/// What to do when an [`if`] condition does not hold. +/// What expression to evaluate when an [`if`] condition evaluates to [`false`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// `else` expressions are optional. When no else expressions are supplied it is assumed to evaluate +/// to the unit type `()`. +/// +/// The type that the `else` blocks evaluate to must be compatible with the type that the `if` block +/// evaluates to. +/// +/// As can be seen below, `else` must be followed by either: `if`, `if let`, or a block `{}` and it +/// will return the value of that expression. +/// +/// ```rust +/// let result = if true == false { +/// "oh no" +/// } else if "something" == "other thing" { +/// "oh dear" +/// } else if let Some(200) = "blarg".parse::().ok() { +/// "uh oh" +/// } else { +/// println!("Sneaky side effect."); +/// "phew, nothing's broken" +/// }; +/// ``` +/// +/// Here's another example but here we do not try and return an expression: +/// +/// ```rust +/// if true == false { +/// println!("oh no"); +/// } else if "something" == "other thing" { +/// println!("oh dear"); +/// } else if let Some(200) = "blarg".parse::().ok() { +/// println!("uh oh"); +/// } else { +/// println!("phew, nothing's broken"); +/// } +/// ``` +/// +/// The above is _still_ an expression but it will always evaluate to `()`. /// +/// There is possibly no limit to the number of `else` blocks that could follow an `if` expression +/// however if you have several then a [`match`] expression might be preferable. +/// +/// Read more about control flow in the [Rust Book]. +/// +/// [Rust Book]: ../book/ch03-05-control-flow.html#handling-multiple-conditions-with-else-if +/// [`match`]: keyword.match.html +/// [`false`]: keyword.false.html /// [`if`]: keyword.if.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod else_keyword {} #[doc(keyword = "enum")] @@ -637,10 +680,18 @@ mod impl_keyword {} // /// Iterate over a series of values with [`for`]. /// -/// The documentation for this keyword is [not yet complete]. Pull requests welcome! +/// The expression immediately following `in` must implement the [`Iterator`] trait. /// +/// ## Literal Examples: +/// +/// * `for _ **in** 1..3 {}` - Iterate over an exclusive range up to but excluding 3. +/// * `for _ **in** 1..=3 {}` - Iterate over an inclusive range up to and includeing 3. +/// +/// (Read more about [range patterns]) +/// +/// [`Iterator`]: ../book/ch13-04-performance.html +/// [`range patterns`]: ../reference/patterns.html?highlight=range#range-patterns /// [`for`]: keyword.for.html -/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601 mod in_keyword {} #[doc(keyword = "let")] From cd9f5ff2a1c50a5af94ad1dd1c976f631b9f19a6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 13 Feb 2020 20:29:03 +0000 Subject: [PATCH 0132/1250] Check `Copy` lifetimes bounds when copying from a projection --- .../borrow_check/type_check/mod.rs | 52 +++++++++---------- ...not-ignore-lifetime-bounds-in-copy-proj.rs | 12 +++++ ...ignore-lifetime-bounds-in-copy-proj.stderr | 14 +++++ 3 files changed, 51 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs create mode 100644 src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 5dab064c7b7..232e7e6b83d 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -466,33 +466,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut place_ty = PlaceTy::from_ty(self.body.local_decls[place.local].ty); - if place.projection.is_empty() { - if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { - let tcx = self.tcx(); - let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().copy_trait().unwrap(), - substs: tcx.mk_substs_trait(place_ty.ty, &[]), - }; - - // To have a `Copy` operand, the type `T` of the - // value must be `Copy`. Note that we prove that `T: Copy`, - // rather than using the `is_copy_modulo_regions` - // test. This is important because - // `is_copy_modulo_regions` ignores the resulting region - // obligations and assumes they pass. This can result in - // bounds from `Copy` impls being unsoundly ignored (e.g., - // #29149). Note that we decide to use `Copy` before knowing - // whether the bounds fully apply: in effect, the rule is - // that if a value of some type could implement `Copy`, then - // it must. - self.cx.prove_trait_ref( - trait_ref, - location.to_locations(), - ConstraintCategory::CopyBound, - ); - } - } - for elem in place.projection.iter() { if place_ty.variant_index.is_none() { if place_ty.ty.references_error() { @@ -503,6 +476,31 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { place_ty = self.sanitize_projection(place_ty, elem, place, location) } + if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { + let tcx = self.tcx(); + let trait_ref = ty::TraitRef { + def_id: tcx.lang_items().copy_trait().unwrap(), + substs: tcx.mk_substs_trait(place_ty.ty, &[]), + }; + + // To have a `Copy` operand, the type `T` of the + // value must be `Copy`. Note that we prove that `T: Copy`, + // rather than using the `is_copy_modulo_regions` + // test. This is important because + // `is_copy_modulo_regions` ignores the resulting region + // obligations and assumes they pass. This can result in + // bounds from `Copy` impls being unsoundly ignored (e.g., + // #29149). Note that we decide to use `Copy` before knowing + // whether the bounds fully apply: in effect, the rule is + // that if a value of some type could implement `Copy`, then + // it must. + self.cx.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::CopyBound, + ); + } + place_ty } diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs new file mode 100644 index 00000000000..96c8719468f --- /dev/null +++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.rs @@ -0,0 +1,12 @@ +// Test that the 'static bound from the Copy impl is respected. Regression test for #29149. + +#[derive(Clone)] +struct Foo<'a>(&'a u32); +impl Copy for Foo<'static> {} + +fn main() { + let s = 2; + let a = (Foo(&s),); //~ ERROR `s` does not live long enough [E0597] + drop(a.0); + drop(a.0); +} diff --git a/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr new file mode 100644 index 00000000000..65be3b37e0e --- /dev/null +++ b/src/test/ui/nll/do-not-ignore-lifetime-bounds-in-copy-proj.stderr @@ -0,0 +1,14 @@ +error[E0597]: `s` does not live long enough + --> $DIR/do-not-ignore-lifetime-bounds-in-copy-proj.rs:9:18 + | +LL | let a = (Foo(&s),); + | ^^ borrowed value does not live long enough +LL | drop(a.0); + | --- copying this value requires that `s` is borrowed for `'static` +LL | drop(a.0); +LL | } + | - `s` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From ddc25456c5945457ba86cb60994ce9872bd98edd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 13 Feb 2020 20:29:30 +0000 Subject: [PATCH 0133/1250] Check types of statics in MIR typeck --- .../borrow_check/type_check/mod.rs | 18 +++++++++-- src/test/ui/nll/issue-69114-static-mut-ty.rs | 30 +++++++++++++++++++ .../ui/nll/issue-69114-static-mut-ty.stderr | 27 +++++++++++++++++ src/test/ui/nll/issue-69114-static-ty.rs | 9 ++++++ src/test/ui/nll/issue-69114-static-ty.stderr | 15 ++++++++++ 5 files changed, 97 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-mut-ty.stderr create mode 100644 src/test/ui/nll/issue-69114-static-ty.rs create mode 100644 src/test/ui/nll/issue-69114-static-ty.stderr diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 232e7e6b83d..78f708b9a74 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -309,6 +309,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ); } } else { + let tcx = self.tcx(); if let ty::ConstKind::Unevaluated(def_id, substs, promoted) = constant.literal.val { if let Some(promoted) = promoted { let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, @@ -358,10 +359,23 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ); } } + } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { + let unnormalized_ty = tcx.type_of(static_def_id); + let locations = location.to_locations(); + let normalized_ty = self.cx.normalize(unnormalized_ty, locations); + let literal_ty = constant.literal.ty.builtin_deref(true).unwrap().ty; + + if let Err(terr) = self.cx.eq_types( + normalized_ty, + literal_ty, + locations, + ConstraintCategory::Boring, + ) { + span_mirbug!(self, constant, "bad static type {:?} ({:?})", constant, terr); + } } - if let ty::FnDef(def_id, substs) = constant.literal.ty.kind { - let tcx = self.tcx(); + if let ty::FnDef(def_id, substs) = constant.literal.ty.kind { let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); self.cx.normalize_and_prove_instantiated_predicates( instantiated_predicates, diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.rs b/src/test/ui/nll/issue-69114-static-mut-ty.rs new file mode 100644 index 00000000000..ce37da053e3 --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-mut-ty.rs @@ -0,0 +1,30 @@ +// Check that borrowck ensures that `static mut` items have the expected type. + +static FOO: u8 = 42; +static mut BAR: &'static u8 = &FOO; +static mut BAR_ELIDED: &u8 = &FOO; + +fn main() { + unsafe { + println!("{} {}", BAR, BAR_ELIDED); + set_bar(); + set_bar_elided(); + println!("{} {}", BAR, BAR_ELIDED); + } +} + +fn set_bar() { + let n = 42; + unsafe { + BAR = &n; + //~^ ERROR does not live long enough + } +} + +fn set_bar_elided() { + let n = 42; + unsafe { + BAR_ELIDED = &n; + //~^ ERROR does not live long enough + } +} diff --git a/src/test/ui/nll/issue-69114-static-mut-ty.stderr b/src/test/ui/nll/issue-69114-static-mut-ty.stderr new file mode 100644 index 00000000000..5e55cb502ca --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-mut-ty.stderr @@ -0,0 +1,27 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:19:15 + | +LL | BAR = &n; + | ------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-mut-ty.rs:27:22 + | +LL | BAR_ELIDED = &n; + | -------------^^ + | | | + | | borrowed value does not live long enough + | assignment requires that `n` is borrowed for `'static` +... +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/nll/issue-69114-static-ty.rs b/src/test/ui/nll/issue-69114-static-ty.rs new file mode 100644 index 00000000000..3318433a1c5 --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-ty.rs @@ -0,0 +1,9 @@ +// Check that borrowck ensures that `static` items have the expected type. + +static FOO: &'static (dyn Fn(&'static u8) + Send + Sync) = &drop; + +fn main() { + let n = 42; + FOO(&n); + //~^ ERROR does not live long enough +} diff --git a/src/test/ui/nll/issue-69114-static-ty.stderr b/src/test/ui/nll/issue-69114-static-ty.stderr new file mode 100644 index 00000000000..0815e74b553 --- /dev/null +++ b/src/test/ui/nll/issue-69114-static-ty.stderr @@ -0,0 +1,15 @@ +error[E0597]: `n` does not live long enough + --> $DIR/issue-69114-static-ty.rs:7:9 + | +LL | FOO(&n); + | ----^^- + | | | + | | borrowed value does not live long enough + | argument requires that `n` is borrowed for `'static` +LL | +LL | } + | - `n` dropped here while still borrowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0597`. From 15a5382ef1115ff11c1357fd21ab4aa12626efee Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 13:56:19 -0800 Subject: [PATCH 0134/1250] Rename `MaybeBorrowedLocals` constructors --- src/librustc_mir/dataflow/impls/borrowed_locals.rs | 7 +++++-- src/librustc_mir/transform/check_consts/validation.rs | 2 +- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 519db963d1e..20aab8b32a5 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -27,7 +27,7 @@ pub struct MaybeBorrowedLocals { impl MaybeBorrowedLocals { /// A dataflow analysis that records whether a pointer or reference exists that may alias the /// given local. - pub fn new() -> Self { + pub fn all_borrows() -> Self { MaybeBorrowedLocals { kind: AnyBorrow } } } @@ -35,7 +35,10 @@ impl MaybeBorrowedLocals { impl MaybeMutBorrowedLocals<'mir, 'tcx> { /// A dataflow analysis that records whether a pointer or reference exists that may *mutably* /// alias the given local. - pub fn new_mut_only( + /// + /// This includes `&mut` and pointers derived from an `&mut`, as well as shared borrows of + /// types with interior mutability. + pub fn mut_borrows_only( tcx: TyCtxt<'tcx>, body: &'mir mir::Body<'tcx>, param_env: ParamEnv<'tcx>, diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 9fef62325f2..d9e179ad42a 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -141,7 +141,7 @@ impl Validator<'a, 'mir, 'tcx> { let needs_drop = QualifCursor::new(NeedsDrop, item); let has_mut_interior = QualifCursor::new(HasMutInterior, item); - let indirectly_mutable = MaybeMutBorrowedLocals::new_mut_only(tcx, *body, param_env) + let indirectly_mutable = MaybeMutBorrowedLocals::mut_borrows_only(tcx, *body, param_env) .into_engine(tcx, *body, def_id) .iterate_to_fixpoint() .into_results_cursor(*body); diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index cd00274afcc..4b3cd2be66d 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -473,7 +473,7 @@ fn locals_live_across_suspend_points( // Calculate the MIR locals which have been previously // borrowed (even if they are still active). let borrowed_locals_results = - MaybeBorrowedLocals::new().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint(); + MaybeBorrowedLocals::all_borrows().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint(); let mut borrowed_locals_cursor = ResultsCursor::new(body_ref, &borrowed_locals_results); diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 16edb7d552b..6176cf8bc0f 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -45,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let flow_def_inits = DefinitelyInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body, def_id) .iterate_to_fixpoint(); - let flow_mut_borrowed = MaybeMutBorrowedLocals::new_mut_only(tcx, body, param_env) + let flow_mut_borrowed = MaybeMutBorrowedLocals::mut_borrows_only(tcx, body, param_env) .into_engine(tcx, body, def_id) .iterate_to_fixpoint(); From 0984639348c2fc98389746f6815e576cfcaacda8 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 13:57:01 -0800 Subject: [PATCH 0135/1250] Ignore mut borrow from drop terminator in const-eval --- .../dataflow/impls/borrowed_locals.rs | 45 ++++++++++++++----- .../transform/check_consts/validation.rs | 6 +++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 20aab8b32a5..0ce37aea69d 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -22,13 +22,14 @@ pub type MaybeMutBorrowedLocals<'mir, 'tcx> = MaybeBorrowedLocals { kind: K, + ignore_borrow_on_drop: bool, } impl MaybeBorrowedLocals { /// A dataflow analysis that records whether a pointer or reference exists that may alias the /// given local. pub fn all_borrows() -> Self { - MaybeBorrowedLocals { kind: AnyBorrow } + MaybeBorrowedLocals { kind: AnyBorrow, ignore_borrow_on_drop: false } } } @@ -43,13 +44,37 @@ impl MaybeMutBorrowedLocals<'mir, 'tcx> { body: &'mir mir::Body<'tcx>, param_env: ParamEnv<'tcx>, ) -> Self { - MaybeBorrowedLocals { kind: MutBorrow { body, tcx, param_env } } + MaybeBorrowedLocals { + kind: MutBorrow { body, tcx, param_env }, + ignore_borrow_on_drop: false, + } } } impl MaybeBorrowedLocals { + /// During dataflow analysis, ignore the borrow that may occur when a place is dropped. + /// + /// Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` as a + /// parameter. In the general case, a drop impl could launder that reference into the + /// surrounding environment through a raw pointer, thus creating a valid `*mut` pointing to the + /// dropped local. We are not yet willing to declare this particular case UB, so we must treat + /// all dropped locals as mutably borrowed for now. See discussion on [#61069]. + /// + /// In some contexts, we know that this borrow will never occur. For example, during + /// const-eval, custom drop glue cannot be run. Code that calls this should document the + /// assumptions that justify `Drop` terminators in this way. + /// + /// [#61069]: https://github.com/rust-lang/rust/pull/61069 + pub fn unsound_ignore_borrow_on_drop(self) -> Self { + MaybeBorrowedLocals { ignore_borrow_on_drop: true, ..self } + } + fn transfer_function<'a, T>(&'a self, trans: &'a mut T) -> TransferFunction<'a, T, K> { - TransferFunction { kind: &self.kind, trans } + TransferFunction { + kind: &self.kind, + trans, + ignore_borrow_on_drop: self.ignore_borrow_on_drop, + } } } @@ -112,6 +137,7 @@ impl BottomValue for MaybeBorrowedLocals { struct TransferFunction<'a, T, K> { trans: &'a mut T, kind: &'a K, + ignore_borrow_on_drop: bool, } impl Visitor<'tcx> for TransferFunction<'a, T, K> @@ -162,17 +188,12 @@ where self.super_terminator(terminator, location); match terminator.kind { - // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut self` - // as a parameter. Hypothetically, a drop impl could launder that reference into the - // surrounding environment through a raw pointer, thus creating a valid `*mut` pointing - // to the dropped local. We are not yet willing to declare this particular case UB, so - // we must treat all dropped locals as mutably borrowed for now. See discussion on - // [#61069]. - // - // [#61069]: https://github.com/rust-lang/rust/pull/61069 mir::TerminatorKind::Drop { location: dropped_place, .. } | mir::TerminatorKind::DropAndReplace { location: dropped_place, .. } => { - self.trans.gen(dropped_place.local); + // See documentation for `unsound_ignore_borrow_on_drop` for an explanation. + if !self.ignore_borrow_on_drop { + self.trans.gen(dropped_place.local); + } } TerminatorKind::Abort diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index d9e179ad42a..d4fa2b10152 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -141,7 +141,13 @@ impl Validator<'a, 'mir, 'tcx> { let needs_drop = QualifCursor::new(NeedsDrop, item); let has_mut_interior = QualifCursor::new(HasMutInterior, item); + // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not + // allowed in a const. + // + // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this + // without breaking stable code? let indirectly_mutable = MaybeMutBorrowedLocals::mut_borrows_only(tcx, *body, param_env) + .unsound_ignore_borrow_on_drop() .into_engine(tcx, *body, def_id) .iterate_to_fixpoint() .into_results_cursor(*body); From dbd8220891d229f9092e623b8a1dcadbddeb12fc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 5 Feb 2020 09:44:03 +1100 Subject: [PATCH 0136/1250] Avoid `base_parser`, it's not needed. --- src/librustc_expand/mbe/macro_rules.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 9e6edee265c..da4309c3b3d 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -191,9 +191,9 @@ fn generic_extension<'cx>( let mut best_failure: Option<(Token, &str)> = None; // We create a base parser that can be used for the "black box" parts. - // Every iteration needs a fresh copy of that base parser. However, the - // parser is not mutated on many of the iterations, particularly when - // dealing with macros like this: + // Every iteration needs a fresh copy of that parser. However, the parser + // is not mutated on many of the iterations, particularly when dealing with + // macros like this: // // macro_rules! foo { // ("a") => (A); @@ -209,11 +209,9 @@ fn generic_extension<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let base_parser = base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); for (i, lhs) in lhses.iter().enumerate() { - let mut parser = Cow::Borrowed(&base_parser); - // try each arm's matchers let lhs_tt = match *lhs { mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], @@ -226,7 +224,7 @@ fn generic_extension<'cx>( // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. let mut gated_spans_snaphot = mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); - match parse_tt(&mut parser, lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. @@ -293,7 +291,7 @@ fn generic_extension<'cx>( // Restore to the state before snapshotting and maybe try again. mem::swap(&mut gated_spans_snaphot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); } - drop(base_parser); + drop(parser); let (token, label) = best_failure.expect("ran no matchers"); let span = token.span.substitute_dummy(sp); @@ -311,9 +309,8 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - let base_parser = - base_parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); - match parse_tt(&mut Cow::Borrowed(&base_parser), lhs_tt) { + let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -395,8 +392,8 @@ pub fn compile_declarative_macro( ), ]; - let base_parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); - let argument_map = match parse_tt(&mut Cow::Borrowed(&base_parser), &argument_gram) { + let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); + let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { Success(m) => m, Failure(token, msg) => { let s = parse_failure_msg(&token); @@ -1212,7 +1209,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn base_parser_from_cx<'cx>( +fn parser_from_cx<'cx>( current_expansion: &'cx ExpansionData, sess: &'cx ParseSess, tts: TokenStream, From 88b0912d27afa0fa2f9593c3c7545207127ff91c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 11 Feb 2020 08:44:55 +1100 Subject: [PATCH 0137/1250] Fix a typo in a variable name. --- src/librustc_expand/mbe/macro_rules.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index da4309c3b3d..f6abcce4d3f 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -222,13 +222,14 @@ fn generic_extension<'cx>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snaphot = mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = + mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. - cx.parse_sess.gated_spans.merge(gated_spans_snaphot); + cx.parse_sess.gated_spans.merge(gated_spans_snapshot); let rhs = match rhses[i] { // ignore delimiters @@ -289,7 +290,7 @@ fn generic_extension<'cx>( // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snaphot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); } drop(parser); From 668d2fe807068073647f9c92d81ff0e7b9ab8486 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 15:58:56 -0800 Subject: [PATCH 0138/1250] Update line # in test output --- src/test/ui/mir-dataflow/indirect-mutation-offset.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr index 0ae9a40c96a..8d3548ececd 100644 --- a/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr +++ b/src/test/ui/mir-dataflow/indirect-mutation-offset.stderr @@ -1,5 +1,5 @@ error: rustc_peek: bit not set - --> $DIR/indirect-mutation-offset.rs:34:14 + --> $DIR/indirect-mutation-offset.rs:41:14 | LL | unsafe { rustc_peek(x) }; | ^^^^^^^^^^^^^ From a64cd592247b0029352b57a7caf038e6d2ba6a05 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 24 Jan 2020 15:30:51 -0800 Subject: [PATCH 0139/1250] Add `Place` getter to `Operand` --- src/librustc/mir/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index f6c7174649f..d3a6ff654d6 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1993,6 +1993,15 @@ impl<'tcx> Operand<'tcx> { Operand::Move(place) => Operand::Copy(place), } } + + /// Returns the `Place` that is the target of this `Operand`, or `None` if this `Operand` is a + /// constant. + pub fn place(&self) -> Option<&Place<'tcx>> { + match self { + Operand::Copy(place) | Operand::Move(place) => Some(place), + Operand::Constant(_) => None, + } + } } /////////////////////////////////////////////////////////////////////////// From ce56f622b4cea033ef339461db46a2ab61d29d13 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 24 Jan 2020 12:38:51 -0800 Subject: [PATCH 0140/1250] Use an `Iterator` for `MovePath` traversal --- .../diagnostics/conflict_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 7 ++- src/librustc_mir/borrow_check/nll.rs | 2 +- src/librustc_mir/dataflow/move_paths/mod.rs | 52 +++++++++++++++---- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index c7c7db9ad80..4f83a660f5c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1350,7 +1350,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // there. let mut mpis = vec![mpi]; let move_paths = &self.move_data.move_paths; - mpis.extend(move_paths[mpi].parents(move_paths)); + mpis.extend(move_paths[mpi].parents(move_paths).map(|(mpi, _)| mpi)); for moi in &self.move_data.loc_map[location] { debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 88173137bd2..03871984e40 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1582,9 +1582,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { if let Some(mpi) = self.move_path_for_place(place_span.0) { let move_paths = &self.move_data.move_paths; - let mut child = move_paths[mpi].first_child; - while let Some(child_mpi) = child { - let child_move_path = &move_paths[child_mpi]; + + let root_path = &move_paths[mpi]; + for (child_mpi, child_move_path) in root_path.children(move_paths) { let last_proj = child_move_path.place.projection.last().unwrap(); if let ProjectionElem::ConstantIndex { offset, from_end, .. } = last_proj { debug_assert!(!from_end, "Array constant indexing shouldn't be `from_end`."); @@ -1606,7 +1606,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } } - child = child_move_path.next_sibling; } } } diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index a71dfc9a778..1fcd5aefb3e 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -90,7 +90,7 @@ fn populate_polonius_move_facts( for (child, move_path) in move_data.move_paths.iter_enumerated() { all_facts .child - .extend(move_path.parents(&move_data.move_paths).iter().map(|&parent| (child, parent))); + .extend(move_path.parents(&move_data.move_paths).map(|(parent, _)| (child, parent))); } // initialized_at diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 614a2761643..6f6ba7dc271 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -58,19 +58,32 @@ pub struct MovePath<'tcx> { } impl<'tcx> MovePath<'tcx> { - pub fn parents( + /// Returns an iterator over the parents of `self`. + pub fn parents<'a>( &self, - move_paths: &IndexVec>, - ) -> Vec { - let mut parents = Vec::new(); - - let mut curr_parent = self.parent; - while let Some(parent_mpi) = curr_parent { - parents.push(parent_mpi); - curr_parent = move_paths[parent_mpi].parent; + move_paths: &'a IndexVec>, + ) -> impl 'a + Iterator)> { + let first = self.parent.map(|mpi| (mpi, &move_paths[mpi])); + MovePathLinearIter { + next: first, + fetch_next: move |_, parent: &MovePath<'_>| { + parent.parent.map(|mpi| (mpi, &move_paths[mpi])) + }, } + } - parents + /// Returns an iterator over the immediate children of `self`. + pub fn children<'a>( + &self, + move_paths: &'a IndexVec>, + ) -> impl 'a + Iterator)> { + let first = self.first_child.map(|mpi| (mpi, &move_paths[mpi])); + MovePathLinearIter { + next: first, + fetch_next: move |_, child: &MovePath<'_>| { + child.next_sibling.map(|mpi| (mpi, &move_paths[mpi])) + }, + } } /// Finds the closest descendant of `self` for which `f` returns `true` using a breadth-first @@ -131,6 +144,25 @@ impl<'tcx> fmt::Display for MovePath<'tcx> { } } +#[allow(unused)] +struct MovePathLinearIter<'a, 'tcx, F> { + next: Option<(MovePathIndex, &'a MovePath<'tcx>)>, + fetch_next: F, +} + +impl<'a, 'tcx, F> Iterator for MovePathLinearIter<'a, 'tcx, F> +where + F: FnMut(MovePathIndex, &'a MovePath<'tcx>) -> Option<(MovePathIndex, &'a MovePath<'tcx>)>, +{ + type Item = (MovePathIndex, &'a MovePath<'tcx>); + + fn next(&mut self) -> Option { + let ret = self.next.take()?; + self.next = (self.fetch_next)(ret.0, ret.1); + Some(ret) + } +} + #[derive(Debug)] pub struct MoveData<'tcx> { pub move_paths: IndexVec>, From 99b96199a6f47a8ff97c0df8dda849b5f6f58abf Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 20 Jan 2020 19:15:23 -0800 Subject: [PATCH 0141/1250] Support effects for particular edges of `SwitchInt` --- src/librustc_mir/dataflow/generic/engine.rs | 75 +++++++++++++++++++-- src/librustc_mir/dataflow/generic/mod.rs | 42 +++++++++++- 2 files changed, 110 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index b81f0adc201..d41ef2a392c 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -5,7 +5,7 @@ use std::fs; use std::path::PathBuf; use rustc::mir::{self, traversal, BasicBlock, Location}; -use rustc::ty::TyCtxt; +use rustc::ty::{self, TyCtxt}; use rustc_data_structures::work_queue::WorkQueue; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; @@ -238,10 +238,15 @@ where } } - SwitchInt { ref targets, .. } => { - for target in targets { - self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list); - } + SwitchInt { ref targets, ref values, ref discr, .. } => { + self.propagate_bits_into_switch_int_successors( + in_out, + (bb, bb_data), + dirty_list, + discr, + &*values, + &*targets, + ); } Call { cleanup, ref destination, ref func, ref args, .. } => { @@ -287,6 +292,66 @@ where dirty_queue.insert(bb); } } + + fn propagate_bits_into_switch_int_successors( + &mut self, + in_out: &mut BitSet, + (bb, bb_data): (BasicBlock, &mir::BasicBlockData<'tcx>), + dirty_list: &mut WorkQueue, + switch_on: &mir::Operand<'tcx>, + values: &[u128], + targets: &[BasicBlock], + ) { + match bb_data.statements.last().map(|stmt| &stmt.kind) { + // Look at the last statement to see if it is an assignment of an enum discriminant to + // the local that determines the target of a `SwitchInt` like so: + // _42 = discriminant(..) + // SwitchInt(_42, ..) + Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(enum_)))) + if Some(lhs) == switch_on.place() => + { + let adt = match enum_.ty(self.body, self.tcx).ty.kind { + ty::Adt(def, _) => def, + _ => bug!("Switch on discriminant of non-ADT"), + }; + + // MIR building adds discriminants to the `values` array in the same order as they + // are yielded by `AdtDef::discriminants`. We rely on this to match each + // discriminant in `values` to its corresponding variant in linear time. + let mut tmp = BitSet::new_empty(in_out.domain_size()); + let mut discriminants = adt.discriminants(self.tcx); + for (value, target) in values.iter().zip(targets.iter().copied()) { + let (variant_idx, _) = + discriminants.find(|&(_, discr)| discr.val == *value).expect( + "Order of `AdtDef::discriminants` differed \ + from that of `SwitchInt::values`", + ); + + tmp.overwrite(in_out); + self.analysis.apply_discriminant_switch_effect( + &mut tmp, + bb, + enum_, + adt, + variant_idx, + ); + self.propagate_bits_into_entry_set_for(&tmp, target, dirty_list); + } + + std::mem::drop(tmp); + + // Propagate dataflow state along the "otherwise" edge. + let otherwise = targets.last().copied().unwrap(); + self.propagate_bits_into_entry_set_for(&in_out, otherwise, dirty_list); + } + + _ => { + for target in targets.iter().copied() { + self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list); + } + } + } + } } // Graphviz diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index ea643042c5f..0f606240aeb 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -35,7 +35,8 @@ use std::io; use rustc::mir::{self, BasicBlock, Location}; -use rustc::ty::TyCtxt; +use rustc::ty::layout::VariantIdx; +use rustc::ty::{self, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_index::vec::{Idx, IndexVec}; @@ -172,7 +173,22 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { return_place: &mir::Place<'tcx>, ); - /// Calls the appropriate `Engine` constructor to find the fixpoint for this dataflow problem. + /// Updates the current dataflow state with the effect of taking a particular branch in a + /// `SwitchInt` terminator. + /// + /// Much like `apply_call_return_effect`, this effect is only propagated along a single + /// outgoing edge from this basic block. + fn apply_discriminant_switch_effect( + &self, + _state: &mut BitSet, + _block: BasicBlock, + _enum_place: &mir::Place<'tcx>, + _adt: &ty::AdtDef, + _variant: VariantIdx, + ) { + } + + /// Creates an `Engine` to find the fixpoint for this dataflow problem. /// /// You shouldn't need to override this outside this module, since the combination of the /// default impl and the one for all `A: GenKillAnalysis` will do the right thing. @@ -249,6 +265,17 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ); + + /// See `Analysis::apply_discriminant_switch_effect`. + fn discriminant_switch_effect( + &self, + _state: &mut impl GenKill, + _block: BasicBlock, + _enum_place: &mir::Place<'tcx>, + _adt: &ty::AdtDef, + _variant: VariantIdx, + ) { + } } impl Analysis<'tcx> for A @@ -302,6 +329,17 @@ where self.call_return_effect(state, block, func, args, return_place); } + fn apply_discriminant_switch_effect( + &self, + state: &mut BitSet, + block: BasicBlock, + enum_place: &mir::Place<'tcx>, + adt: &ty::AdtDef, + variant: VariantIdx, + ) { + self.discriminant_switch_effect(state, block, enum_place, adt, variant); + } + fn into_engine( self, tcx: TyCtxt<'tcx>, From e2c80477532b54271cbb7249d0bb36d7b257fca2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 24 Jan 2020 15:32:22 -0800 Subject: [PATCH 0142/1250] Kill move paths of dead variants --- src/librustc_mir/dataflow/impls/mod.rs | 37 ++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 5b2264c2a65..bd710bc429a 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -3,7 +3,8 @@ //! zero-sized structure. use rustc::mir::{self, Body, Location}; -use rustc::ty::TyCtxt; +use rustc::ty::layout::VariantIdx; +use rustc::ty::{self, TyCtxt}; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; @@ -12,12 +13,13 @@ use super::MoveDataParamEnv; use crate::util::elaborate_drops::DropFlagState; use super::generic::{AnalysisDomain, GenKill, GenKillAnalysis}; -use super::move_paths::{HasMoveData, InitIndex, InitKind, MoveData, MovePathIndex}; +use super::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; use super::{BottomValue, GenKillSet}; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; use super::on_lookup_result_bits; +use crate::dataflow::drop_flag_effects; mod borrowed_locals; mod indirect_mutation; @@ -338,6 +340,37 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeInitializedPlaces<'_, 'tcx> { }, ); } + + fn discriminant_switch_effect( + &self, + trans: &mut impl GenKill, + _block: mir::BasicBlock, + enum_place: &mir::Place<'tcx>, + _adt: &ty::AdtDef, + variant: VariantIdx, + ) { + let enum_mpi = match self.move_data().rev_lookup.find(enum_place.as_ref()) { + LookupResult::Exact(mpi) => mpi, + LookupResult::Parent(_) => return, + }; + + // Kill all move paths that correspond to variants other than this one + let move_paths = &self.move_data().move_paths; + let enum_path = &move_paths[enum_mpi]; + for (mpi, variant_path) in enum_path.children(move_paths) { + trans.kill(mpi); + match variant_path.place.projection.last().unwrap() { + mir::ProjectionElem::Downcast(_, idx) if *idx == variant => continue, + _ => drop_flag_effects::on_all_children_bits( + self.tcx, + self.body, + self.move_data(), + mpi, + |mpi| trans.kill(mpi), + ), + } + } + } } impl<'tcx> AnalysisDomain<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> { From 95186201724a087bacafc74317722314f203cfdc Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 21 Jan 2020 20:00:55 -0800 Subject: [PATCH 0143/1250] Use `ResultsCursor` for `elaborate_drops` The old code hard-coded the transfer function for the initialized places analyses. --- src/librustc_mir/transform/elaborate_drops.rs | 114 +++++------------- 1 file changed, 33 insertions(+), 81 deletions(-) diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 99f13f68cbc..28a50547b19 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -1,8 +1,8 @@ use crate::dataflow; -use crate::dataflow::generic::{Analysis, Results}; +use crate::dataflow::generic::{Analysis, ResultsCursor}; use crate::dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; +use crate::dataflow::on_lookup_result_bits; use crate::dataflow::MoveDataParamEnv; -use crate::dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits}; use crate::dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use crate::transform::{MirPass, MirSource}; @@ -41,22 +41,23 @@ impl<'tcx> MirPass<'tcx> for ElaborateDrops { let env = MoveDataParamEnv { move_data, param_env }; let dead_unwinds = find_dead_unwinds(tcx, body, def_id, &env); - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &env) + let inits = MaybeInitializedPlaces::new(tcx, body, &env) .into_engine(tcx, body, def_id) .dead_unwinds(&dead_unwinds) - .iterate_to_fixpoint(); + .iterate_to_fixpoint() + .into_results_cursor(body); - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &env) + let uninits = MaybeUninitializedPlaces::new(tcx, body, &env) .into_engine(tcx, body, def_id) .dead_unwinds(&dead_unwinds) - .iterate_to_fixpoint(); + .iterate_to_fixpoint() + .into_results_cursor(body); ElaborateDropsCtxt { tcx, body, env: &env, - flow_inits, - flow_uninits, + init_data: InitializationData { inits, uninits }, drop_flags: Default::default(), patch: MirPatch::new(body), } @@ -79,9 +80,10 @@ fn find_dead_unwinds<'tcx>( // We only need to do this pass once, because unwind edges can only // reach cleanup blocks, which can't have unwind edges themselves. let mut dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &env) + let mut flow_inits = MaybeInitializedPlaces::new(tcx, body, &env) .into_engine(tcx, body, def_id) - .iterate_to_fixpoint(); + .iterate_to_fixpoint() + .into_results_cursor(body); for (bb, bb_data) in body.basic_blocks().iter_enumerated() { let location = match bb_data.terminator().kind { TerminatorKind::Drop { ref location, unwind: Some(_), .. } @@ -89,15 +91,7 @@ fn find_dead_unwinds<'tcx>( _ => continue, }; - let mut init_data = InitializationData { - live: flow_inits.entry_set_for_block(bb).clone(), - dead: BitSet::new_empty(env.move_data.move_paths.len()), - }; - debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}", bb, bb_data, init_data.live); - for stmt in 0..bb_data.statements.len() { - let loc = Location { block: bb, statement_index: stmt }; - init_data.apply_location(tcx, body, env, loc); - } + debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}", bb, bb_data, flow_inits.get()); let path = match env.move_data.rev_lookup.find(location.as_ref()) { LookupResult::Exact(e) => e, @@ -109,10 +103,10 @@ fn find_dead_unwinds<'tcx>( debug!("find_dead_unwinds @ {:?}: path({:?})={:?}", bb, location, path); + flow_inits.seek_after(body.terminator_loc(bb)); let mut maybe_live = false; on_all_drop_children_bits(tcx, body, &env, path, |child| { - let (child_maybe_live, _) = init_data.state(child); - maybe_live |= child_maybe_live; + maybe_live |= flow_inits.contains(child); }); debug!("find_dead_unwinds @ {:?}: maybe_live={}", bb, maybe_live); @@ -124,41 +118,23 @@ fn find_dead_unwinds<'tcx>( dead_unwinds } -struct InitializationData { - live: BitSet, - dead: BitSet, +struct InitializationData<'mir, 'tcx> { + inits: ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>, + uninits: ResultsCursor<'mir, 'tcx, MaybeUninitializedPlaces<'mir, 'tcx>>, } -impl InitializationData { - fn apply_location<'tcx>( - &mut self, - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - env: &MoveDataParamEnv<'tcx>, - loc: Location, - ) { - drop_flag_effects_for_location(tcx, body, env, loc, |path, df| { - debug!("at location {:?}: setting {:?} to {:?}", loc, path, df); - match df { - DropFlagState::Present => { - self.live.insert(path); - self.dead.remove(path); - } - DropFlagState::Absent => { - self.dead.insert(path); - self.live.remove(path); - } - } - }); +impl InitializationData<'_, '_> { + fn seek_after(&mut self, loc: Location) { + self.inits.seek_after(loc); + self.uninits.seek_after(loc); } fn state(&self, path: MovePathIndex) -> (bool, bool) { - (self.live.contains(path), self.dead.contains(path)) + (self.inits.contains(path), self.uninits.contains(path)) } } struct Elaborator<'a, 'b, 'tcx> { - init_data: &'a InitializationData, ctxt: &'a mut ElaborateDropsCtxt<'b, 'tcx>, } @@ -189,13 +165,13 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { - DropFlagMode::Shallow => (self.init_data.state(path), false), + DropFlagMode::Shallow => (self.ctxt.init_data.state(path), false), DropFlagMode::Deep => { let mut some_live = false; let mut some_dead = false; let mut children_count = 0; on_all_drop_children_bits(self.tcx(), self.body(), self.ctxt.env, path, |child| { - let (live, dead) = self.init_data.state(child); + let (live, dead) = self.ctxt.init_data.state(child); debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); some_live |= live; some_dead |= dead; @@ -269,8 +245,7 @@ struct ElaborateDropsCtxt<'a, 'tcx> { tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, env: &'a MoveDataParamEnv<'tcx>, - flow_inits: Results<'tcx, MaybeInitializedPlaces<'a, 'tcx>>, - flow_uninits: Results<'tcx, MaybeUninitializedPlaces<'a, 'tcx>>, + init_data: InitializationData<'a, 'tcx>, drop_flags: FxHashMap, patch: MirPatch<'tcx>, } @@ -284,25 +259,6 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { self.env.param_env } - // FIXME(ecstaticmorse): This duplicates `dataflow::ResultsCursor` but hardcodes the transfer - // function for `Maybe{Un,}InitializedPlaces` directly. It should be replaced by a a pair of - // `ResultsCursor`s. - fn initialization_data_at(&self, loc: Location) -> InitializationData { - let mut data = InitializationData { - live: self.flow_inits.entry_set_for_block(loc.block).to_owned(), - dead: self.flow_uninits.entry_set_for_block(loc.block).to_owned(), - }; - for stmt in 0..loc.statement_index { - data.apply_location( - self.tcx, - self.body, - self.env, - Location { block: loc.block, statement_index: stmt }, - ); - } - data - } - fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) { let tcx = self.tcx; let patch = &mut self.patch; @@ -338,10 +294,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { _ => continue, }; - let init_data = self.initialization_data_at(Location { - block: bb, - statement_index: data.statements.len(), - }); + self.init_data.seek_after(self.body.terminator_loc(bb)); let path = self.move_data().rev_lookup.find(location.as_ref()); debug!("collect_drop_flags: {:?}, place {:?} ({:?})", bb, location, path); @@ -350,7 +303,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { LookupResult::Exact(e) => e, LookupResult::Parent(None) => continue, LookupResult::Parent(Some(parent)) => { - let (_maybe_live, maybe_dead) = init_data.state(parent); + let (_maybe_live, maybe_dead) = self.init_data.state(parent); if maybe_dead { span_bug!( terminator.source_info.span, @@ -365,7 +318,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { }; on_all_drop_children_bits(self.tcx, self.body, self.env, path, |child| { - let (maybe_live, maybe_dead) = init_data.state(child); + let (maybe_live, maybe_dead) = self.init_data.state(child); debug!( "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", child, @@ -388,10 +341,10 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let resume_block = self.patch.resume_block(); match terminator.kind { TerminatorKind::Drop { ref location, target, unwind } => { - let init_data = self.initialization_data_at(loc); + self.init_data.seek_after(loc); match self.move_data().rev_lookup.find(location.as_ref()) { LookupResult::Exact(path) => elaborate_drop( - &mut Elaborator { init_data: &init_data, ctxt: self }, + &mut Elaborator { ctxt: self }, terminator.source_info, location, path, @@ -471,10 +424,9 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { match self.move_data().rev_lookup.find(location.as_ref()) { LookupResult::Exact(path) => { debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path); - let init_data = self.initialization_data_at(loc); - + self.init_data.seek_after(loc); elaborate_drop( - &mut Elaborator { init_data: &init_data, ctxt: self }, + &mut Elaborator { ctxt: self }, terminator.source_info, location, path, From f0260ae196b62f27c64738d52519efb424724915 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 20:48:17 -0800 Subject: [PATCH 0144/1250] Use `seek_before` instead of `seek_after` --- src/librustc_mir/transform/elaborate_drops.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 28a50547b19..306fe14266f 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -103,7 +103,7 @@ fn find_dead_unwinds<'tcx>( debug!("find_dead_unwinds @ {:?}: path({:?})={:?}", bb, location, path); - flow_inits.seek_after(body.terminator_loc(bb)); + flow_inits.seek_before(body.terminator_loc(bb)); let mut maybe_live = false; on_all_drop_children_bits(tcx, body, &env, path, |child| { maybe_live |= flow_inits.contains(child); @@ -124,9 +124,9 @@ struct InitializationData<'mir, 'tcx> { } impl InitializationData<'_, '_> { - fn seek_after(&mut self, loc: Location) { - self.inits.seek_after(loc); - self.uninits.seek_after(loc); + fn seek_before(&mut self, loc: Location) { + self.inits.seek_before(loc); + self.uninits.seek_before(loc); } fn state(&self, path: MovePathIndex) -> (bool, bool) { @@ -294,7 +294,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { _ => continue, }; - self.init_data.seek_after(self.body.terminator_loc(bb)); + self.init_data.seek_before(self.body.terminator_loc(bb)); let path = self.move_data().rev_lookup.find(location.as_ref()); debug!("collect_drop_flags: {:?}, place {:?} ({:?})", bb, location, path); @@ -341,7 +341,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let resume_block = self.patch.resume_block(); match terminator.kind { TerminatorKind::Drop { ref location, target, unwind } => { - self.init_data.seek_after(loc); + self.init_data.seek_before(loc); match self.move_data().rev_lookup.find(location.as_ref()) { LookupResult::Exact(path) => elaborate_drop( &mut Elaborator { ctxt: self }, @@ -424,7 +424,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { match self.move_data().rev_lookup.find(location.as_ref()) { LookupResult::Exact(path) => { debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path); - self.init_data.seek_after(loc); + self.init_data.seek_before(loc); elaborate_drop( &mut Elaborator { ctxt: self }, terminator.source_info, From 2aa39350d3dde13f5e82f24d42a51cbfe92f723e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 21:30:10 -0800 Subject: [PATCH 0145/1250] Use more descriptive name to get `InitializationData` state --- src/librustc_mir/transform/elaborate_drops.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 306fe14266f..a4531e53ce1 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -129,7 +129,7 @@ impl InitializationData<'_, '_> { self.uninits.seek_before(loc); } - fn state(&self, path: MovePathIndex) -> (bool, bool) { + fn maybe_live_dead(&self, path: MovePathIndex) -> (bool, bool) { (self.inits.contains(path), self.uninits.contains(path)) } } @@ -165,13 +165,13 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { fn drop_style(&self, path: Self::Path, mode: DropFlagMode) -> DropStyle { let ((maybe_live, maybe_dead), multipart) = match mode { - DropFlagMode::Shallow => (self.ctxt.init_data.state(path), false), + DropFlagMode::Shallow => (self.ctxt.init_data.maybe_live_dead(path), false), DropFlagMode::Deep => { let mut some_live = false; let mut some_dead = false; let mut children_count = 0; on_all_drop_children_bits(self.tcx(), self.body(), self.ctxt.env, path, |child| { - let (live, dead) = self.ctxt.init_data.state(child); + let (live, dead) = self.ctxt.init_data.maybe_live_dead(child); debug!("elaborate_drop: state({:?}) = {:?}", child, (live, dead)); some_live |= live; some_dead |= dead; @@ -303,7 +303,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { LookupResult::Exact(e) => e, LookupResult::Parent(None) => continue, LookupResult::Parent(Some(parent)) => { - let (_maybe_live, maybe_dead) = self.init_data.state(parent); + let (_maybe_live, maybe_dead) = self.init_data.maybe_live_dead(parent); if maybe_dead { span_bug!( terminator.source_info.span, @@ -318,7 +318,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { }; on_all_drop_children_bits(self.tcx, self.body, self.env, path, |child| { - let (maybe_live, maybe_dead) = self.init_data.state(child); + let (maybe_live, maybe_dead) = self.init_data.maybe_live_dead(child); debug!( "collect_drop_flags: collecting {:?} from {:?}@{:?} - {:?}", child, From 26451d007e7482f0c4cdae152a972f4e7c8bf970 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 21:34:19 -0800 Subject: [PATCH 0146/1250] Print flow state in debug messages for `find_dead_unwinds` --- src/librustc_mir/transform/elaborate_drops.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index a4531e53ce1..5d02074aaaa 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -91,7 +91,7 @@ fn find_dead_unwinds<'tcx>( _ => continue, }; - debug!("find_dead_unwinds @ {:?}: {:?}; init_data={:?}", bb, bb_data, flow_inits.get()); + debug!("find_dead_unwinds @ {:?}: {:?}", bb, bb_data); let path = match env.move_data.rev_lookup.find(location.as_ref()) { LookupResult::Exact(e) => e, @@ -101,9 +101,15 @@ fn find_dead_unwinds<'tcx>( } }; - debug!("find_dead_unwinds @ {:?}: path({:?})={:?}", bb, location, path); - flow_inits.seek_before(body.terminator_loc(bb)); + debug!( + "find_dead_unwinds @ {:?}: path({:?})={:?}; init_data={:?}", + bb, + location, + path, + flow_inits.get() + ); + let mut maybe_live = false; on_all_drop_children_bits(tcx, body, &env, path, |child| { maybe_live |= flow_inits.contains(child); From 5c473a059e26614b65414cfb8cf75c283cda5a87 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 13 Feb 2020 15:27:54 -0800 Subject: [PATCH 0147/1250] Don't print block exit state if unchanged --- src/librustc_mir/dataflow/generic/graphviz.rs | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index b805b13592f..157526d3c51 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -195,6 +195,8 @@ where // C: Entry state self.bg = Background::Light; self.results.seek_to_block_start(block); + let block_entry_state = self.results.get().clone(); + self.write_row_with_full_state(w, "", "(on entry)")?; // D: Statement transfer functions @@ -213,29 +215,42 @@ where self.write_row_for_location(w, "T", &terminator_str, terminator_loc)?; // F: Exit state + + // Write the full dataflow state immediately after the terminator if it differs from the + // state at block entry. self.results.seek_after(terminator_loc); - if let mir::TerminatorKind::Call { destination: Some(_), .. } = &terminator.kind { - self.write_row_with_full_state(w, "", "(on unwind)")?; - - let num_state_columns = self.num_state_columns(); - self.write_row(w, "", "(on successful return)", |this, w, fmt| { - write!( - w, - r#""#, - colspan = num_state_columns, - fmt = fmt, - )?; - - let state_on_unwind = this.results.get().clone(); - this.results.seek_after_assume_call_returns(terminator_loc); - write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?; - - write!(w, "") - })?; - } else { - self.write_row_with_full_state(w, "", "(on exit)")?; + if self.results.get() != &block_entry_state { + let after_terminator_name = match terminator.kind { + mir::TerminatorKind::Call { destination: Some(_), .. } => "(on unwind)", + _ => "(on exit)", + }; + + self.write_row_with_full_state(w, "", after_terminator_name)?; } + // Write any changes caused by terminator-specific effects + match terminator.kind { + mir::TerminatorKind::Call { destination: Some(_), .. } => { + let num_state_columns = self.num_state_columns(); + self.write_row(w, "", "(on successful return)", |this, w, fmt| { + write!( + w, + r#""#, + colspan = num_state_columns, + fmt = fmt, + )?; + + let state_on_unwind = this.results.get().clone(); + this.results.seek_after_assume_call_returns(terminator_loc); + write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?; + + write!(w, "") + })?; + } + + _ => {} + }; + write!(w, "") } From cdb4a59633536d8e7f59c0b1ac9a683b196bc4db Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Feb 2020 09:41:32 +0100 Subject: [PATCH 0148/1250] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index e3cfb61ece2..ded5a52639a 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit e3cfb61ece273d59b62fb959ed17c99c04941d82 +Subproject commit ded5a52639a78907523b74a9d3ed8e3824c88ca5 From be92200af7ac732063500a96890ed0354dcc490b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 14 Feb 2020 21:49:57 +0900 Subject: [PATCH 0149/1250] Check `has_typeck_tables` before calling `typeck_tables_of` --- src/librustc_mir/const_eval/eval_queries.rs | 5 ++++- src/test/ui/consts/issue-68684.rs | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/issue-68684.rs diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 2e8e4dac237..4fdabed54b8 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -288,7 +288,10 @@ pub fn const_eval_raw_provider<'tcx>( let cid = key.value; let def_id = cid.instance.def.def_id(); - if def_id.is_local() && tcx.typeck_tables_of(def_id).tainted_by_errors { + if def_id.is_local() + && tcx.has_typeck_tables(def_id) + && tcx.typeck_tables_of(def_id).tainted_by_errors + { return Err(ErrorHandled::Reported); } diff --git a/src/test/ui/consts/issue-68684.rs b/src/test/ui/consts/issue-68684.rs new file mode 100644 index 00000000000..c98f199b60e --- /dev/null +++ b/src/test/ui/consts/issue-68684.rs @@ -0,0 +1,15 @@ +// check-pass + +enum _Enum { + A(), +} + +type _E = _Enum; + +const fn _a() -> _Enum { + _E::A() +} + +const _A: _Enum = _a(); + +fn main() {} From ea2ffda44e0c38854dbe63c786a194dd35559545 Mon Sep 17 00:00:00 2001 From: Alberto Piai Date: Fri, 14 Feb 2020 14:27:22 +0100 Subject: [PATCH 0150/1250] add regression test for issue #68794 This is a minimal regression test for the issue #68794: "TEXTREL in i686", which was fixed with e86019c4a0968a1e393cdd0731649168624a88b8. The test links a minimal rust static library into a shared library, and checks that the linker didn't have to add the TEXTREL flag. --- .../issue-68794-textrel-on-minimal-lib/Makefile | 17 +++++++++++++++++ .../issue-68794-textrel-on-minimal-lib/bar.c | 6 ++++++ .../issue-68794-textrel-on-minimal-lib/foo.rs | 8 ++++++++ 3 files changed, 31 insertions(+) create mode 100644 src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile create mode 100644 src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c create mode 100644 src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile new file mode 100644 index 00000000000..2f16ad32859 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/Makefile @@ -0,0 +1,17 @@ +# Regression test for issue #68794 +# +# Verify that no text relocations are accidentally introduced by linking a +# minimal rust staticlib. +# +# The test links a rust static library into a shared library, and checks that +# the linker doesn't have to flag the resulting file as containing TEXTRELs. + +-include ../tools.mk + +# only-linux + +all: + $(RUSTC) foo.rs + $(CC) bar.c $(call STATICLIB,foo) -fPIC -shared -o $(call DYLIB,bar) \ + $(EXTRACFLAGS) $(EXTRACXXFLAGS) + readelf -d $(call DYLIB,bar) | grep TEXTREL; test $$? -eq 1 diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c new file mode 100644 index 00000000000..bb4036b06e1 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/bar.c @@ -0,0 +1,6 @@ +void foo(); + +int main() { + foo(); + return 0; +} diff --git a/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs new file mode 100644 index 00000000000..a3e865b638e --- /dev/null +++ b/src/test/run-make-fulldeps/issue-68794-textrel-on-minimal-lib/foo.rs @@ -0,0 +1,8 @@ +#![crate_type = "staticlib"] + +#[no_mangle] +pub extern "C" fn foo(x: u32) { + // using the println! makes it so that enough code from the standard + // library is included (see issue #68794) + println!("foo: {}", x); +} From 033bd8c7af79d362b4e861543b63991e7300948f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 21:13:51 +0000 Subject: [PATCH 0151/1250] Explain a test --- .../impl-trait/multiple-lifetimes/error-handling.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs index b226cf058aa..8fb4794e891 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs @@ -12,10 +12,17 @@ type E<'a, 'b> = impl Sized; fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { //~^ ERROR lifetime may not live long enough - let v = CopyIfEq::<*mut _, *mut _>(&mut {x}, &mut y); + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. let u = v; let _: *mut &'a i32 = u.1; - unsafe { let _: &'b i32 = *u.0; } + unsafe { + let _: &'b i32 = *u.0; + } u.0 } From 7f41cf4cef551d887de539842d11945b6bfaa8b6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 23:41:32 +0000 Subject: [PATCH 0152/1250] Check associated opaque types don't use unconstrained lifetimes --- src/librustc_typeck/impl_wf_check.rs | 18 ++++++++++--- .../type-alias-impl-trait/assoc-type-const.rs | 12 ++++----- .../assoc-type-lifetime-unconstrained.rs | 26 +++++++++++++++++++ .../assoc-type-lifetime-unconstrained.stderr | 9 +++++++ .../assoc-type-lifetime.rs | 6 ++--- 5 files changed, 57 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs create mode 100644 src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index e9c18b59da9..0b4b8a49054 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -120,11 +120,23 @@ fn enforce_impl_params_are_constrained( let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs .iter() .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id)) - .filter(|&def_id| { + .flat_map(|def_id| { let item = tcx.associated_item(def_id); - item.kind == ty::AssocKind::Type && item.defaultness.has_value() + match item.kind { + ty::AssocKind::Type => { + if item.defaultness.has_value() { + cgp::parameters_for(&tcx.type_of(def_id), true) + } else { + Vec::new() + } + } + ty::AssocKind::OpaqueTy => { + let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx); + cgp::parameters_for(&predicates, true) + } + ty::AssocKind::Method | ty::AssocKind::Const => Vec::new(), + } }) - .flat_map(|def_id| cgp::parameters_for(&tcx.type_of(def_id), true)) .collect(); for param in &impl_generics.params { diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs index 5db677d82e2..2907c21c620 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs +++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs @@ -6,7 +6,7 @@ #![feature(const_generics)] //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash -trait UnwrapItemsExt { +trait UnwrapItemsExt<'a, const C: usize> { type Iter; fn unwrap_items(self) -> Self::Iter; } @@ -18,18 +18,16 @@ trait MyTrait<'a, const C: usize> { const MY_CONST: usize; } -impl<'a, const C: usize> MyTrait<'a, {C}> for MyStruct<{C}> { +impl<'a, const C: usize> MyTrait<'a, { C }> for MyStruct<{ C }> { type MyItem = u8; const MY_CONST: usize = C; } -impl<'a, I, const C: usize> UnwrapItemsExt<{C}> for I -where -{ - type Iter = impl MyTrait<'a, {C}>; +impl<'a, I, const C: usize> UnwrapItemsExt<'a, { C }> for I { + type Iter = impl MyTrait<'a, { C }>; fn unwrap_items(self) -> Self::Iter { - MyStruct::<{C}> {} + MyStruct::<{ C }> {} } } diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs new file mode 100644 index 00000000000..3f34b00ec77 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs @@ -0,0 +1,26 @@ +// Tests that we don't allow unconstrained lifetime parameters in impls when +// the lifetime is used in an associated opaque type. + +#![feature(type_alias_impl_trait)] + +trait UnwrapItemsExt { + type Iter; + fn unwrap_items(self) -> Self::Iter; +} + +struct MyStruct {} + +trait MyTrait<'a> {} + +impl<'a> MyTrait<'a> for MyStruct {} + +impl<'a, I> UnwrapItemsExt for I { + //~^ ERROR the lifetime parameter `'a` is not constrained + type Iter = impl MyTrait<'a>; + + fn unwrap_items(self) -> Self::Iter { + MyStruct {} + } +} + +fn main() {} diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr new file mode 100644 index 00000000000..e594dc577b1 --- /dev/null +++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr @@ -0,0 +1,9 @@ +error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates + --> $DIR/assoc-type-lifetime-unconstrained.rs:17:6 + | +LL | impl<'a, I> UnwrapItemsExt for I { + | ^^ unconstrained lifetime parameter + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0207`. diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs index cff1d24494e..39f785d8cc5 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs +++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs @@ -4,7 +4,7 @@ #![feature(type_alias_impl_trait)] -trait UnwrapItemsExt { +trait UnwrapItemsExt<'a> { type Iter; fn unwrap_items(self) -> Self::Iter; } @@ -15,9 +15,7 @@ trait MyTrait<'a> {} impl<'a> MyTrait<'a> for MyStruct {} -impl<'a, I> UnwrapItemsExt for I -where -{ +impl<'a, I> UnwrapItemsExt<'a> for I { type Iter = impl MyTrait<'a>; fn unwrap_items(self) -> Self::Iter { From 4af0952961520d44088107d000b78eb3a698edba Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:51:44 +0000 Subject: [PATCH 0153/1250] Call `is_freeze` less in unsafety-checking This is to avoid cycles when calling `is_freeze` on an opaque type. --- src/librustc_mir/transform/check_unsafety.rs | 45 +++++++++++-------- .../ui/impl-trait/unsafety-checking-cycle.rs | 32 +++++++++++++ 2 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 src/test/ui/impl-trait/unsafety-checking-cycle.rs diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 6e80338c975..fab55018d30 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -178,6 +178,16 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { } fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) { + // prevent + // * `&mut x.field` + // * `x.field = y;` + // * `&x.field` if `field`'s type has interior mutability + // because either of these would allow modifying the layout constrained field and + // insert values that violate the layout constraints. + if context.is_mutating_use() || context.is_borrow() { + self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use()); + } + for (i, elem) in place.projection.iter().enumerate() { let proj_base = &place.projection[..i]; @@ -198,24 +208,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { ); } } - let is_borrow_of_interior_mut = context.is_borrow() - && !Place::ty_from(place.local, proj_base, self.body, self.tcx).ty.is_freeze( - self.tcx, - self.param_env, - self.source_info.span, - ); - // prevent - // * `&mut x.field` - // * `x.field = y;` - // * `&x.field` if `field`'s type has interior mutability - // because either of these would allow modifying the layout constrained field and - // insert values that violate the layout constraints. - if context.is_mutating_use() || is_borrow_of_interior_mut { - self.check_mut_borrowing_layout_constrained_field(place, context.is_mutating_use()); - } let old_source_info = self.source_info; - if let (local, []) = (&place.local, proj_base) { - let decl = &self.body.local_decls[*local]; + if let [] = proj_base { + let decl = &self.body.local_decls[place.local]; if decl.internal { if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { if self.tcx.is_mutable_static(def_id) { @@ -240,7 +235,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { // Internal locals are used in the `move_val_init` desugaring. // We want to check unsafety against the source info of the // desugaring, rather than the source info of the RHS. - self.source_info = self.body.local_decls[*local].source_info; + self.source_info = self.body.local_decls[place.local].source_info; } } } @@ -396,6 +391,9 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { cursor = proj_base; match elem { + // Modifications behind a dereference don't affect the value of + // the pointer. + ProjectionElem::Deref => return, ProjectionElem::Field(..) => { let ty = Place::ty_from(place.local, proj_base, &self.body.local_decls, self.tcx).ty; @@ -409,7 +407,14 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { "mutating layout constrained fields cannot statically be \ checked for valid values", ) - } else { + + // Check `is_freeze` as late as possible to avoid cycle errors + // with opaque types. + } else if !place.ty(self.body, self.tcx).ty.is_freeze( + self.tcx, + self.param_env, + self.source_info.span, + ) { ( "borrow of layout constrained field with interior \ mutability", @@ -417,6 +422,8 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> { lose the constraints. Coupled with interior mutability, \ the field can be changed to invalid values", ) + } else { + continue; }; self.require_unsafe( description, diff --git a/src/test/ui/impl-trait/unsafety-checking-cycle.rs b/src/test/ui/impl-trait/unsafety-checking-cycle.rs new file mode 100644 index 00000000000..4a5831c5b73 --- /dev/null +++ b/src/test/ui/impl-trait/unsafety-checking-cycle.rs @@ -0,0 +1,32 @@ +// Ensure that we don't get a cycle error from trying to determine whether an +// opaque type implements `Freeze` in safety checking, when it doesn't matter. + +// check-pass + +#![feature(rustc_attrs)] + +struct AnyValue(T); + +// No need to check for `Freeze` here, there's no +// `rustc_layout_scalar_valid_range_start` involved. +fn not_restricted(c: bool) -> impl Sized { + if c { + let x = AnyValue(not_restricted(false)); + &x.0; + } + 2u32 +} + +#[rustc_layout_scalar_valid_range_start(1)] +struct NonZero(T); + +// No need to check for `Freeze` here, we're not borrowing the field. +fn not_field(c: bool) -> impl Sized { + if c { + let x = unsafe { NonZero(not_field(false)) }; + &x; + } + 5u32 +} + +fn main() {} From 60970be1fd67b19cfcdbbc53f5e87ebcbf0b61bf Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:39:52 +0000 Subject: [PATCH 0154/1250] Distinguish RPIT from other impl trait --- src/librustc/infer/opaque_types/mod.rs | 1 + src/librustc_ast_lowering/item.rs | 14 ++++++--- src/librustc_ast_lowering/lib.rs | 42 ++++++++++++++++---------- src/librustc_hir/hir.rs | 2 ++ 4 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 7fef9d27c4d..7a45782cd45 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -502,6 +502,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Otherwise, generate the label we'll use in the error message. hir::OpaqueTyOrigin::TypeAlias => "impl Trait", hir::OpaqueTyOrigin::FnReturn => "impl Trait", + hir::OpaqueTyOrigin::Misc => "impl Trait", }; let msg = format!("ambiguous lifetime bound in `{}`", context_name); let mut err = self.tcx.sess.struct_span_err(span, &msg); diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 73a25620b5a..426659fd924 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -272,7 +272,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty( t, if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None) + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) } else { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) }, @@ -283,7 +283,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty( t, if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None) + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) } else { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) }, @@ -327,8 +327,14 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(bounds) => { let ty = hir::OpaqueTy { - generics: self.lower_generics(generics, ImplTraitContext::OpaqueTy(None)), - bounds: self.lower_param_bounds(bounds, ImplTraitContext::OpaqueTy(None)), + generics: self.lower_generics( + generics, + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc), + ), + bounds: self.lower_param_bounds( + bounds, + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc), + ), impl_trait_fn: None, origin: hir::OpaqueTyOrigin::TypeAlias, }; diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 618b1e7964b..b600869fdf6 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -222,7 +222,7 @@ enum ImplTraitContext<'b, 'a> { /// We optionally store a `DefId` for the parent item here so we can look up necessary /// information later. It is `None` when no information about the context should be stored /// (e.g., for consts and statics). - OpaqueTy(Option /* fn def-ID */), + OpaqueTy(Option /* fn def-ID */, hir::OpaqueTyOrigin), /// `impl Trait` is not accepted in this position. Disallowed(ImplTraitPosition), @@ -248,7 +248,7 @@ impl<'a> ImplTraitContext<'_, 'a> { use self::ImplTraitContext::*; match self { Universal(params) => Universal(params), - OpaqueTy(fn_def_id) => OpaqueTy(*fn_def_id), + OpaqueTy(fn_def_id, origin) => OpaqueTy(*fn_def_id, *origin), Disallowed(pos) => Disallowed(*pos), } } @@ -1010,7 +1010,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo() -> impl Iterator - ImplTraitContext::OpaqueTy(_) => (true, itctx), + ImplTraitContext::OpaqueTy(..) => (true, itctx), // We are in the argument position, but within a dyn type: // @@ -1019,7 +1019,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // so desugar to // // fn foo(x: dyn Iterator) - ImplTraitContext::Universal(_) if self.is_in_dyn_type => (true, itctx), + ImplTraitContext::Universal(..) if self.is_in_dyn_type => (true, itctx), // In `type Foo = dyn Iterator` we desugar to // `type Foo = dyn Iterator` but we have to override the @@ -1028,7 +1028,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // // FIXME: this is only needed until `impl Trait` is allowed in type aliases. ImplTraitContext::Disallowed(_) if self.is_in_dyn_type => { - (true, ImplTraitContext::OpaqueTy(None)) + (true, ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc)) } // We are in the parameter position, but not within a dyn type: @@ -1269,8 +1269,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { TyKind::ImplTrait(def_node_id, ref bounds) => { let span = t.span; match itctx { - ImplTraitContext::OpaqueTy(fn_def_id) => { - self.lower_opaque_impl_trait(span, fn_def_id, def_node_id, |this| { + ImplTraitContext::OpaqueTy(fn_def_id, origin) => { + self.lower_opaque_impl_trait(span, fn_def_id, origin, def_node_id, |this| { this.lower_param_bounds(bounds, itctx) }) } @@ -1349,6 +1349,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, span: Span, fn_def_id: Option, + origin: hir::OpaqueTyOrigin, opaque_ty_node_id: NodeId, lower_bounds: impl FnOnce(&mut Self) -> hir::GenericBounds<'hir>, ) -> hir::TyKind<'hir> { @@ -1390,7 +1391,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { }, bounds: hir_bounds, impl_trait_fn: fn_def_id, - origin: hir::OpaqueTyOrigin::FnReturn, + origin, }; trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); @@ -1622,7 +1623,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lower_ty( t, if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(Some(parent_def_id)) + ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc) } else { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) }, @@ -1723,9 +1724,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } else { match decl.output { FunctionRetTy::Ty(ref ty) => match in_band_ty_params { - Some((def_id, _)) if impl_trait_return_allow => hir::FunctionRetTy::Return( - self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(def_id))), - ), + Some((def_id, _)) if impl_trait_return_allow => { + hir::FunctionRetTy::Return(self.lower_ty( + ty, + ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn), + )) + } _ => hir::FunctionRetTy::Return( self.lower_ty(ty, ImplTraitContext::disallowed()), ), @@ -1957,7 +1961,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FunctionRetTy::Ty(ty) => self.lower_ty(ty, ImplTraitContext::OpaqueTy(Some(fn_def_id))), + FunctionRetTy::Ty(ty) => self.lower_ty( + ty, + ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn), + ), FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; @@ -2102,9 +2109,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } let kind = hir::GenericParamKind::Type { - default: default - .as_ref() - .map(|x| self.lower_ty(x, ImplTraitContext::OpaqueTy(None))), + default: default.as_ref().map(|x| { + self.lower_ty( + x, + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc), + ) + }), synthetic: param .attrs .iter() diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 80b379218a5..07a2c482253 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1990,6 +1990,8 @@ pub enum OpaqueTyOrigin { FnReturn, /// `async fn` AsyncFn, + /// Impl trait in bindings, consts, statics, bounds. + Misc, } /// The various kinds of types recognized by the compiler. From 43dae91821afd70eeea46bfe0a793321b7e77526 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 11:24:26 +0000 Subject: [PATCH 0155/1250] Give some more queries descriptions --- src/librustc/query/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11b079806af..1cc7c7a1c69 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -125,7 +125,9 @@ rustc_queries! { /// Fetch the MIR for a given `DefId` right after it's built - this includes /// unreachable code. - query mir_built(_: DefId) -> &'tcx Steal> {} + query mir_built(_: DefId) -> &'tcx Steal> { + desc { "building MIR for" } + } /// Fetch the MIR for a given `DefId` up till the point where it is /// ready for const evaluation. @@ -345,6 +347,7 @@ rustc_queries! { TypeChecking { /// The result of unsafety-checking this `DefId`. query unsafety_check_result(key: DefId) -> mir::UnsafetyCheckResult { + desc { |tcx| "unsafety-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } } @@ -414,6 +417,7 @@ rustc_queries! { } query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { + desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } load_cached(tcx, id) { let typeck_tables: Option> = tcx @@ -453,6 +457,7 @@ rustc_queries! { /// Borrow-checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> { + desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) } } } From 9664122b1ff04dd8a853de602cd64d86a6473248 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 20:46:38 +0000 Subject: [PATCH 0156/1250] Simplify function signature in opaque_types --- src/librustc/infer/opaque_types/mod.rs | 12 ++++-------- src/librustc_typeck/check/writeback.rs | 2 +- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 7a45782cd45..1d69f598256 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -550,13 +550,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// # Parameters /// /// - `def_id`, the `impl Trait` type - /// - `opaque_defn`, the opaque definition created in `instantiate_opaque_types` + /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` pub fn infer_opaque_definition_from_instantiation( &self, def_id: DefId, - opaque_defn: &OpaqueTypeDecl<'tcx>, + substs: SubstsRef<'tcx>, instantiated_ty: Ty<'tcx>, span: Span, ) -> Ty<'tcx> { @@ -572,12 +572,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // `impl Trait` return type, resulting in the parameters // shifting. let id_substs = InternalSubsts::identity_for_item(self.tcx, def_id); - let map: FxHashMap, GenericArg<'tcx>> = opaque_defn - .substs - .iter() - .enumerate() - .map(|(index, subst)| (*subst, id_substs[index])) - .collect(); + let map: FxHashMap, GenericArg<'tcx>> = + substs.iter().enumerate().map(|(index, subst)| (*subst, id_substs[index])).collect(); // Convert the type from the function into a type valid outside // the function, by replacing invalid regions with 'static, diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b4798fb67f8..758ce6b5222 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -444,7 +444,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // figures out the concrete type with `U`, but the stored type is with `T`. let definition_ty = self.fcx.infer_opaque_definition_from_instantiation( def_id, - opaque_defn, + opaque_defn.substs, instantiated_ty, span, ); From d8589de1f05fdf84016ad8b6fa1d14a076385b90 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Feb 2020 18:39:40 +0100 Subject: [PATCH 0157/1250] Update pulldown-cmark dependency --- Cargo.lock | 30 +++--- src/librustdoc/Cargo.toml | 2 +- src/librustdoc/html/markdown.rs | 170 ++++++++++++++++++-------------- 3 files changed, 108 insertions(+), 94 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 149f02b4b8c..f3b2f41a09b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1564,7 +1564,7 @@ dependencies = [ "rand_xoshiro", "sized-chunks", "typenum", - "version_check 0.9.1", + "version_check", ] [[package]] @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.2.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +checksum = "53445de381a1f436797497c61d851644d0e8e88e6140f22872ad33a704933978" [[package]] name = "memmap" @@ -2604,23 +2604,23 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.5.3" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77043da1282374688ee212dc44b3f37ff929431de9c9adc3053bd3cee5630357" +checksum = "1c205cc82214f3594e2d50686730314f817c67ffa80fe800cf0db78c3c2b9d9e" dependencies = [ "bitflags", + "getopts", "memchr", "unicase", ] [[package]] name = "pulldown-cmark" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c205cc82214f3594e2d50686730314f817c67ffa80fe800cf0db78c3c2b9d9e" +checksum = "2c2d7fd131800e0d63df52aff46201acaab70b431a4a1ec6f0343fe8e64f35a4" dependencies = [ "bitflags", - "getopts", "memchr", "unicase", ] @@ -4158,7 +4158,7 @@ version = "0.0.0" dependencies = [ "itertools 0.8.0", "minifier", - "pulldown-cmark 0.5.3", + "pulldown-cmark 0.7.0", "rustc-rayon", "serde", "serde_json", @@ -5158,11 +5158,11 @@ checksum = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.1.5", + "version_check", ] [[package]] @@ -5332,12 +5332,6 @@ dependencies = [ "failure", ] -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" - [[package]] name = "version_check" version = "0.9.1" diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 74e46b1eae3..4af13e4cd58 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -9,7 +9,7 @@ name = "rustdoc" path = "lib.rs" [dependencies] -pulldown-cmark = { version = "0.5.3", default-features = false } +pulldown-cmark = { version = "0.7", default-features = false } minifier = "0.0.33" rayon = { version = "0.3.0", package = "rustc-rayon" } serde = { version = "1.0", features = ["derive"] } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c87964af020..07c092a511c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -33,7 +33,7 @@ use crate::html::highlight; use crate::html::toc::TocBuilder; use crate::test; -use pulldown_cmark::{html, CowStr, Event, Options, Parser, Tag}; +use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; #[cfg(test)] mod tests; @@ -189,10 +189,15 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { let compile_fail; let ignore; let edition; - if let Some(Event::Start(Tag::CodeBlock(lang))) = event { - let parse_result = LangString::parse(&lang, self.check_error_codes, false); + if let Some(Event::Start(Tag::CodeBlock(kind))) = event { + let parse_result = match kind { + CodeBlockKind::Fenced(ref lang) => { + LangString::parse(&lang, self.check_error_codes, false) + } + CodeBlockKind::Indented => LangString::all_false(), + }; if !parse_result.rust { - return Some(Event::Start(Tag::CodeBlock(lang))); + return Some(Event::Start(Tag::CodeBlock(kind))); } compile_fail = parse_result.compile_fail; ignore = parse_result.ignore; @@ -370,11 +375,11 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, } let event = self.inner.next(); - if let Some(Event::Start(Tag::Header(level))) = event { + if let Some(Event::Start(Tag::Heading(level))) = event { let mut id = String::new(); for event in &mut self.inner { match &event { - Event::End(Tag::Header(..)) => break, + Event::End(Tag::Heading(..)) => break, Event::Text(text) | Event::Code(text) => { id.extend(text.chars().filter_map(slugify)); } @@ -391,10 +396,10 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, let mut html_header = String::new(); html::push_html(&mut html_header, self.buf.iter().cloned()); let sec = builder.push(level as u32, html_header, id.clone()); - self.buf.push_front(Event::InlineHtml(format!("{} ", sec).into())); + self.buf.push_front(Event::Html(format!("{} ", sec).into())); } - self.buf.push_back(Event::InlineHtml(format!("", level).into())); + self.buf.push_back(Event::Html(format!("", level).into())); let start_tags = format!( "\ @@ -402,7 +407,7 @@ impl<'a, 'b, 'ids, I: Iterator>> Iterator for HeadingLinks<'a, id = id, level = level ); - return Some(Event::InlineHtml(start_tags.into())); + return Some(Event::Html(start_tags.into())); } event } @@ -556,40 +561,44 @@ pub fn find_testable_code( error_codes: ErrorCodes, enable_per_target_ignores: bool, ) { - let mut parser = Parser::new(doc); + let mut parser = Parser::new(doc).into_offset_iter(); let mut prev_offset = 0; let mut nb_lines = 0; let mut register_header = None; - while let Some(event) = parser.next() { + while let Some((event, offset)) = parser.next() { match event { - Event::Start(Tag::CodeBlock(s)) => { - let offset = parser.get_offset(); - - let block_info = if s.is_empty() { - LangString::all_false() - } else { - LangString::parse(&*s, error_codes, enable_per_target_ignores) + Event::Start(Tag::CodeBlock(kind)) => { + let block_info = match kind { + CodeBlockKind::Fenced(ref lang) => { + if lang.is_empty() { + LangString::all_false() + } else { + LangString::parse(lang, error_codes, enable_per_target_ignores) + } + } + CodeBlockKind::Indented => LangString::all_false(), }; if !block_info.rust { continue; } + let mut test_s = String::new(); - while let Some(Event::Text(s)) = parser.next() { + while let Some((Event::Text(s), _)) = parser.next() { test_s.push_str(&s); } - let text = test_s .lines() .map(|l| map_line(l).for_code()) .collect::>>() .join("\n"); - nb_lines += doc[prev_offset..offset].lines().count(); - let line = tests.get_line() + nb_lines; + + nb_lines += doc[prev_offset..offset.start].lines().count(); + let line = tests.get_line() + nb_lines + 1; tests.add_test(text, block_info, line); - prev_offset = offset; + prev_offset = offset.start; } - Event::Start(Tag::Header(level)) => { + Event::Start(Tag::Heading(level)) => { register_header = Some(level as u32); } Event::Text(ref s) if register_header.is_some() => { @@ -783,7 +792,7 @@ impl MarkdownHtml<'_> { // Treat inline HTML as plain text. let p = p.map(|event| match event { - Event::Html(text) | Event::InlineHtml(text) => Event::Text(text), + Event::Html(text) => Event::Text(text), _ => event, }); @@ -842,10 +851,10 @@ pub fn plain_summary_line(md: &str) -> String { let next_event = next_event.unwrap(); let (ret, is_in) = match next_event { Event::Start(Tag::Paragraph) => (None, 1), - Event::Start(Tag::Header(_)) => (None, 1), + Event::Start(Tag::Heading(_)) => (None, 1), Event::Code(code) => (Some(format!("`{}`", code)), 0), Event::Text(ref s) if self.is_in > 0 => (Some(s.as_ref().to_owned()), 0), - Event::End(Tag::Paragraph) | Event::End(Tag::Header(_)) => (None, -1), + Event::End(Tag::Paragraph) | Event::End(Tag::Heading(_)) => (None, -1), _ => (None, 0), }; if is_in > 0 || (is_in < 0 && self.is_in > 0) { @@ -940,68 +949,79 @@ crate fn rust_code_blocks(md: &str) -> Vec { return code_blocks; } - let mut p = Parser::new_ext(md, opts()); - - let mut code_block_start = 0; - let mut code_start = 0; - let mut is_fenced = false; - let mut previous_offset = 0; - let mut in_rust_code_block = false; - while let Some(event) = p.next() { - let offset = p.get_offset(); + let mut p = Parser::new_ext(md, opts()).into_offset_iter(); + while let Some((event, offset)) = p.next() { match event { Event::Start(Tag::CodeBlock(syntax)) => { - let lang_string = if syntax.is_empty() { - LangString::all_false() - } else { - LangString::parse(&*syntax, ErrorCodes::Yes, false) - }; - - if lang_string.rust { - in_rust_code_block = true; - - code_start = offset; - code_block_start = match md[previous_offset..offset].find("```") { - Some(fence_idx) => { - is_fenced = true; - previous_offset + fence_idx + let (syntax, code_start, code_end, range, is_fenced) = match syntax { + CodeBlockKind::Fenced(syntax) => { + let syntax = syntax.as_ref(); + let lang_string = if syntax.is_empty() { + LangString::all_false() + } else { + LangString::parse(&*syntax, ErrorCodes::Yes, false) + }; + if !lang_string.rust { + continue; } - None => { - is_fenced = false; - offset + let syntax = if syntax.is_empty() { None } else { Some(syntax.to_owned()) }; + let (code_start, mut code_end) = match p.next() { + Some((Event::Text(_), offset)) => (offset.start, offset.end), + Some((_, sub_offset)) => { + let code = Range { start: sub_offset.start, end: sub_offset.start }; + code_blocks.push(RustCodeBlock { + is_fenced: true, + range: offset, + code, + syntax, + }); + continue; + } + None => { + let code = Range { start: offset.end, end: offset.end }; + code_blocks.push(RustCodeBlock { + is_fenced: true, + range: offset, + code, + syntax, + }); + continue; + } + }; + while let Some((Event::Text(_), offset)) = p.next() { + code_end = offset.end; } - }; - } - } - Event::End(Tag::CodeBlock(syntax)) if in_rust_code_block => { - in_rust_code_block = false; - - let code_block_end = if is_fenced { - let fence_str = &md[previous_offset..offset].chars().rev().collect::(); - fence_str - .find("```") - .map(|fence_idx| offset - fence_idx) - .unwrap_or_else(|| offset) - } else if md.as_bytes().get(offset).map(|b| *b == b'\n').unwrap_or_default() { - offset - 1 - } else { - offset + (syntax, code_start, code_end, offset, true) + } + CodeBlockKind::Indented => { + // The ending of the offset goes too far sometime so we reduce it by one in + // these cases. + if offset.end > offset.start + && md.get(offset.end..=offset.end) == Some(&"\n") + { + ( + None, + offset.start, + offset.end, + Range { start: offset.start, end: offset.end - 1 }, + false, + ) + } else { + (None, offset.start, offset.end, offset, false) + } + } }; - let code_end = if is_fenced { previous_offset } else { code_block_end }; - code_blocks.push(RustCodeBlock { is_fenced, - range: Range { start: code_block_start, end: code_block_end }, + range, code: Range { start: code_start, end: code_end }, - syntax: if !syntax.is_empty() { Some(syntax.into_string()) } else { None }, + syntax, }); } _ => (), } - - previous_offset = offset; } code_blocks From ad4b3f3e175a1b5d9e532ed35a917cd47196e75b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Feb 2020 22:49:01 +0100 Subject: [PATCH 0158/1250] const-prop: use one helper method for all lints; consistently lint overflow on BinOps and not on Assert --- src/librustc_mir/transform/const_prop.rs | 167 +++++++++++------------ src/librustc_session/lint/builtin.rs | 14 ++ 2 files changed, 94 insertions(+), 87 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 5729cda64f7..53acf1490bf 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,8 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::mir::interpret::{InterpError, InterpResult, Scalar}; +use rustc::lint; +use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, }; @@ -292,7 +293,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { struct ConstPropagator<'mir, 'tcx> { ecx: InterpCx<'mir, 'tcx, ConstPropMachine>, tcx: TyCtxt<'tcx>, - source: MirSource<'tcx>, can_const_prop: IndexVec, param_env: ParamEnv<'tcx>, // FIXME(eddyb) avoid cloning these two fields more than once, @@ -372,7 +372,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { ConstPropagator { ecx, tcx, - source, param_env, can_const_prop, // FIXME(eddyb) avoid cloning these two fields more than once, @@ -501,19 +500,20 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn report_panic_as_lint(&self, source_info: SourceInfo, panic: AssertKind) -> Option<()> { - // Somewhat convoluted way to re-use the CTFE error reporting code. + fn report_assert_as_lint( + &self, + lint: &'static lint::Lint, + source_info: SourceInfo, + message: &str, + panic: AssertKind, + ) -> Option<()> { let lint_root = self.lint_root(source_info)?; - let error = InterpError::MachineStop(Box::new(format!("{:?}", panic))); - let mut diagnostic = error_to_const_error(&self.ecx, error.into()); - diagnostic.span = source_info.span; // fix the span - diagnostic.report_as_lint( - self.tcx.at(source_info.span), - "this expression will panic at runtime", - lint_root, - None, - ); - None + self.tcx.struct_span_lint_hir(lint, lint_root, source_info.span, |lint| { + let mut err = lint.build(message); + err.span_label(source_info.span, format!("{:?}", panic)); + err.emit() + }); + return None; } fn check_unary_op( @@ -530,7 +530,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // `AssertKind` only has an `OverflowNeg` variant, so make sure that is // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); - self.report_panic_as_lint(source_info, AssertKind::OverflowNeg)?; + self.report_assert_as_lint( + lint::builtin::OVERFLOW, + source_info, + "this arithmetic operation will overflow", + AssertKind::OverflowNeg, + )?; } Some(()) @@ -552,17 +557,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let right_size = r.layout.size; let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); if r_bits.map_or(false, |b| b >= left_bits as u128) { - let lint_root = self.lint_root(source_info)?; - self.tcx.struct_span_lint_hir( - ::rustc::lint::builtin::EXCEEDING_BITSHIFTS, - lint_root, - source_info.span, - |lint| { - let dir = if op == BinOp::Shr { "right" } else { "left" }; - lint.build(&format!("attempt to shift {} with overflow", dir)).emit() - }, - ); - return None; + self.report_assert_as_lint( + lint::builtin::EXCEEDING_BITSHIFTS, + source_info, + "this arithmetic operation will overflow", + AssertKind::Overflow(op), + )?; } } @@ -572,7 +572,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let (_res, overflow, _ty) = this.ecx.overflowing_binary_op(op, l, r)?; Ok(overflow) })? { - self.report_panic_as_lint(source_info, AssertKind::Overflow(op))?; + self.report_assert_as_lint( + lint::builtin::OVERFLOW, + source_info, + "this arithmetic operation will overflow", + AssertKind::Overflow(op), + )?; } Some(()) @@ -595,8 +600,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } - let overflow_check = self.tcx.sess.overflow_checks(); - // Perform any special handling for specific Rvalue types. // Generally, checks here fall into one of two categories: // 1. Additional checking to provide useful lints to the user @@ -606,21 +609,26 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // - In this case, we'll return `None` from this function to stop evaluation. match rvalue { // Additional checking: give lints to the user if an overflow would occur. - // If `overflow_check` is set, running const-prop on the `Assert` terminators - // will already generate the appropriate messages. - Rvalue::UnaryOp(op, arg) if !overflow_check => { + // We do this here and not in the `Assert` terminator as that terminator is + // only sometimes emitted (overflow checks can be disabled), but we want to always + // lint. + Rvalue::UnaryOp(op, arg) => { trace!("checking UnaryOp(op = {:?}, arg = {:?})", op, arg); self.check_unary_op(*op, arg, source_info)?; } - - // Additional checking: check for overflows on integer binary operations and report - // them to the user as lints. - // If `overflow_check` is set, running const-prop on the `Assert` terminators - // will already generate the appropriate messages. - Rvalue::BinaryOp(op, left, right) if !overflow_check => { + Rvalue::BinaryOp(op, left, right) => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); self.check_binary_op(*op, left, right, source_info, place_layout)?; } + Rvalue::CheckedBinaryOp(op, left, right) => { + trace!( + "checking CheckedBinaryOp(op = {:?}, left = {:?}, right = {:?})", + op, + left, + right + ); + self.check_binary_op(*op, left, right, source_info, place_layout)?; + } // Do not try creating references (#67862) Rvalue::Ref(_, _, place_ref) => { @@ -898,54 +906,39 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { } Operand::Constant(_) => {} } - let span = terminator.source_info.span; - let hir_id = self - .tcx - .hir() - .as_local_hir_id(self.source.def_id()) - .expect("some part of a failing const eval must be local"); - self.tcx.struct_span_lint_hir( - ::rustc::lint::builtin::CONST_ERR, - hir_id, - span, - |lint| { - let msg = match msg { - AssertKind::Overflow(_) - | AssertKind::OverflowNeg - | AssertKind::DivisionByZero - | AssertKind::RemainderByZero => msg.description().to_owned(), - AssertKind::BoundsCheck { ref len, ref index } => { - let len = self - .eval_operand(len, source_info) - .expect("len must be const"); - let len = match self.ecx.read_scalar(len) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { - data, - .. - })) => data, - other => bug!("const len not primitive: {:?}", other), - }; - let index = self - .eval_operand(index, source_info) - .expect("index must be const"); - let index = match self.ecx.read_scalar(index) { - Ok(ScalarMaybeUndef::Scalar(Scalar::Raw { - data, - .. - })) => data, - other => bug!("const index not primitive: {:?}", other), - }; - format!( - "index out of bounds: \ - the len is {} but the index is {}", - len, index, - ) - } - // Need proper const propagator for these - _ => return, - }; - lint.build(&msg).emit() - }, + let msg = match msg { + AssertKind::DivisionByZero => AssertKind::DivisionByZero, + AssertKind::RemainderByZero => AssertKind::RemainderByZero, + AssertKind::BoundsCheck { ref len, ref index } => { + let len = + self.eval_operand(len, source_info).expect("len must be const"); + let len = self + .ecx + .read_scalar(len) + .unwrap() + .to_machine_usize(&self.tcx) + .unwrap(); + let index = self + .eval_operand(index, source_info) + .expect("index must be const"); + let index = self + .ecx + .read_scalar(index) + .unwrap() + .to_machine_usize(&self.tcx) + .unwrap(); + AssertKind::BoundsCheck { len, index } + } + // Overflow is are already covered by checks on the binary operators. + AssertKind::Overflow(_) | AssertKind::OverflowNeg => return, + // Need proper const propagator for these. + _ => return, + }; + self.report_assert_as_lint( + lint::builtin::PANIC, + source_info, + "this operation will panic at runtime", + msg, ); } else { if self.should_const_prop(value) { diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 5a360b40d61..992f8ab2617 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -46,6 +46,18 @@ declare_lint! { "shift exceeds the type's number of bits" } +declare_lint! { + pub OVERFLOW, + Deny, + "arithmetic operation overflows" +} + +declare_lint! { + pub PANIC, + Deny, + "operation will cause a panic at runtime" +} + declare_lint! { pub CONST_ERR, Deny, @@ -496,6 +508,8 @@ declare_lint_pass! { HardwiredLints => [ ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, EXCEEDING_BITSHIFTS, + OVERFLOW, + PANIC, UNUSED_IMPORTS, UNUSED_EXTERN_CRATES, UNUSED_QUALIFICATIONS, From 47aa2b5bfd35d3e094b55a1a2841698f2765e419 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 14 Feb 2020 12:46:06 +0900 Subject: [PATCH 0159/1250] Avoid calling `fn_sig` on closures --- src/librustc_typeck/collect.rs | 4 ++-- src/test/ui/macros/issue-68060.rs | 16 ++++++++++++++++ src/test/ui/macros/issue-68060.stderr | 24 ++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/macros/issue-68060.rs create mode 100644 src/test/ui/macros/issue-68060.stderr diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5349c324ad8..5779218a937 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2877,7 +2877,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.check_name(sym::thread_local) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL; } else if attr.check_name(sym::track_caller) { - if tcx.fn_sig(id).abi() != abi::Abi::Rust { + if tcx.is_closure(id) || tcx.fn_sig(id).abi() != abi::Abi::Rust { struct_span_err!(tcx.sess, attr.span, E0737, "`#[track_caller]` requires Rust ABI") .emit(); } @@ -2898,7 +2898,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.export_name = Some(s); } } else if attr.check_name(sym::target_feature) { - if tcx.fn_sig(id).unsafety() == Unsafety::Normal { + if tcx.is_closure(id) || tcx.fn_sig(id).unsafety() == Unsafety::Normal { let msg = "`#[target_feature(..)]` can only be applied to `unsafe` functions"; tcx.sess .struct_span_err(attr.span, msg) diff --git a/src/test/ui/macros/issue-68060.rs b/src/test/ui/macros/issue-68060.rs new file mode 100644 index 00000000000..85ebd66b66c --- /dev/null +++ b/src/test/ui/macros/issue-68060.rs @@ -0,0 +1,16 @@ +// build-fail + +#![feature(track_caller)] + +fn main() { + (0..) + .map( + #[target_feature(enable = "")] + //~^ ERROR: the feature named `` is not valid for this target + //~| ERROR: `#[target_feature(..)]` can only be applied to `unsafe` functions + #[track_caller] + //~^ ERROR: `#[track_caller]` requires Rust ABI + |_| (), + ) + .next(); +} diff --git a/src/test/ui/macros/issue-68060.stderr b/src/test/ui/macros/issue-68060.stderr new file mode 100644 index 00000000000..230867410d9 --- /dev/null +++ b/src/test/ui/macros/issue-68060.stderr @@ -0,0 +1,24 @@ +error: `#[target_feature(..)]` can only be applied to `unsafe` functions + --> $DIR/issue-68060.rs:8:13 + | +LL | #[target_feature(enable = "")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can only be applied to `unsafe` functions +... +LL | |_| (), + | ------ not an `unsafe` function + +error: the feature named `` is not valid for this target + --> $DIR/issue-68060.rs:8:30 + | +LL | #[target_feature(enable = "")] + | ^^^^^^^^^^^ `` is not valid for this target + +error[E0737]: `#[track_caller]` requires Rust ABI + --> $DIR/issue-68060.rs:11:13 + | +LL | #[track_caller] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0737`. From 378b5b4ca06d027d9dfff807fe0fff4bc5e62806 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 17:51:39 +0000 Subject: [PATCH 0160/1250] Generate more accurate MIR in `construct_error` --- src/librustc_mir_build/build/mod.rs | 47 ++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 32b1f2b6e13..5f8c0b027e9 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -670,14 +670,51 @@ fn construct_const<'a, 'tcx>( builder.finish() } +/// Construct MIR for a item that has had errors in type checking. +/// +/// This is required because we may still want to run MIR passes on an item +/// with type errors, but normal MIR construction can't handle that in general. fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> { - let owner_id = hir.tcx().hir().body_owner(body_id); - let span = hir.tcx().hir().span(owner_id); - let ty = hir.tcx().types.err; - let mut builder = Builder::new(hir, span, 0, Safety::Safe, ty, span, None); + let tcx = hir.tcx(); + let owner_id = tcx.hir().body_owner(body_id); + let span = tcx.hir().span(owner_id); + let ty = tcx.types.err; + let num_params = match hir.body_owner_kind { + hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(), + hir::BodyOwnerKind::Closure => { + if tcx.hir().body(body_id).generator_kind().is_some() { + // Generators have an implicit `self` parameter *and* a possibly + // implicit resume parameter. + 2 + } else { + // The implicit self parameter adds another local in MIR. + 1 + tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len() + } + } + hir::BodyOwnerKind::Const => 0, + hir::BodyOwnerKind::Static(_) => 0, + }; + let mut builder = Builder::new(hir, span, num_params, Safety::Safe, ty, span, None); let source_info = builder.source_info(span); + // Some MIR passes will expect the number of parameters to match the + // function declaration. + for _ in 0..num_params { + builder.local_decls.push(LocalDecl { + mutability: Mutability::Mut, + ty, + user_ty: UserTypeProjections::none(), + source_info, + internal: false, + local_info: LocalInfo::Other, + is_block_tail: None, + }); + } builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable); - builder.finish() + let mut body = builder.finish(); + if tcx.hir().body(body_id).generator_kind.is_some() { + body.yield_ty = Some(ty); + } + body } impl<'a, 'tcx> Builder<'a, 'tcx> { From 43a3348fd94568b78db7755bb5196fc73fa65214 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 17:26:53 +0000 Subject: [PATCH 0161/1250] Arena allocate the result of mir_borrowck --- src/librustc/arena.rs | 3 ++- src/librustc/query/mod.rs | 15 ++++++--------- src/librustc_mir/borrow_check/mod.rs | 4 ++-- src/librustc_mir/borrow_check/type_check/mod.rs | 3 ++- 4 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index dd242686d26..33cbf6ede0a 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -35,7 +35,8 @@ macro_rules! arena_types { rustc::mir::Promoted, rustc::mir::BodyAndCache<$tcx> >, - [] tables: rustc::ty::TypeckTables<$tcx>, + [decode] tables: rustc::ty::TypeckTables<$tcx>, + [decode] borrowck_result: rustc::mir::BorrowCheckResult<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, [] vtable_method: Option<( rustc_hir::def_id::DefId, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 1cc7c7a1c69..5e279975d15 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -419,13 +419,6 @@ rustc_queries! { query typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { desc { |tcx| "type-checking `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } - load_cached(tcx, id) { - let typeck_tables: Option> = tcx - .queries.on_disk_cache - .try_load_query_result(tcx, id); - - typeck_tables.map(|tables| &*tcx.arena.alloc(tables)) - } } query diagnostic_only_typeck_tables_of(key: DefId) -> &'tcx ty::TypeckTables<'tcx> { cache_on_disk_if { key.is_local() } @@ -456,9 +449,13 @@ rustc_queries! { BorrowChecking { /// Borrow-checks the function body. If this is a closure, returns /// additional requirements that the closure's creator must verify. - query mir_borrowck(key: DefId) -> mir::BorrowCheckResult<'tcx> { + query mir_borrowck(key: DefId) -> &'tcx mir::BorrowCheckResult<'tcx> { desc { |tcx| "borrow-checking `{}`", tcx.def_path_str(key) } - cache_on_disk_if(tcx, _) { key.is_local() && tcx.is_closure(key) } + cache_on_disk_if(tcx, opt_result) { + key.is_local() + && (tcx.is_closure(key) + || opt_result.map_or(false, |r| !r.concrete_opaque_types.is_empty())) + } } } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 941534e68fc..07d3a12fb20 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -90,7 +90,7 @@ pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { mir_borrowck, ..*providers }; } -fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { +fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> &BorrowCheckResult<'_> { let (input_body, promoted) = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); @@ -101,7 +101,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { }); debug!("mir_borrowck done"); - opt_closure_req + tcx.arena.alloc(opt_closure_req) } fn do_mir_borrowck<'a, 'tcx>( diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 5dab064c7b7..67dbf8a2b6d 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2512,7 +2512,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { substs: SubstsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { - if let Some(closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements { + if let Some(ref closure_region_requirements) = tcx.mir_borrowck(def_id).closure_requirements + { let closure_constraints = QueryRegionConstraints { outlives: closure_region_requirements.apply_requirements(tcx, def_id, substs), From 75ac0cca3678d5d309c737f1bd8ef237628a278b Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 25 Dec 2019 09:50:07 +0000 Subject: [PATCH 0162/1250] Prepare to use borrowck to resolve opaque types --- src/librustc/mir/query.rs | 8 +- src/librustc_mir/borrow_check/mod.rs | 32 +++--- src/librustc_mir/borrow_check/nll.rs | 32 +++--- .../borrow_check/type_check/mod.rs | 101 +++++++++++------- src/librustc_typeck/collect.rs | 23 +++- 5 files changed, 128 insertions(+), 68 deletions(-) diff --git a/src/librustc/mir/query.rs b/src/librustc/mir/query.rs index 34f58ab89b1..824cdfe55bf 100644 --- a/src/librustc/mir/query.rs +++ b/src/librustc/mir/query.rs @@ -1,8 +1,10 @@ //! Values computed by queries that use MIR. use crate::ty::{self, Ty}; +use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitMatrix; use rustc_index::vec::IndexVec; use rustc_span::{Span, Symbol}; @@ -59,8 +61,12 @@ pub struct GeneratorLayout<'tcx> { pub storage_conflicts: BitMatrix, } -#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct BorrowCheckResult<'tcx> { + /// All the opaque types that are restricted to concrete types + /// by this function. Unlike the value in `TypeckTables`, this has + /// unerased regions. + pub concrete_opaque_types: FxHashMap>, pub closure_requirements: Option>, pub used_mut_upvars: SmallVec<[Field; 8]>, } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 07d3a12fb20..1843d4bf72d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -195,19 +195,24 @@ fn do_mir_borrowck<'a, 'tcx>( Rc::new(BorrowSet::build(tcx, body, locals_are_invalidated_at_exit, &mdpe.move_data)); // Compute non-lexical lifetimes. - let nll::NllOutput { regioncx, polonius_output, opt_closure_req, nll_errors } = - nll::compute_regions( - infcx, - def_id, - free_regions, - body, - &promoted, - location_table, - param_env, - &mut flow_inits, - &mdpe.move_data, - &borrow_set, - ); + let nll::NllOutput { + regioncx, + opaque_type_values, + polonius_output, + opt_closure_req, + nll_errors, + } = nll::compute_regions( + infcx, + def_id, + free_regions, + body, + &promoted, + location_table, + param_env, + &mut flow_inits, + &mdpe.move_data, + &borrow_set, + ); // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. @@ -389,6 +394,7 @@ fn do_mir_borrowck<'a, 'tcx>( } let result = BorrowCheckResult { + concrete_opaque_types: opaque_type_values, closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, }; diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index a71dfc9a778..4acf1cf7c2b 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -6,6 +6,7 @@ use rustc::mir::{ Location, Promoted, ReadOnlyBodyAndCache, }; use rustc::ty::{self, RegionKind, RegionVid}; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; @@ -46,6 +47,7 @@ crate type PoloniusOutput = Output; /// closure requirements to propagate, and any generated errors. crate struct NllOutput<'tcx> { pub regioncx: RegionInferenceContext<'tcx>, + pub opaque_type_values: FxHashMap>, pub polonius_output: Option>, pub opt_closure_req: Option>, pub nll_errors: RegionErrors<'tcx>, @@ -160,20 +162,21 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let elements = &Rc::new(RegionValueElements::new(&body)); // Run the MIR type-checker. - let MirTypeckResults { constraints, universal_region_relations } = type_check::type_check( - infcx, - param_env, - body, - promoted, - def_id, - &universal_regions, - location_table, - borrow_set, - &mut all_facts, - flow_inits, - move_data, - elements, - ); + let MirTypeckResults { constraints, universal_region_relations, opaque_type_values } = + type_check::type_check( + infcx, + param_env, + body, + promoted, + def_id, + &universal_regions, + location_table, + borrow_set, + &mut all_facts, + flow_inits, + move_data, + elements, + ); if let Some(all_facts) = &mut all_facts { let _prof_timer = infcx.tcx.prof.generic_activity("polonius_fact_generation"); @@ -281,6 +284,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( NllOutput { regioncx, + opaque_type_values, polonius_output, opt_closure_req: closure_region_requirements, nll_errors, diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 67dbf8a2b6d..c6809f9e37e 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -158,7 +158,7 @@ pub(crate) fn type_check<'mir, 'tcx>( constraints: &mut constraints, }; - type_check_internal( + let opaque_type_values = type_check_internal( infcx, mir_def_id, param_env, @@ -173,10 +173,11 @@ pub(crate) fn type_check<'mir, 'tcx>( liveness::generate(&mut cx, body, elements, flow_inits, move_data, location_table); translate_outlives_facts(&mut cx); + cx.opaque_type_values }, ); - MirTypeckResults { constraints, universal_region_relations } + MirTypeckResults { constraints, universal_region_relations, opaque_type_values } } fn type_check_internal<'a, 'tcx, R>( @@ -189,7 +190,7 @@ fn type_check_internal<'a, 'tcx, R>( implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, - mut extra: impl FnMut(&mut TypeChecker<'a, 'tcx>) -> R, + extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R, ) -> R { let mut checker = TypeChecker::new( infcx, @@ -212,7 +213,7 @@ fn type_check_internal<'a, 'tcx, R>( checker.typeck_mir(body); } - extra(&mut checker) + extra(checker) } fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) { @@ -799,6 +800,7 @@ struct TypeChecker<'a, 'tcx> { reported_errors: FxHashSet<(Ty<'tcx>, Span)>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, universal_region_relations: &'a UniversalRegionRelations<'tcx>, + opaque_type_values: FxHashMap>, } struct BorrowCheckContext<'a, 'tcx> { @@ -812,6 +814,7 @@ struct BorrowCheckContext<'a, 'tcx> { crate struct MirTypeckResults<'tcx> { crate constraints: MirTypeckRegionConstraints<'tcx>, crate universal_region_relations: Rc>, + crate opaque_type_values: FxHashMap>, } /// A collection of region constraints that must be satisfied for the @@ -958,6 +961,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { borrowck_context, reported_errors: Default::default(), universal_region_relations, + opaque_type_values: FxHashMap::default(), }; checker.check_user_type_annotations(); checker @@ -1195,6 +1199,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = infcx.tcx; let param_env = self.param_env; let body = self.body; + let concrete_opaque_types = &tcx.typeck_tables_of(anon_owner_def_id).concrete_opaque_types; + let mut opaque_type_values = Vec::new(); + debug!("eq_opaque_type_and_type: mir_def_id={:?}", self.mir_def_id); let opaque_type_map = self.fully_perform_op( locations, @@ -1226,47 +1233,65 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); for (&opaque_def_id, opaque_decl) in &opaque_type_map { - let opaque_defn_ty = tcx.type_of(opaque_def_id); - let opaque_defn_ty = opaque_defn_ty.subst(tcx, opaque_decl.substs); - let opaque_defn_ty = renumber::renumber_regions(infcx, &opaque_defn_ty); - let concrete_is_opaque = infcx - .resolve_vars_if_possible(&opaque_decl.concrete_ty) - .is_impl_trait(); + let resolved_ty = infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty); + let concrete_is_opaque = if let ty::Opaque(def_id, _) = resolved_ty.kind { + def_id == opaque_def_id + } else { + false + }; + let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) { + None => { + assert!( + concrete_is_opaque, + "Non-defining use of {:?} with revealed type", + opaque_def_id, + ); + continue; + } + Some(opaque_defn_ty) => opaque_defn_ty, + }; + debug!("opaque_defn_ty = {:?}", opaque_defn_ty); + let subst_opaque_defn_ty = + opaque_defn_ty.concrete_type.subst(tcx, opaque_decl.substs); + let renumbered_opaque_defn_ty = + renumber::renumber_regions(infcx, &subst_opaque_defn_ty); debug!( - "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?} \ - concrete_is_opaque={}", - opaque_decl.concrete_ty, - infcx.resolve_vars_if_possible(&opaque_decl.concrete_ty), - opaque_defn_ty, - concrete_is_opaque + "eq_opaque_type_and_type: concrete_ty={:?}={:?} opaque_defn_ty={:?}", + opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty, ); - // concrete_is_opaque is `true` when we're using an opaque `impl Trait` - // type without 'revealing' it. For example, code like this: - // - // type Foo = impl Debug; - // fn foo1() -> Foo { ... } - // fn foo2() -> Foo { foo1() } - // - // In `foo2`, we're not revealing the type of `Foo` - we're - // just treating it as the opaque type. - // - // When this occurs, we do *not* want to try to equate - // the concrete type with the underlying defining type - // of the opaque type - this will always fail, since - // the defining type of an opaque type is always - // some other type (e.g. not itself) - // Essentially, none of the normal obligations apply here - - // we're just passing around some unknown opaque type, - // without actually looking at the underlying type it - // gets 'revealed' into - if !concrete_is_opaque { obligations.add( infcx .at(&ObligationCause::dummy(), param_env) - .eq(opaque_decl.concrete_ty, opaque_defn_ty)?, + .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?, + ); + opaque_type_values + .push((opaque_def_id, ty::ResolvedOpaqueTy { ..*opaque_defn_ty })); + } else { + // We're using an opaque `impl Trait` type without + // 'revealing' it. For example, code like this: + // + // type Foo = impl Debug; + // fn foo1() -> Foo { ... } + // fn foo2() -> Foo { foo1() } + // + // In `foo2`, we're not revealing the type of `Foo` - we're + // just treating it as the opaque type. + // + // When this occurs, we do *not* want to try to equate + // the concrete type with the underlying defining type + // of the opaque type - this will always fail, since + // the defining type of an opaque type is always + // some other type (e.g. not itself) + // Essentially, none of the normal obligations apply here - + // we're just passing around some unknown opaque type, + // without actually looking at the underlying type it + // gets 'revealed' into + debug!( + "eq_opaque_type_and_type: non-defining use of {:?}", + opaque_def_id, ); } } @@ -1282,6 +1307,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ), )?; + self.opaque_type_values.extend(opaque_type_values); + let universal_region_relations = self.universal_region_relations; // Finally, if we instantiated the anon types successfully, we diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5349c324ad8..cf82789482b 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1464,7 +1464,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } // Opaque types desugared from `impl Trait`. ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(owner), .. }) => { - tcx.typeck_tables_of(owner) + tcx.mir_borrowck(owner) .concrete_opaque_types .get(&def_id) .map(|opaque| opaque.concrete_type) @@ -1687,7 +1687,7 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { } fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { - use rustc_hir::{ImplItem, Item, TraitItem}; + use rustc_hir::{Expr, ImplItem, Item, TraitItem}; debug!("find_opaque_ty_constraints({:?})", def_id); @@ -1713,7 +1713,17 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ); return; } - let ty = self.tcx.typeck_tables_of(def_id).concrete_opaque_types.get(&self.def_id); + // Calling `mir_borrowck` can lead to cycle errors through + // const-checking, avoid calling it if we don't have to. + if !self.tcx.typeck_tables_of(def_id).concrete_opaque_types.contains_key(&self.def_id) { + debug!( + "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", + self.def_id, def_id, + ); + return; + } + // Use borrowck to get the type with unerased regions. + let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id); if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty { debug!( "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", @@ -1856,6 +1866,13 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { intravisit::NestedVisitorMap::All(&self.tcx.hir()) } + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { + if let hir::ExprKind::Closure(..) = ex.kind { + let def_id = self.tcx.hir().local_def_id(ex.hir_id); + self.check(def_id); + } + intravisit::walk_expr(self, ex); + } fn visit_item(&mut self, it: &'tcx Item<'tcx>) { debug!("find_existential_constraints: visiting {:?}", it); let def_id = self.tcx.hir().local_def_id(it.hir_id); From d9b9f00109aefcaf565c9da3c6fdf9e446f4876c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Thu, 26 Dec 2019 21:16:28 +0000 Subject: [PATCH 0163/1250] Infer opaque type regions in borrow checking We want type checking for function bodies to ignore/erase regions. As such, we need to infer the regions in opaque types in borrow check instead. --- src/librustc_mir/borrow_check/nll.rs | 4 +- .../borrow_check/region_infer/mod.rs | 1 + .../borrow_check/region_infer/opaque_types.rs | 72 +++++++++++++++++++ .../borrow_check/type_check/mod.rs | 9 ++- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/librustc_mir/borrow_check/region_infer/opaque_types.rs diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 4acf1cf7c2b..e4e5fe35d7f 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -282,9 +282,11 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let (closure_region_requirements, nll_errors) = regioncx.solve(infcx, &body, def_id, polonius_output.clone()); + let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span); + NllOutput { regioncx, - opaque_type_values, + opaque_type_values: remapped_opaque_tys, polonius_output, opt_closure_req: closure_region_requirements, nll_errors, diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 6abca481eac..4a2f398c6d5 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -36,6 +36,7 @@ use crate::borrow_check::{ mod dump_mir; mod graphviz; +mod opaque_types; pub mod values; diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs new file mode 100644 index 00000000000..e16a2c838eb --- /dev/null +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -0,0 +1,72 @@ +use rustc::hir::def_id::DefId; +use rustc::infer::InferCtxt; +use rustc::ty; +use rustc_data_structures::fx::FxHashMap; +use rustc_span::Span; + +use super::RegionInferenceContext; + +impl<'tcx> RegionInferenceContext<'tcx> { + /// Resolve any opaque types that were encountered while borrow checking + /// this item. This is then used to get the type in the `type_of` query. + pub(in crate::borrow_check) fn infer_opaque_types( + &self, + infcx: &InferCtxt<'_, 'tcx>, + opaque_ty_decls: FxHashMap>, + span: Span, + ) -> FxHashMap> { + opaque_ty_decls + .into_iter() + .map(|(opaque_def_id, ty::ResolvedOpaqueTy { concrete_type, substs })| { + debug!( + "infer_opaque_types(concrete_type = {:?}, substs = {:?})", + concrete_type, substs + ); + + // Map back to "concrete" regions so that errors in + // `infer_opaque_definition_from_instantiation` can show + // sensible region names. + let universal_concrete_type = + infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match region { + &ty::ReVar(vid) => { + let universal_bound = self.universal_upper_bound(vid); + self.definitions[universal_bound] + .external_name + .filter(|_| self.eval_equal(universal_bound, vid)) + .unwrap_or(infcx.tcx.lifetimes.re_empty) + } + concrete => concrete, + }); + let universal_substs = + infcx.tcx.fold_regions(&substs, &mut false, |region, _| match region { + ty::ReVar(vid) => { + self.definitions[*vid].external_name.unwrap_or_else(|| { + infcx.tcx.sess.delay_span_bug( + span, + "opaque type with non-universal region substs", + ); + infcx.tcx.lifetimes.re_static + }) + } + concrete => concrete, + }); + + debug!( + "infer_opaque_types(universal_concrete_type = {:?}, universal_substs = {:?})", + universal_concrete_type, universal_substs + ); + + let remapped_type = infcx.infer_opaque_definition_from_instantiation( + opaque_def_id, + universal_substs, + universal_concrete_type, + span, + ); + ( + opaque_def_id, + ty::ResolvedOpaqueTy { concrete_type: remapped_type, substs: universal_substs }, + ) + }) + .collect() + } +} diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index c6809f9e37e..5c6f3a0ffa9 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1267,8 +1267,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .at(&ObligationCause::dummy(), param_env) .eq(opaque_decl.concrete_ty, renumbered_opaque_defn_ty)?, ); - opaque_type_values - .push((opaque_def_id, ty::ResolvedOpaqueTy { ..*opaque_defn_ty })); + opaque_type_values.push(( + opaque_def_id, + ty::ResolvedOpaqueTy { + concrete_type: renumbered_opaque_defn_ty, + substs: opaque_decl.substs, + }, + )); } else { // We're using an opaque `impl Trait` type without // 'revealing' it. For example, code like this: From edee23ee25d813547587fdd6bcd3677606839fad Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:50:06 +0000 Subject: [PATCH 0164/1250] Avoid unnecessary opaque type errors in borrowck --- src/librustc_mir/borrow_check/mod.rs | 3 +++ src/librustc_mir/borrow_check/nll.rs | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 1843d4bf72d..da9bdc8b4b0 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -136,6 +136,9 @@ fn do_mir_borrowck<'a, 'tcx>( // Gather the upvars of a closure, if any. let tables = tcx.typeck_tables_of(def_id); + if tables.tainted_by_errors { + infcx.set_tainted_by_errors(); + } let upvars: Vec<_> = tables .upvar_list .get(&def_id) diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index e4e5fe35d7f..4c1ee9582c1 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -282,6 +282,11 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( let (closure_region_requirements, nll_errors) = regioncx.solve(infcx, &body, def_id, polonius_output.clone()); + if !nll_errors.is_empty() { + // Suppress unhelpful extra errors in `infer_opaque_types`. + infcx.set_tainted_by_errors(); + } + let remapped_opaque_tys = regioncx.infer_opaque_types(&infcx, opaque_type_values, body.span); NllOutput { From 2fb02549b85258a039cc8cb6006c028ab437f85a Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:50:39 +0000 Subject: [PATCH 0165/1250] Ensure RPIT types get recorded in borrowck --- .../borrow_check/type_check/input_output.rs | 2 ++ .../borrow_check/type_check/mod.rs | 32 +++++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index 3d3b1e5cbf6..1f1106f0545 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -120,6 +120,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, + true, ) { span_mirbug!( self, @@ -143,6 +144,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, + false, ) { span_mirbug!( self, diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 5c6f3a0ffa9..e7b44715865 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1122,7 +1122,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // the resulting inferend values are stored with the // def-id of the base function. let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id); - return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category); + return self.eq_opaque_type_and_type( + sub, + sup, + parent_def_id, + locations, + category, + false, + ); } else { return Err(terr); } @@ -1188,6 +1195,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { anon_owner_def_id: DefId, locations: Locations, category: ConstraintCategory, + is_function_return: bool, ) -> Fallible<()> { debug!( "eq_opaque_type_and_type( \ @@ -1241,11 +1249,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { }; let opaque_defn_ty = match concrete_opaque_types.get(&opaque_def_id) { None => { - assert!( - concrete_is_opaque, - "Non-defining use of {:?} with revealed type", - opaque_def_id, - ); + if !concrete_is_opaque { + tcx.sess.delay_span_bug( + body.span, + &format!( + "Non-defining use of {:?} with revealed type", + opaque_def_id, + ), + ); + } continue; } Some(opaque_defn_ty) => opaque_defn_ty, @@ -1261,7 +1273,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty, ); - if !concrete_is_opaque { + if !concrete_is_opaque + || (is_function_return + && matches!(opaque_decl.origin, hir::OpaqueTyOrigin::FnReturn)) + { + // For return position impl Trait, the function + // return is the only possible definition site, so + // always record it. obligations.add( infcx .at(&ObligationCause::dummy(), param_env) From bb8c9911f591b2f72d5d473acab3c27ef9ae1a46 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:52:51 +0000 Subject: [PATCH 0166/1250] Erase regions in opaque types in typeck --- src/librustc/infer/opaque_types/mod.rs | 37 +++++++++++++++----------- src/librustc/ty/fold.rs | 4 +++ src/librustc/ty/mod.rs | 10 ++++--- src/librustc/ty/sty.rs | 4 ++- src/librustc_typeck/check/writeback.rs | 3 ++- src/librustc_typeck/collect.rs | 34 ++++++++++++++++++----- 6 files changed, 65 insertions(+), 27 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 1d69f598256..088e57f91a7 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -814,32 +814,37 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r { - // ignore bound regions that appear in the type (e.g., this - // would ignore `'r` in a type like `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) | + // Ignore bound regions that appear in the type, they don't need to + // be remapped (e.g., this would ignore `'r` in a type like + // `for<'r> fn(&'r u32)`. + ty::ReLateBound(..) + + // If regions have been erased, don't try to unerase them. + | ty::ReErased // ignore `'static`, as that can appear anywhere - ty::ReStatic => return r, + | ty::ReStatic => return r, - _ => { } + _ => {} } let generics = self.tcx().generics_of(self.opaque_type_def_id); match self.map.get(&r.into()).map(|k| k.unpack()) { Some(GenericArgKind::Lifetime(r1)) => r1, Some(u) => panic!("region mapped to unexpected kind: {:?}", u), + None if self.map_missing_regions_to_empty || self.tainted_by_errors => { + self.tcx.lifetimes.re_empty + } None if generics.parent.is_some() => { - if !self.map_missing_regions_to_empty && !self.tainted_by_errors { - if let Some(hidden_ty) = self.hidden_ty.take() { - unexpected_hidden_region_diagnostic( - self.tcx, - None, - self.opaque_type_def_id, - hidden_ty, - r, - ) - .emit(); - } + if let Some(hidden_ty) = self.hidden_ty.take() { + unexpected_hidden_region_diagnostic( + self.tcx, + None, + self.opaque_type_def_id, + hidden_ty, + r, + ) + .emit(); } self.tcx.lifetimes.re_root_empty } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 1f007b970b0..5ff0d04c1ed 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -120,6 +120,10 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) } + fn has_erased_regions(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_RE_ERASED) + } + /// True if there are any un-erased free regions. fn has_erasable_regions(&self) -> bool { self.has_type_flags(TypeFlags::HAS_FREE_REGIONS) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b67cab65207..6d36116d782 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -474,10 +474,13 @@ bitflags! { /// if a global bound is safe to evaluate. const HAS_RE_LATE_BOUND = 1 << 11; - const HAS_TY_PLACEHOLDER = 1 << 12; + /// Does this have any `ReErased` regions? + const HAS_RE_ERASED = 1 << 12; - const HAS_CT_INFER = 1 << 13; - const HAS_CT_PLACEHOLDER = 1 << 14; + const HAS_TY_PLACEHOLDER = 1 << 13; + + const HAS_CT_INFER = 1 << 14; + const HAS_CT_PLACEHOLDER = 1 << 15; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits; @@ -497,6 +500,7 @@ bitflags! { TypeFlags::HAS_FREE_LOCAL_NAMES.bits | TypeFlags::KEEP_IN_LOCAL_TCX.bits | TypeFlags::HAS_RE_LATE_BOUND.bits | + TypeFlags::HAS_RE_ERASED.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_INFER.bits | TypeFlags::HAS_CT_PLACEHOLDER.bits; diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0718853b1df..02abac975ac 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1777,7 +1777,9 @@ impl RegionKind { ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } - ty::ReErased => {} + ty::ReErased => { + flags = flags | TypeFlags::HAS_RE_ERASED; + } ty::ReClosureBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 758ce6b5222..3a1622f1649 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -426,7 +426,8 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); - let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); + let instantiated_ty = + self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id)); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cf82789482b..4448c067d34 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -33,8 +33,8 @@ use rustc::ty::subst::GenericArgKind; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; -use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, WithConstness}; -use rustc::ty::{ReprOptions, ToPredicate}; +use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; @@ -1463,9 +1463,22 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { find_opaque_ty_constraints(tcx, def_id) } // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: Some(owner), .. }) => { - tcx.mir_borrowck(owner) - .concrete_opaque_types + ItemKind::OpaqueTy(hir::OpaqueTy { + impl_trait_fn: Some(owner), origin, .. + }) => { + let concrete_types = match origin { + hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { + &tcx.mir_borrowck(owner).concrete_opaque_types + } + hir::OpaqueTyOrigin::Misc => { + // We shouldn't leak borrowck results through impl Trait in bindings. + &tcx.typeck_tables_of(owner).concrete_opaque_types + } + hir::OpaqueTyOrigin::TypeAlias => { + span_bug!(item.span, "Type alias impl trait shouldn't have an owner") + } + }; + let concrete_ty = concrete_types .get(&def_id) .map(|opaque| opaque.concrete_type) .unwrap_or_else(|| { @@ -1480,7 +1493,16 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { ), ); tcx.types.err - }) + }); + debug!("concrete_ty = {:?}", concrete_ty); + if concrete_ty.has_erased_regions() { + // FIXME(impl_trait_in_bindings) Handle this case. + tcx.sess.span_fatal( + item.span, + "lifetimes in impl Trait types in bindings are not currently supported", + ); + } + concrete_ty } ItemKind::Trait(..) | ItemKind::TraitAlias(..) From 93ac5bc7de2b47f8848275254a0e327269ee5f06 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 28 Dec 2019 15:54:27 +0000 Subject: [PATCH 0167/1250] Update tests --- .../ui/consts/min_const_fn/min_const_fn.rs | 3 - .../consts/min_const_fn/min_const_fn.stderr | 34 ++---- .../min_const_fn/min_const_fn_impl_trait.rs | 9 ++ .../min_const_fn_impl_trait.stderr | 21 ++++ .../feature-gate-member-constraints.rs | 5 +- .../feature-gate-member-constraints.stderr | 10 +- src/test/ui/impl-trait/auto-trait-leak.stderr | 100 ++++++++++++++++++ .../recursive-impl-trait-type-direct.rs | 5 +- .../recursive-impl-trait-type-direct.stderr | 2 +- .../recursive-impl-trait-type-indirect.rs | 65 ++++++++---- .../recursive-impl-trait-type-indirect.stderr | 42 ++++---- src/test/ui/lint/lint-unused-mut-variables.rs | 52 ++++----- .../ui/lint/lint-unused-mut-variables.stderr | 68 ++++++------ .../generic_duplicate_param_use6.rs | 6 +- .../generic_duplicate_param_use6.stderr | 4 +- .../issue-52843-closure-constrain.rs | 2 +- .../issue-52843-closure-constrain.stderr | 18 ++-- .../ui/type-alias-impl-trait/issue-60564.rs | 2 +- 18 files changed, 291 insertions(+), 157 deletions(-) create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs create mode 100644 src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.rs b/src/test/ui/consts/min_const_fn/min_const_fn.rs index c3436d4840a..557439f3949 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn.rs @@ -123,12 +123,9 @@ impl Foo { } struct AlanTuring(T); -const fn no_rpit2() -> AlanTuring { AlanTuring(0) } -//~^ ERROR `impl Trait` in const fn is unstable const fn no_apit2(_x: AlanTuring) {} //~^ ERROR trait bounds other than `Sized` const fn no_apit(_x: impl std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` -const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} //~ ERROR trait bounds other than `Sized` const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } //~^ ERROR trait bounds other than `Sized` diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index 927cdfae189..512b343011b 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -214,17 +214,8 @@ LL | impl Foo { = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0723]: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:126:24 - | -LL | const fn no_rpit2() -> AlanTuring { AlanTuring(0) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:128:34 + --> $DIR/min_const_fn.rs:126:34 | LL | const fn no_apit2(_x: AlanTuring) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -233,7 +224,7 @@ LL | const fn no_apit2(_x: AlanTuring) {} = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:130:22 + --> $DIR/min_const_fn.rs:128:22 | LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^^^^^^^^^^^^^^^^^^^ @@ -241,17 +232,8 @@ LL | const fn no_apit(_x: impl std::fmt::Debug) {} = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0723]: `impl Trait` in const fn is unstable - --> $DIR/min_const_fn.rs:131:23 - | -LL | const fn no_rpit() -> impl std::fmt::Debug {} - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #57563 for more information - = help: add `#![feature(const_fn)]` to the crate attributes to enable - error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:132:23 + --> $DIR/min_const_fn.rs:129:23 | LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} | ^^ @@ -260,7 +242,7 @@ LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:133:32 + --> $DIR/min_const_fn.rs:130:32 | LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -269,7 +251,7 @@ LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0723]: trait bounds other than `Sized` on const fn parameters are unstable - --> $DIR/min_const_fn.rs:138:41 + --> $DIR/min_const_fn.rs:135:41 | LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -278,7 +260,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0723]: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:141:21 + --> $DIR/min_const_fn.rs:138:21 | LL | const fn no_fn_ptrs(_x: fn()) {} | ^^ @@ -287,7 +269,7 @@ LL | const fn no_fn_ptrs(_x: fn()) {} = help: add `#![feature(const_fn)]` to the crate attributes to enable error[E0723]: function pointers in const fn are unstable - --> $DIR/min_const_fn.rs:143:27 + --> $DIR/min_const_fn.rs:140:27 | LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } | ^^^^ @@ -295,7 +277,7 @@ LL | const fn no_fn_ptrs2() -> fn() { fn foo() {} foo } = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error: aborting due to 34 previous errors +error: aborting due to 32 previous errors Some errors have detailed explanations: E0493, E0723. For more information about an error, try `rustc --explain E0493`. diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs new file mode 100644 index 00000000000..9cc9b69ac0b --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.rs @@ -0,0 +1,9 @@ +struct AlanTuring(T); +const fn no_rpit2() -> AlanTuring { + //~^ ERROR `impl Trait` in const fn is unstable + AlanTuring(0) +} + +const fn no_rpit() -> impl std::fmt::Debug {} //~ ERROR `impl Trait` in const fn is unstable + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr new file mode 100644 index 00000000000..a62a340332d --- /dev/null +++ b/src/test/ui/consts/min_const_fn/min_const_fn_impl_trait.stderr @@ -0,0 +1,21 @@ +error[E0723]: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn_impl_trait.rs:2:24 + | +LL | const fn no_rpit2() -> AlanTuring { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error[E0723]: `impl Trait` in const fn is unstable + --> $DIR/min_const_fn_impl_trait.rs:7:23 + | +LL | const fn no_rpit() -> impl std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/feature-gates/feature-gate-member-constraints.rs b/src/test/ui/feature-gates/feature-gate-member-constraints.rs index 293a93352e6..f6a92b0d0bf 100644 --- a/src/test/ui/feature-gates/feature-gate-member-constraints.rs +++ b/src/test/ui/feature-gates/feature-gate-member-constraints.rs @@ -1,9 +1,10 @@ -trait Trait<'a, 'b> { } +trait Trait<'a, 'b> {} impl Trait<'_, '_> for T {} fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> { //~^ ERROR ambiguous lifetime bound + //~| ERROR ambiguous lifetime bound (x, y) } -fn main() { } +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-member-constraints.stderr b/src/test/ui/feature-gates/feature-gate-member-constraints.stderr index 3745d5e1c59..c2ec7ae16a3 100644 --- a/src/test/ui/feature-gates/feature-gate-member-constraints.stderr +++ b/src/test/ui/feature-gates/feature-gate-member-constraints.stderr @@ -6,5 +6,13 @@ LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> { | = help: add #![feature(member_constraints)] to the crate attributes to enable -error: aborting due to previous error +error: ambiguous lifetime bound in `impl Trait` + --> $DIR/feature-gate-member-constraints.rs:4:43 + | +LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Trait<'a, 'b> { + | ^^^^^^^^^^^^^^^^^^ the elided lifetimes here do not outlive one another + | + = help: add #![feature(member_constraints)] to the crate attributes to enable + +error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 0ebaac89450..981fad57b0f 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -4,9 +4,34 @@ error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0` LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle1`... --> $DIR/auto-trait-leak.rs:12:1 | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... @@ -15,9 +40,34 @@ note: ...which requires processing `cycle2::{{opaque}}#0`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:22:1 | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... @@ -40,9 +90,34 @@ error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0` LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle1`... --> $DIR/auto-trait-leak.rs:12:1 | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... @@ -51,6 +126,11 @@ note: ...which requires processing `cycle2::{{opaque}}#0`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:22:1 | @@ -89,6 +169,26 @@ LL | fn cycle2() -> impl Clone { note: ...which requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:22:1 | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:21:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:21:1 + | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs index 2b4f5e0975a..3cc53744097 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.rs @@ -1,6 +1,9 @@ // Test that an `impl Trait` type that expands to itself is an error. -fn test() -> impl Sized { //~ ERROR E0720 +#![allow(unconditional_recursion)] + +fn test() -> impl Sized { + //~^ ERROR E0720 test() } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr index 1b5dbd814a4..5a95e2969d1 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-direct.rs:3:14 + --> $DIR/recursive-impl-trait-type-direct.rs:5:14 | LL | fn test() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs index 2428b560b70..e3c621f0c57 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.rs @@ -2,59 +2,75 @@ // otherwise forbidden. #![feature(generators)] +#![allow(unconditional_recursion)] -fn option(i: i32) -> impl Sized { //~ ERROR - if i < 0 { - None - } else { - Some((option(i - 1), i)) - } +fn option(i: i32) -> impl Sized { + //~^ ERROR + if i < 0 { None } else { Some((option(i - 1), i)) } } -fn tuple() -> impl Sized { //~ ERROR +fn tuple() -> impl Sized { + //~^ ERROR (tuple(),) } -fn array() -> impl Sized { //~ ERROR +fn array() -> impl Sized { + //~^ ERROR [array()] } -fn ptr() -> impl Sized { //~ ERROR +fn ptr() -> impl Sized { + //~^ ERROR &ptr() as *const _ } -fn fn_ptr() -> impl Sized { //~ ERROR +fn fn_ptr() -> impl Sized { + //~^ ERROR fn_ptr as fn() -> _ } -fn closure_capture() -> impl Sized { //~ ERROR +fn closure_capture() -> impl Sized { + //~^ ERROR let x = closure_capture(); - move || { x; } + move || { + x; + } } -fn closure_ref_capture() -> impl Sized { //~ ERROR +fn closure_ref_capture() -> impl Sized { + //~^ ERROR let x = closure_ref_capture(); - move || { &x; } + move || { + &x; + } } -fn closure_sig() -> impl Sized { //~ ERROR +fn closure_sig() -> impl Sized { + //~^ ERROR || closure_sig() } -fn generator_sig() -> impl Sized { //~ ERROR +fn generator_sig() -> impl Sized { + //~^ ERROR || generator_sig() } -fn generator_capture() -> impl Sized { //~ ERROR +fn generator_capture() -> impl Sized { + //~^ ERROR let x = generator_capture(); - move || { yield; x; } + move || { + yield; + x; + } } -fn substs_change() -> impl Sized { //~ ERROR +fn substs_change() -> impl Sized { + //~^ ERROR (substs_change::<&T>(),) } -fn generator_hold() -> impl Sized { //~ ERROR +fn generator_hold() -> impl Sized { + //~^ ERROR move || { let x = generator_hold(); yield; @@ -62,15 +78,18 @@ fn generator_hold() -> impl Sized { //~ ERROR } } -fn use_fn_ptr() -> impl Sized { // OK, error already reported +fn use_fn_ptr() -> impl Sized { + // OK, error already reported fn_ptr() } -fn mutual_recursion() -> impl Sync { //~ ERROR +fn mutual_recursion() -> impl Sync { + //~^ ERROR mutual_recursion_b() } -fn mutual_recursion_b() -> impl Sized { //~ ERROR +fn mutual_recursion_b() -> impl Sized { + //~^ ERROR mutual_recursion() } diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr index b7ba0d6ab17..6573b00870c 100644 --- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr +++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr @@ -1,5 +1,5 @@ error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:6:22 + --> $DIR/recursive-impl-trait-type-indirect.rs:7:22 | LL | fn option(i: i32) -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -7,7 +7,7 @@ LL | fn option(i: i32) -> impl Sized { = note: expanded type is `std::option::Option<(impl Sized, i32)>` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:14:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:12:15 | LL | fn tuple() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -15,7 +15,7 @@ LL | fn tuple() -> impl Sized { = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:18:15 + --> $DIR/recursive-impl-trait-type-indirect.rs:17:15 | LL | fn array() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -31,7 +31,7 @@ LL | fn ptr() -> impl Sized { = note: expanded type is `*const impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:26:16 + --> $DIR/recursive-impl-trait-type-indirect.rs:27:16 | LL | fn fn_ptr() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type @@ -39,63 +39,63 @@ LL | fn fn_ptr() -> impl Sized { = note: expanded type is `fn() -> impl Sized` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:30:25 + --> $DIR/recursive-impl-trait-type-indirect.rs:32:25 | LL | fn closure_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:32:5: 32:19 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:35:29 + --> $DIR/recursive-impl-trait-type-indirect.rs:40:29 | LL | fn closure_ref_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:37:5: 37:20 x:impl Sized]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:40:21 + --> $DIR/recursive-impl-trait-type-indirect.rs:48:21 | LL | fn closure_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:41:5: 41:21]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:44:23 + --> $DIR/recursive-impl-trait-type-indirect.rs:53:23 | LL | fn generator_sig() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:45:5: 45:23]` + = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:48:27 + --> $DIR/recursive-impl-trait-type-indirect.rs:58:27 | LL | fn generator_capture() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:26 x:impl Sized {()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:53:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:67:35 | -LL | fn substs_change() -> impl Sized { - | ^^^^^^^^^^ expands to a recursive type +LL | fn substs_change() -> impl Sized { + | ^^^^^^^^^^ expands to a recursive type | = note: expanded type is `(impl Sized,)` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:57:24 + --> $DIR/recursive-impl-trait-type-indirect.rs:72:24 | LL | fn generator_hold() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type | - = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:58:5: 62:6 {impl Sized, ()}]` + = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]` error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:69:26 + --> $DIR/recursive-impl-trait-type-indirect.rs:86:26 | LL | fn mutual_recursion() -> impl Sync { | ^^^^^^^^^ expands to a recursive type @@ -103,7 +103,7 @@ LL | fn mutual_recursion() -> impl Sync { = note: type resolves to itself error[E0720]: opaque type expands to a recursive type - --> $DIR/recursive-impl-trait-type-indirect.rs:73:28 + --> $DIR/recursive-impl-trait-type-indirect.rs:91:28 | LL | fn mutual_recursion_b() -> impl Sized { | ^^^^^^^^^^ expands to a recursive type diff --git a/src/test/ui/lint/lint-unused-mut-variables.rs b/src/test/ui/lint/lint-unused-mut-variables.rs index dd8dbda6d43..5c7ed9d5219 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.rs +++ b/src/test/ui/lint/lint-unused-mut-variables.rs @@ -2,17 +2,17 @@ // Exercise the unused_mut attribute in some positive and negative cases -#![deny(unused_mut)] +#![warn(unused_mut)] #![feature(async_closure, raw_ref_op)] async fn baz_async( mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, ) {} fn baz( mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, #[allow(unused_mut)] (mut c, d): (i32, i32) ) {} @@ -21,13 +21,13 @@ struct RefStruct {} impl RefStruct { async fn baz_async( mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, ) {} fn baz( &self, mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, #[allow(unused_mut)] (mut c, d): (i32, i32) ) {} @@ -37,7 +37,7 @@ trait RefTrait { fn baz( &self, mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, #[allow(unused_mut)] (mut c, d): (i32, i32) ) {} @@ -46,7 +46,7 @@ impl RefTrait for () { fn baz( &self, mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, #[allow(unused_mut)] (mut c, d): (i32, i32) ) {} @@ -55,32 +55,32 @@ impl RefTrait for () { fn main() { let _ = async move | mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, | {}; let _ = | mut a: i32, - //~^ ERROR: variable does not need to be mutable + //~^ WARN: variable does not need to be mutable #[allow(unused_mut)] mut b: i32, #[allow(unused_mut)] (mut c, d): (i32, i32) | {}; // negative cases - let mut a = 3; //~ ERROR: variable does not need to be mutable + let mut a = 3; //~ WARN: variable does not need to be mutable - let mut a = 2; //~ ERROR: variable does not need to be mutable + let mut a = 2; //~ WARN: variable does not need to be mutable - let mut b = 3; //~ ERROR: variable does not need to be mutable + let mut b = 3; //~ WARN: variable does not need to be mutable - let mut a = vec![3]; //~ ERROR: variable does not need to be mutable + let mut a = vec![3]; //~ WARN: variable does not need to be mutable - let (mut a, b) = (1, 2); //~ ERROR: variable does not need to be mutable + let (mut a, b) = (1, 2); //~ WARN: variable does not need to be mutable - let mut a; //~ ERROR: variable does not need to be mutable + let mut a; //~ WARN: variable does not need to be mutable a = 3; - let mut b; //~ ERROR: variable does not need to be mutable + let mut b; //~ WARN: variable does not need to be mutable if true { b = 3; @@ -89,11 +89,11 @@ fn main() { } match 30 { - mut x => {} //~ ERROR: variable does not need to be mutable + mut x => {} //~ WARN: variable does not need to be mutable } match (30, 2) { - (mut x, 1) | //~ ERROR: variable does not need to be mutable + (mut x, 1) | //~ WARN: variable does not need to be mutable (mut x, 2) | (mut x, 3) => { @@ -101,20 +101,20 @@ fn main() { _ => {} } - let x = |mut y: isize| 10; //~ ERROR: variable does not need to be mutable + let x = |mut y: isize| 10; //~ WARN: variable does not need to be mutable - fn what(mut foo: isize) {} //~ ERROR: variable does not need to be mutable + fn what(mut foo: isize) {} //~ WARN: variable does not need to be mutable - let mut a = &mut 5; //~ ERROR: variable does not need to be mutable + let mut a = &mut 5; //~ WARN: variable does not need to be mutable *a = 4; let mut a = 5; - let mut b = (&mut a,); //~ ERROR: variable does not need to be mutable + let mut b = (&mut a,); //~ WARN: variable does not need to be mutable *b.0 = 4; - let mut x = &mut 1; //~ ERROR: variable does not need to be mutable + let mut x = &mut 1; //~ WARN: variable does not need to be mutable let mut f = || { *x += 1; @@ -122,11 +122,11 @@ fn main() { f(); fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { - &mut arg[..] //~^ ERROR: variable does not need to be mutable + &mut arg[..] //~^ WARN: variable does not need to be mutable } - let mut v : &mut Vec<()> = &mut vec![]; //~ ERROR: variable does not need to be mutable + let mut v : &mut Vec<()> = &mut vec![]; //~ WARN: variable does not need to be mutable v.push(()); @@ -181,7 +181,7 @@ fn main() { let mut raw_address_of_mut = 1; // OK let mut_ptr = &raw mut raw_address_of_mut; - let mut raw_address_of_const = 1; //~ ERROR: variable does not need to be mutable + let mut raw_address_of_const = 1; //~ WARN: variable does not need to be mutable let const_ptr = &raw const raw_address_of_const; } diff --git a/src/test/ui/lint/lint-unused-mut-variables.stderr b/src/test/ui/lint/lint-unused-mut-variables.stderr index eda078da9a0..b56b3c7569f 100644 --- a/src/test/ui/lint/lint-unused-mut-variables.stderr +++ b/src/test/ui/lint/lint-unused-mut-variables.stderr @@ -1,4 +1,4 @@ -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:9:5 | LL | mut a: i32, @@ -9,18 +9,10 @@ LL | mut a: i32, note: the lint level is defined here --> $DIR/lint-unused-mut-variables.rs:5:9 | -LL | #![deny(unused_mut)] +LL | #![warn(unused_mut)] | ^^^^^^^^^^ -error: variable does not need to be mutable - --> $DIR/lint-unused-mut-variables.rs:14:5 - | -LL | mut a: i32, - | ----^ - | | - | help: remove this `mut` - -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:23:9 | LL | mut a: i32, @@ -28,7 +20,15 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable + --> $DIR/lint-unused-mut-variables.rs:14:5 + | +LL | mut a: i32, + | ----^ + | | + | help: remove this `mut` + +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:29:9 | LL | mut a: i32, @@ -36,7 +36,7 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:39:9 | LL | mut a: i32, @@ -44,7 +44,7 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:48:9 | LL | mut a: i32, @@ -52,7 +52,7 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:57:9 | LL | mut a: i32, @@ -60,7 +60,7 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:62:9 | LL | mut a: i32, @@ -68,7 +68,7 @@ LL | mut a: i32, | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:104:14 | LL | let x = |mut y: isize| 10; @@ -76,7 +76,7 @@ LL | let x = |mut y: isize| 10; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:69:9 | LL | let mut a = 3; @@ -84,7 +84,7 @@ LL | let mut a = 3; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:71:9 | LL | let mut a = 2; @@ -92,7 +92,7 @@ LL | let mut a = 2; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:73:9 | LL | let mut b = 3; @@ -100,7 +100,7 @@ LL | let mut b = 3; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:75:9 | LL | let mut a = vec![3]; @@ -108,7 +108,7 @@ LL | let mut a = vec![3]; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:77:10 | LL | let (mut a, b) = (1, 2); @@ -116,7 +116,7 @@ LL | let (mut a, b) = (1, 2); | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:79:9 | LL | let mut a; @@ -124,7 +124,7 @@ LL | let mut a; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:83:9 | LL | let mut b; @@ -132,7 +132,7 @@ LL | let mut b; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:92:9 | LL | mut x => {} @@ -140,7 +140,7 @@ LL | mut x => {} | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:96:8 | LL | (mut x, 1) | @@ -148,7 +148,7 @@ LL | (mut x, 1) | | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:109:9 | LL | let mut a = &mut 5; @@ -156,7 +156,7 @@ LL | let mut a = &mut 5; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:114:9 | LL | let mut b = (&mut a,); @@ -164,7 +164,7 @@ LL | let mut b = (&mut a,); | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:117:9 | LL | let mut x = &mut 1; @@ -172,7 +172,7 @@ LL | let mut x = &mut 1; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:129:9 | LL | let mut v : &mut Vec<()> = &mut vec![]; @@ -180,7 +180,7 @@ LL | let mut v : &mut Vec<()> = &mut vec![]; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:184:9 | LL | let mut raw_address_of_const = 1; @@ -188,7 +188,7 @@ LL | let mut raw_address_of_const = 1; | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:106:13 | LL | fn what(mut foo: isize) {} @@ -196,7 +196,7 @@ LL | fn what(mut foo: isize) {} | | | help: remove this `mut` -error: variable does not need to be mutable +warning: variable does not need to be mutable --> $DIR/lint-unused-mut-variables.rs:124:20 | LL | fn mut_ref_arg(mut arg : &mut [u8]) -> &mut [u8] { @@ -218,5 +218,5 @@ note: the lint level is defined here LL | #[deny(unused_mut)] | ^^^^^^^^^^ -error: aborting due to 26 previous errors +error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs index 59e7de413a2..6cbb3069ecd 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs @@ -7,11 +7,11 @@ fn main() {} // test that unused generic parameters are ok type Two = impl Debug; -fn two(t: T, u: U) -> Two { +fn two(t: T, u: U) -> Two { (t, t) } -fn three(t: T, u: U) -> Two { -//~^ concrete type differs from previous +fn three(t: T, u: U) -> Two { + //~^ concrete type differs from previous (u, t) } diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr index 66649413d38..7e81d362661 100644 --- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr @@ -1,7 +1,7 @@ error: concrete type differs from previous defining opaque type use --> $DIR/generic_duplicate_param_use6.rs:14:1 | -LL | / fn three(t: T, u: U) -> Two { +LL | / fn three(t: T, u: U) -> Two { LL | | LL | | (u, t) LL | | } @@ -10,7 +10,7 @@ LL | | } note: previous use here --> $DIR/generic_duplicate_param_use6.rs:10:1 | -LL | / fn two(t: T, u: U) -> Two { +LL | / fn two(t: T, u: U) -> Two { LL | | (t, t) LL | | } | |_^ diff --git a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs index a102d16078b..50eeff0b18f 100644 --- a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs +++ b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs @@ -7,7 +7,7 @@ use std::fmt::Debug; fn main() { type Opaque = impl Debug; fn _unused() -> Opaque { String::new() } - //~^ ERROR: concrete type differs from previous defining opaque type use let null = || -> Opaque { 0 }; + //~^ ERROR: concrete type differs from previous defining opaque type use println!("{:?}", null()); } diff --git a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr index c994eb5986c..1333b4c63d1 100644 --- a/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr +++ b/src/test/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr @@ -1,20 +1,14 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/issue-52843-closure-constrain.rs:9:5 + --> $DIR/issue-52843-closure-constrain.rs:10:16 | -LL | fn _unused() -> Opaque { String::new() } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `std::string::String` +LL | let null = || -> Opaque { 0 }; + | ^^^^^^^^^^^^^^^^^^ expected `std::string::String`, got `i32` | note: previous use here - --> $DIR/issue-52843-closure-constrain.rs:7:1 + --> $DIR/issue-52843-closure-constrain.rs:9:5 | -LL | / fn main() { -LL | | type Opaque = impl Debug; -LL | | fn _unused() -> Opaque { String::new() } -LL | | -LL | | let null = || -> Opaque { 0 }; -LL | | println!("{:?}", null()); -LL | | } - | |_^ +LL | fn _unused() -> Opaque { String::new() } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/issue-60564.rs b/src/test/ui/type-alias-impl-trait/issue-60564.rs index 8686100205f..73acc92172b 100644 --- a/src/test/ui/type-alias-impl-trait/issue-60564.rs +++ b/src/test/ui/type-alias-impl-trait/issue-60564.rs @@ -8,7 +8,7 @@ trait IterBits { type IterBitsIter = impl std::iter::Iterator; //~^ ERROR could not find defining uses -impl IterBits for T +impl IterBits for T where T: std::ops::Shr + std::ops::BitAnd From f23bca79d44642b7a6af11f288216a4828a7b530 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 29 Dec 2019 14:23:20 +0000 Subject: [PATCH 0168/1250] Address review comments --- src/librustc/infer/opaque_types/mod.rs | 45 ++++++++++++------- src/librustc_ast_lowering/lib.rs | 32 ++++++------- .../borrow_check/type_check/input_output.rs | 2 - .../borrow_check/type_check/mod.rs | 18 +------- src/librustc_typeck/collect.rs | 22 ++++++--- src/librustc_typeck/impl_wf_check.rs | 3 ++ 6 files changed, 67 insertions(+), 55 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 088e57f91a7..4abc3ef437e 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -500,9 +500,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::OpaqueTyOrigin::AsyncFn => return false, // Otherwise, generate the label we'll use in the error message. - hir::OpaqueTyOrigin::TypeAlias => "impl Trait", - hir::OpaqueTyOrigin::FnReturn => "impl Trait", - hir::OpaqueTyOrigin::Misc => "impl Trait", + hir::OpaqueTyOrigin::TypeAlias + | hir::OpaqueTyOrigin::FnReturn + | hir::OpaqueTyOrigin::Misc => "impl Trait", }; let msg = format!("ambiguous lifetime bound in `{}`", context_name); let mut err = self.tcx.sess.struct_span_err(span, &msg); @@ -814,18 +814,29 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { match r { - // Ignore bound regions that appear in the type, they don't need to - // be remapped (e.g., this would ignore `'r` in a type like - // `for<'r> fn(&'r u32)`. - ty::ReLateBound(..) - - // If regions have been erased, don't try to unerase them. - | ty::ReErased - - // ignore `'static`, as that can appear anywhere - | ty::ReStatic => return r, - - _ => {} + // Ignore bound regions and `'static` regions that appear in the + // type, we only need to remap regions that reference lifetimes + // from the function declaraion. + // This would ignore `'r` in a type like `for<'r> fn(&'r u32)`. + ty::ReLateBound(..) | ty::ReStatic => return r, + + // If regions have been erased (by writeback), don't try to unerase + // them. + ty::ReErased => return r, + + // The regions that we expect from borrow checking. + ty::ReEarlyBound(_) | ty::ReFree(_) | ty::ReEmpty(ty::UniverseIndex::ROOT) => {} + + ty::ReEmpty(_) + | ty::RePlaceholder(_) + | ty::ReVar(_) + | ty::ReScope(_) + | ty::ReClosureBound(_) => { + // All of the regions in the type should either have been + // erased by writeback, or mapped back to named regions by + // borrow checking. + bug!("unexpected region kind in opaque type: {:?}", r); + } } let generics = self.tcx().generics_of(self.opaque_type_def_id); @@ -833,7 +844,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { Some(GenericArgKind::Lifetime(r1)) => r1, Some(u) => panic!("region mapped to unexpected kind: {:?}", u), None if self.map_missing_regions_to_empty || self.tainted_by_errors => { - self.tcx.lifetimes.re_empty + self.tcx.lifetimes.re_root_empty } None if generics.parent.is_some() => { if let Some(hidden_ty) = self.hidden_ty.take() { @@ -862,7 +873,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { ) .emit(); - self.tcx().mk_region(ty::ReStatic) + self.tcx().lifetimes.re_static } } } diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index b600869fdf6..99de4b88fd3 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -1723,17 +1723,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } else { match decl.output { - FunctionRetTy::Ty(ref ty) => match in_band_ty_params { - Some((def_id, _)) if impl_trait_return_allow => { - hir::FunctionRetTy::Return(self.lower_ty( - ty, - ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn), - )) - } - _ => hir::FunctionRetTy::Return( - self.lower_ty(ty, ImplTraitContext::disallowed()), - ), - }, + FunctionRetTy::Ty(ref ty) => { + let context = match in_band_ty_params { + Some((def_id, _)) if impl_trait_return_allow => { + ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn) + } + _ => ImplTraitContext::disallowed(), + }; + hir::FunctionRetTy::Return(self.lower_ty(ty, context)) + } FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span), } }; @@ -1961,10 +1959,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FunctionRetTy::Ty(ty) => self.lower_ty( - ty, - ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn), - ), + FunctionRetTy::Ty(ty) => { + // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the + // `impl Future` opaque type that `async fn` implicitly + // generates. + let context = + ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn); + self.lower_ty(ty, context) + } FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index 1f1106f0545..3d3b1e5cbf6 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -120,7 +120,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, - true, ) { span_mirbug!( self, @@ -144,7 +143,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.mir_def_id, Locations::All(output_span), ConstraintCategory::BoringNoLocation, - false, ) { span_mirbug!( self, diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index e7b44715865..b2e8cf9df7c 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1122,14 +1122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // the resulting inferend values are stored with the // def-id of the base function. let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id); - return self.eq_opaque_type_and_type( - sub, - sup, - parent_def_id, - locations, - category, - false, - ); + return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category); } else { return Err(terr); } @@ -1195,7 +1188,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { anon_owner_def_id: DefId, locations: Locations, category: ConstraintCategory, - is_function_return: bool, ) -> Fallible<()> { debug!( "eq_opaque_type_and_type( \ @@ -1273,13 +1265,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { opaque_decl.concrete_ty, resolved_ty, renumbered_opaque_defn_ty, ); - if !concrete_is_opaque - || (is_function_return - && matches!(opaque_decl.origin, hir::OpaqueTyOrigin::FnReturn)) - { - // For return position impl Trait, the function - // return is the only possible definition site, so - // always record it. + if !concrete_is_opaque { obligations.add( infcx .at(&ObligationCause::dummy(), param_env) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 4448c067d34..899527ebb95 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1471,7 +1471,9 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { &tcx.mir_borrowck(owner).concrete_opaque_types } hir::OpaqueTyOrigin::Misc => { - // We shouldn't leak borrowck results through impl Trait in bindings. + // We shouldn't leak borrowck results through impl trait in bindings. + // For example, we shouldn't be able to tell if `x` in + // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`. &tcx.typeck_tables_of(owner).concrete_opaque_types } hir::OpaqueTyOrigin::TypeAlias => { @@ -1482,9 +1484,6 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .get(&def_id) .map(|opaque| opaque.concrete_type) .unwrap_or_else(|| { - // This can occur if some error in the - // owner fn prevented us from populating - // the `concrete_opaque_types` table. tcx.sess.delay_span_bug( DUMMY_SP, &format!( @@ -1492,7 +1491,20 @@ fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { owner, def_id, ), ); - tcx.types.err + if tcx.typeck_tables_of(owner).tainted_by_errors { + // Some error in the + // owner fn prevented us from populating + // the `concrete_opaque_types` table. + tcx.types.err + } else { + // We failed to resolve the opaque type or it + // resolves to itself. Return the non-revealed + // type, which should result in E0720. + tcx.mk_opaque( + def_id, + InternalSubsts::identity_for_item(tcx, def_id), + ) + } }); debug!("concrete_ty = {:?}", concrete_ty); if concrete_ty.has_erased_regions() { diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 0b4b8a49054..0a765a1f9c9 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -131,6 +131,9 @@ fn enforce_impl_params_are_constrained( } } ty::AssocKind::OpaqueTy => { + // We don't know which lifetimes appear in the actual + // opaque type, so use all of the lifetimes that appear + // in the type's predicates. let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx); cgp::parameters_for(&predicates, true) } From 728224d1e08f4d28fdc8d9c94b8a553750534435 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 5 Jan 2020 18:27:51 +0000 Subject: [PATCH 0169/1250] Show inferred opaque types with `#[rustc_regions]` --- src/librustc_mir/borrow_check/mod.rs | 12 ++++++++++-- src/librustc_mir/borrow_check/nll.rs | 13 ++++++++++--- src/librustc_mir/borrow_check/type_check/mod.rs | 9 +++++++++ 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index da9bdc8b4b0..f9db62e0a3a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -221,9 +221,17 @@ fn do_mir_borrowck<'a, 'tcx>( // write unit-tests, as well as helping with debugging. nll::dump_mir_results(infcx, MirSource::item(def_id), &body, ®ioncx, &opt_closure_req); - // We also have a `#[rustc_nll]` annotation that causes us to dump + // We also have a `#[rustc_regions]` annotation that causes us to dump // information. - nll::dump_annotation(infcx, &body, def_id, ®ioncx, &opt_closure_req, &mut errors_buffer); + nll::dump_annotation( + infcx, + &body, + def_id, + ®ioncx, + &opt_closure_req, + &opaque_type_values, + &mut errors_buffer, + ); // The various `flow_*` structures can be large. We drop `flow_inits` here // so it doesn't overlap with the others below. This reduces peak memory diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 4c1ee9582c1..101d1856c38 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -355,6 +355,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( mir_def_id: DefId, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, + opaque_type_values: &FxHashMap>, errors_buffer: &mut Vec, ) { let tcx = infcx.tcx; @@ -370,7 +371,7 @@ pub(super) fn dump_annotation<'a, 'tcx>( // viewing the intraprocedural state, the -Zdump-mir output is // better. - if let Some(closure_region_requirements) = closure_region_requirements { + let mut err = if let Some(closure_region_requirements) = closure_region_requirements { let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "external requirements"); regioncx.annotate(tcx, &mut err); @@ -388,13 +389,19 @@ pub(super) fn dump_annotation<'a, 'tcx>( }) .unwrap(); - err.buffer(errors_buffer); + err } else { let mut err = tcx.sess.diagnostic().span_note_diag(body.span, "no external requirements"); regioncx.annotate(tcx, &mut err); - err.buffer(errors_buffer); + err + }; + + if !opaque_type_values.is_empty() { + err.note(&format!("Inferred opaque type values:\n{:#?}", opaque_type_values)); } + + err.buffer(errors_buffer); } fn for_each_region_constraint( diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index b2e8cf9df7c..6c073b3d2c8 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1226,6 +1226,15 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { revealed_ty={:?}", output_ty, opaque_type_map, revealed_ty ); + // Make sure that the inferred types are well-formed. I'm + // not entirely sure this is needed (the HIR type check + // didn't do this) but it seems sensible to prevent opaque + // types hiding ill-formed types. + obligations.obligations.push(traits::Obligation::new( + ObligationCause::dummy(), + param_env, + ty::Predicate::WellFormed(revealed_ty), + )); obligations.add( infcx .at(&ObligationCause::dummy(), param_env) From 5cfa7d1dfb8a83c24ba3220d6740388546c664b9 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 8 Jan 2020 21:20:38 +0000 Subject: [PATCH 0170/1250] Handle equal regions in opaque type inference --- .../borrow_check/region_infer/opaque_types.rs | 86 +++++++++++++++---- .../borrow_check/type_check/mod.rs | 2 + .../ui/impl-trait/equal-hidden-lifetimes.rs | 49 +++++++++++ .../impl-trait/equal-hidden-lifetimes.stderr | 8 ++ 4 files changed, 127 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/impl-trait/equal-hidden-lifetimes.rs create mode 100644 src/test/ui/impl-trait/equal-hidden-lifetimes.stderr diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index e16a2c838eb..f3f392683f6 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -1,7 +1,7 @@ -use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; use rustc::ty; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::DefId; use rustc_span::Span; use super::RegionInferenceContext; @@ -9,6 +9,42 @@ use super::RegionInferenceContext; impl<'tcx> RegionInferenceContext<'tcx> { /// Resolve any opaque types that were encountered while borrow checking /// this item. This is then used to get the type in the `type_of` query. + /// + /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`. + /// This is lowered to give HIR something like + /// + /// type _Return<'_a> = impl Sized + '_a; + /// fn f<'a>(x: &'a i32) -> _Return<'a> { x } + /// + /// When checking the return type record the type from the return and the + /// type used in the return value. In this case they might be `_Return<'1>` + /// and `&'2 i32` respectively. + /// + /// Once we to this method, we have completed region inference and want to + /// call `infer_opaque_definition_from_instantiation` to get the inferred + /// type of `_Return<'_a>`. `infer_opaque_definition_from_instantiation` + /// compares lifetimes directly, so we need to map the inference variables + /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`. + /// + /// First we map all the lifetimes in the concrete type to an equal + /// universal region that occurs in the concrete type's substs, in this case + /// this would result in `&'1 i32`. We only consider regions in the substs + /// in case there is an equal region that does not. For example, this should + /// be allowed: + /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }` + /// + /// Then we map the regions in both the type and the subst to their + /// `external_name` giving `concrete_type = &'a i32, substs = ['a]`. This + /// will then allow `infer_opaque_definition_from_instantiation` to + /// determine that `_Return<'_a> = &'_a i32`. + /// + /// There's a slight complication around closures. Given + /// `fn f<'a: 'a>() { || {} }` the closure's type is something like + /// `f::<'a>::{{closure}}`. The region parameter from f is essentially + /// ignored by type checking so ends up being inferred to an empty region. + /// Calling `universal_upper_bound` for such a region gives `fr_fn_body`, + /// which has no `external_name` in which case we use `'empty` as the + /// region to pass to `infer_opaque_definition_from_instantiation`. pub(in crate::borrow_check) fn infer_opaque_types( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -23,24 +59,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { concrete_type, substs ); - // Map back to "concrete" regions so that errors in - // `infer_opaque_definition_from_instantiation` can show - // sensible region names. - let universal_concrete_type = - infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match region { - &ty::ReVar(vid) => { - let universal_bound = self.universal_upper_bound(vid); - self.definitions[universal_bound] - .external_name - .filter(|_| self.eval_equal(universal_bound, vid)) - .unwrap_or(infcx.tcx.lifetimes.re_empty) - } - concrete => concrete, - }); + let mut subst_regions = vec![self.universal_regions.fr_static]; let universal_substs = - infcx.tcx.fold_regions(&substs, &mut false, |region, _| match region { + infcx.tcx.fold_regions(&substs, &mut false, |region, _| match *region { ty::ReVar(vid) => { - self.definitions[*vid].external_name.unwrap_or_else(|| { + subst_regions.push(vid); + self.definitions[vid].external_name.unwrap_or_else(|| { infcx.tcx.sess.delay_span_bug( span, "opaque type with non-universal region substs", @@ -48,7 +72,33 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx.tcx.lifetimes.re_static }) } - concrete => concrete, + _ => { + infcx.tcx.sess.delay_span_bug( + span, + &format!("unexpected concrete region in borrowck: {:?}", region), + ); + region + } + }); + + subst_regions.sort(); + subst_regions.dedup(); + + let universal_concrete_type = + infcx.tcx.fold_regions(&concrete_type, &mut false, |region, _| match *region { + ty::ReVar(vid) => subst_regions + .iter() + .find(|ur_vid| self.eval_equal(vid, **ur_vid)) + .and_then(|ur_vid| self.definitions[*ur_vid].external_name) + .unwrap_or(infcx.tcx.lifetimes.re_root_empty), + ty::ReLateBound(..) => region, + _ => { + infcx.tcx.sess.delay_span_bug( + span, + &format!("unexpected concrete region in borrowck: {:?}", region), + ); + region + } }); debug!( diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 6c073b3d2c8..85bc032606f 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1275,6 +1275,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); if !concrete_is_opaque { + // Equate concrete_ty (an inference variable) with + // the renumbered type from typeck. obligations.add( infcx .at(&ObligationCause::dummy(), param_env) diff --git a/src/test/ui/impl-trait/equal-hidden-lifetimes.rs b/src/test/ui/impl-trait/equal-hidden-lifetimes.rs new file mode 100644 index 00000000000..79db88828b9 --- /dev/null +++ b/src/test/ui/impl-trait/equal-hidden-lifetimes.rs @@ -0,0 +1,49 @@ +// Test that we consider equal regions when checking for hidden regions in +// opaque types + +// check-pass + +// `'a == 'static` so `&'a i32` is fine as the return type +fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized { + //~^ WARNING unnecessary lifetime parameter `'a` + x +} + +// `'a == 'b` so `&'b i32` is fine as the return type +fn equal_regions<'a: 'b, 'b: 'a>(x: &'b i32) -> impl Sized + 'a { + let y: &'a i32 = x; + let z: &'b i32 = y; + x +} + +// `'a == 'b` so `&'a i32` is fine as the return type +fn equal_regions_rev<'a: 'b, 'b: 'a>(x: &'a i32) -> impl Sized + 'b { + let y: &'a i32 = x; + let z: &'b i32 = y; + x +} + +// `'a == 'b` so `*mut &'b i32` is fine as the return type +fn equal_regions_inv<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { + let y: *mut &'a i32 = x; + let z: *mut &'b i32 = y; + x +} + +// `'a == 'b` so `*mut &'a i32` is fine as the return type +fn equal_regions_inv_rev<'a: 'b, 'b: 'a>(x: *mut &'a i32) -> impl Sized + 'b { + let y: *mut &'a i32 = x; + let z: *mut &'b i32 = y; + x +} + +// Should be able to infer `fn(&'static ())` as the return type. +fn contravariant_lub<'a, 'b: 'a, 'c: 'a, 'd: 'b + 'c>( + x: fn(&'b ()), + y: fn(&'c ()), + c: bool, +) -> impl Sized + 'a { + if c { x } else { y } +} + +fn main() {} diff --git a/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr new file mode 100644 index 00000000000..eb064b4e14a --- /dev/null +++ b/src/test/ui/impl-trait/equal-hidden-lifetimes.stderr @@ -0,0 +1,8 @@ +warning: unnecessary lifetime parameter `'a` + --> $DIR/equal-hidden-lifetimes.rs:7:25 + | +LL | fn equal_regions_static<'a: 'static>(x: &'a i32) -> impl Sized { + | ^^^^^^^^^^^ + | + = help: you can use the `'static` lifetime directly, in place of `'a` + From 2bd16f3c81af80718403e2e202fd0d59e8f94c60 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 11 Jan 2020 14:12:39 +0000 Subject: [PATCH 0171/1250] Improve opaque type lifetime errors * Use better span for member constraint errors * Avoid a bad suggestion * Don't report member constraint errors if we have other universal region errors. --- src/librustc/infer/error_reporting/mod.rs | 6 ++--- .../infer/lexical_region_resolve/mod.rs | 11 +-------- src/librustc/infer/opaque_types/mod.rs | 5 ++-- .../borrow_check/diagnostics/region_errors.rs | 23 ++++++++++--------- .../borrow_check/region_infer/mod.rs | 6 +++-- .../borrow_check/region_infer/opaque_types.rs | 21 ++++++++++++++++- 6 files changed, 41 insertions(+), 31 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 01390f2c719..327e1da64c4 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -405,17 +405,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } RegionResolutionError::MemberConstraintFailure { - opaque_type_def_id, hidden_ty, member_region, - span: _, - choice_regions: _, + span, } => { let hidden_ty = self.resolve_vars_if_possible(&hidden_ty); opaque_types::unexpected_hidden_region_diagnostic( self.tcx, Some(region_scope_tree), - opaque_type_def_id, + span, hidden_ty, member_region, ) diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs index e0a8c3b4e65..1b204e5ba6c 100644 --- a/src/librustc/infer/lexical_region_resolve/mod.rs +++ b/src/librustc/infer/lexical_region_resolve/mod.rs @@ -18,7 +18,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, }; -use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::Span; use std::fmt; @@ -95,13 +94,7 @@ pub enum RegionResolutionError<'tcx> { /// Indicates a failure of a `MemberConstraint`. These arise during /// impl trait processing explicitly -- basically, the impl trait's hidden type /// included some region that it was not supposed to. - MemberConstraintFailure { - span: Span, - opaque_type_def_id: DefId, - hidden_ty: Ty<'tcx>, - member_region: Region<'tcx>, - choice_regions: Vec>, - }, + MemberConstraintFailure { span: Span, hidden_ty: Ty<'tcx>, member_region: Region<'tcx> }, } struct RegionAndOrigin<'tcx> { @@ -656,10 +649,8 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let span = self.tcx().def_span(member_constraint.opaque_type_def_id); errors.push(RegionResolutionError::MemberConstraintFailure { span, - opaque_type_def_id: member_constraint.opaque_type_def_id, hidden_ty: member_constraint.hidden_ty, member_region, - choice_regions: choice_regions.collect(), }); } } diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 4abc3ef437e..4edacd4731c 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -595,11 +595,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn unexpected_hidden_region_diagnostic( tcx: TyCtxt<'tcx>, region_scope_tree: Option<®ion::ScopeTree>, - opaque_type_def_id: DefId, + span: Span, hidden_ty: Ty<'tcx>, hidden_region: ty::Region<'tcx>, ) -> DiagnosticBuilder<'tcx> { - let span = tcx.def_span(opaque_type_def_id); let mut err = struct_span_err!( tcx.sess, span, @@ -851,7 +850,7 @@ impl TypeFolder<'tcx> for ReverseMapper<'tcx> { unexpected_hidden_region_diagnostic( self.tcx, None, - self.opaque_type_def_id, + self.tcx.def_span(self.opaque_type_def_id), hidden_ty, r, ) diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 0e040ec7827..b393d4bc2a5 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -6,7 +6,6 @@ use rustc::infer::{ use rustc::mir::ConstraintCategory; use rustc::ty::{self, RegionVid, Ty}; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_hir::def_id::DefId; use rustc_span::symbol::kw; use rustc_span::Span; @@ -58,8 +57,8 @@ crate enum RegionErrorKind<'tcx> { /// An unexpected hidden region for an opaque type. UnexpectedHiddenRegion { - /// The def id of the opaque type. - opaque_type_def_id: DefId, + /// The span for the member constraint. + span: Span, /// The hidden type. hidden_ty: Ty<'tcx>, /// The unexpected region. @@ -194,18 +193,16 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } - RegionErrorKind::UnexpectedHiddenRegion { - opaque_type_def_id, - hidden_ty, - member_region, - } => { + RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => { let region_scope_tree = &self.infcx.tcx.region_scope_tree(self.mir_def_id); + let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty); + let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region); opaque_types::unexpected_hidden_region_diagnostic( self.infcx.tcx, Some(region_scope_tree), - opaque_type_def_id, - hidden_ty, - member_region, + span, + named_ty, + named_region, ) .buffer(&mut self.errors_buffer); } @@ -588,6 +585,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { { found = true; break; + } else { + // If there's already a lifetime bound, don't + // suggest anything. + return; } } } diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 4a2f398c6d5..8435e6bc885 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -511,7 +511,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_universal_regions(body, outlives_requirements.as_mut(), &mut errors_buffer); } - self.check_member_constraints(infcx, &mut errors_buffer); + if errors_buffer.is_empty() { + self.check_member_constraints(infcx, &mut errors_buffer); + } let outlives_requirements = outlives_requirements.unwrap_or(vec![]); @@ -1604,7 +1606,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // If not, report an error. let member_region = infcx.tcx.mk_region(ty::ReVar(member_region_vid)); errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion { - opaque_type_def_id: m_c.opaque_type_def_id, + span: m_c.definition_span, hidden_ty: m_c.hidden_ty, member_region, }); diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index f3f392683f6..71702eb84e7 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -1,5 +1,5 @@ use rustc::infer::InferCtxt; -use rustc::ty; +use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_span::Span; @@ -119,4 +119,23 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) .collect() } + + /// Map the regions in the type to named regions. This is similar to what + /// `infer_opaque_types` does, but can infer any universal region, not only + /// ones from the substs for the opaque type. It also doesn't double check + /// that the regions produced are in fact equal to the named region they are + /// replaced with. This is fine because this function is only to improve the + /// region names in error messages. + pub(in crate::borrow_check) fn name_regions(&self, tcx: TyCtxt<'tcx>, ty: T) -> T + where + T: TypeFoldable<'tcx>, + { + tcx.fold_regions(&ty, &mut false, |region, _| match *region { + ty::ReVar(vid) => { + let upper_bound = self.universal_upper_bound(vid); + self.definitions[upper_bound].external_name.unwrap_or(region) + } + _ => region, + }) + } } From dd1687ef416f9a5856872c7ed40c4a1a3d8788ea Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 11 Jan 2020 16:58:50 +0000 Subject: [PATCH 0172/1250] Always check upper bounds when choosing member regions Also correctly calculate what the upper bounds are. --- .../borrow_check/region_infer/mod.rs | 53 ++++----------- .../borrow_check/region_infer/reverse_sccs.rs | 68 +++++++++++++++++++ 2 files changed, 81 insertions(+), 40 deletions(-) create mode 100644 src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 8435e6bc885..192e4700b91 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -12,8 +12,6 @@ use rustc::ty::{self, subst::SubstsRef, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::binary_search_util; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; -use rustc_data_structures::graph::vec_graph::VecGraph; -use rustc_data_structures::graph::WithSuccessors; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; @@ -26,6 +24,7 @@ use crate::borrow_check::{ diagnostics::{RegionErrorKind, RegionErrors}, member_constraints::{MemberConstraintSet, NllMemberConstraintIndex}, nll::{PoloniusOutput, ToRegionVid}, + region_infer::reverse_sccs::ReverseSccGraph, region_infer::values::{ LivenessValues, PlaceholderIndices, RegionElement, RegionValueElements, RegionValues, ToElementIndex, @@ -37,6 +36,7 @@ use crate::borrow_check::{ mod dump_mir; mod graphviz; mod opaque_types; +mod reverse_sccs; pub mod values; @@ -66,9 +66,10 @@ pub struct RegionInferenceContext<'tcx> { /// compute the values of each region. constraint_sccs: Rc>, - /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` - /// exists if `B: A`. Computed lazilly. - rev_constraint_graph: Option>>, + /// Reverse of the SCC constraint graph -- i.e., an edge `A -> B` exists if + /// `B: A`. This is used to compute the universal regions that are required + /// to outlive a given SCC. Computed lazily. + rev_scc_graph: Option>, /// The "R0 member of [R1..Rn]" constraints, indexed by SCC. member_constraints: Rc>, @@ -288,7 +289,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { constraints, constraint_graph, constraint_sccs, - rev_constraint_graph: None, + rev_scc_graph: None, member_constraints, member_constraints_applied: Vec::new(), closure_bounds_mapping, @@ -680,15 +681,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { // free region that must outlive the member region `R0` (`UB: // R0`). Therefore, we need only keep an option `O` if `UB: O` // for all UB. - if choice_regions.len() > 1 { - let universal_region_relations = self.universal_region_relations.clone(); - let rev_constraint_graph = self.rev_constraint_graph(); - for ub in self.upper_bounds(scc, &rev_constraint_graph) { - debug!("apply_member_constraint: ub={:?}", ub); - choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r)); - } - debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions); + let rev_scc_graph = self.reverse_scc_graph(); + let universal_region_relations = &self.universal_region_relations; + for ub in rev_scc_graph.upper_bounds(scc) { + debug!("apply_member_constraint: ub={:?}", ub); + choice_regions.retain(|&o_r| universal_region_relations.outlives(ub, o_r)); } + debug!("apply_member_constraint: after ub, choice_regions={:?}", choice_regions); // If we ruled everything out, we're done. if choice_regions.is_empty() { @@ -744,32 +743,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - /// Compute and return the reverse SCC-based constraint graph (lazilly). - fn upper_bounds( - &'a mut self, - scc0: ConstraintSccIndex, - rev_constraint_graph: &'a VecGraph, - ) -> impl Iterator + 'a { - let scc_values = &self.scc_values; - let mut duplicates = FxHashSet::default(); - rev_constraint_graph - .depth_first_search(scc0) - .skip(1) - .flat_map(move |scc1| scc_values.universal_regions_outlived_by(scc1)) - .filter(move |&r| duplicates.insert(r)) - } - - /// Compute and return the reverse SCC-based constraint graph (lazilly). - fn rev_constraint_graph(&mut self) -> Rc> { - if let Some(g) = &self.rev_constraint_graph { - return g.clone(); - } - - let rev_graph = Rc::new(self.constraint_sccs.reverse()); - self.rev_constraint_graph = Some(rev_graph.clone()); - rev_graph - } - /// Returns `true` if all the elements in the value of `scc_b` are nameable /// in `scc_a`. Used during constraint propagation, and only once /// the value of `scc_b` has been computed. diff --git a/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs new file mode 100644 index 00000000000..4b8357bda02 --- /dev/null +++ b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs @@ -0,0 +1,68 @@ +use crate::borrow_check::constraints::ConstraintSccIndex; +use crate::borrow_check::RegionInferenceContext; +use itertools::Itertools; +use rustc::ty::RegionVid; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::graph::vec_graph::VecGraph; +use rustc_data_structures::graph::WithSuccessors; +use std::ops::Range; +use std::rc::Rc; + +crate struct ReverseSccGraph { + graph: VecGraph, + /// For each SCC, the range of `universal_regions` that use that SCC as + /// their value. + scc_regions: FxHashMap>, + /// All of the universal regions, in grouped so that `scc_regions` can + /// index into here. + universal_regions: Vec, +} + +impl ReverseSccGraph { + /// Find all universal regions that are required to outlive the given SCC. + pub(super) fn upper_bounds<'a>( + &'a self, + scc0: ConstraintSccIndex, + ) -> impl Iterator + 'a { + let mut duplicates = FxHashSet::default(); + self.graph + .depth_first_search(scc0) + .flat_map(move |scc1| { + self.scc_regions + .get(&scc1) + .map_or(&[][..], |range| &self.universal_regions[range.clone()]) + }) + .copied() + .filter(move |r| duplicates.insert(*r)) + } +} + +impl RegionInferenceContext<'_> { + /// Compute and return the reverse SCC-based constraint graph (lazily). + pub(super) fn reverse_scc_graph(&mut self) -> Rc { + if let Some(g) = &self.rev_scc_graph { + return g.clone(); + } + + let graph = self.constraint_sccs.reverse(); + let mut paired_scc_regions = self + .universal_regions + .universal_regions() + .map(|region| (self.constraint_sccs.scc(region), region)) + .collect_vec(); + paired_scc_regions.sort(); + let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect(); + + let mut scc_regions = FxHashMap::default(); + let mut start = 0; + for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) { + let group_size = group.into_iter().count(); + scc_regions.insert(scc, start..start + group_size); + start += group_size; + } + + let rev_graph = Rc::new(ReverseSccGraph { graph, scc_regions, universal_regions }); + self.rev_scc_graph = Some(rev_graph.clone()); + rev_graph + } +} From e3e5d27f23f466f7a9e65950e6ce32169ad2a557 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 11 Jan 2020 17:18:52 +0000 Subject: [PATCH 0173/1250] Use member constraint for most opaque types in NLL This ensures that NLL will infer suitable values for regions in opaque types when it's possible. --- src/librustc/infer/opaque_types/mod.rs | 56 ++++++++++++++----- .../borrow_check/type_check/mod.rs | 2 + 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc/infer/opaque_types/mod.rs index 4edacd4731c..5ecd03e4123 100644 --- a/src/librustc/infer/opaque_types/mod.rs +++ b/src/librustc/infer/opaque_types/mod.rs @@ -93,6 +93,18 @@ pub struct OpaqueTypeDecl<'tcx> { pub origin: hir::OpaqueTyOrigin, } +/// Whether member constraints should be generated for all opaque types +pub enum GenerateMemberConstraints { + /// The default, used by typeck + WhenRequired, + /// The borrow checker needs member constraints in any case where we don't + /// have a `'static` bound. This is because the borrow checker has more + /// flexibility in the values of regions. For example, given `f<'a, 'b>` + /// the borrow checker can have an inference variable outlive `'a` and `'b`, + /// but not be equal to `'static`. + IfNoStaticBound, +} + impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Replaces all opaque types in `value` with fresh inference variables /// and creates appropriate obligations. For example, given the input: @@ -315,7 +327,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { debug!("constrain_opaque_types()"); for (&def_id, opaque_defn) in opaque_types { - self.constrain_opaque_type(def_id, opaque_defn, free_region_relations); + self.constrain_opaque_type( + def_id, + opaque_defn, + GenerateMemberConstraints::WhenRequired, + free_region_relations, + ); } } @@ -324,6 +341,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, def_id: DefId, opaque_defn: &OpaqueTypeDecl<'tcx>, + mode: GenerateMemberConstraints, free_region_relations: &FRR, ) { debug!("constrain_opaque_type()"); @@ -358,6 +376,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { op: |r| self.sub_regions(infer::CallReturn(span), required_region, r), }); } + if let GenerateMemberConstraints::IfNoStaticBound = mode { + self.generate_member_constraint( + concrete_ty, + opaque_type_generics, + opaque_defn, + def_id, + ); + } return; } @@ -398,13 +424,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // we will create a "in bound" like `'r in // ['a, 'b, 'c]`, where `'a..'c` are the // regions that appear in the impl trait. + + // For now, enforce a feature gate outside of async functions. + self.member_constraint_feature_gate(opaque_defn, def_id, lr, subst_arg); + return self.generate_member_constraint( concrete_ty, opaque_type_generics, opaque_defn, def_id, - lr, - subst_arg, ); } } @@ -414,6 +442,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let least_region = least_region.unwrap_or(tcx.lifetimes.re_static); debug!("constrain_opaque_types: least_region={:?}", least_region); + if let GenerateMemberConstraints::IfNoStaticBound = mode { + if least_region != tcx.lifetimes.re_static { + self.generate_member_constraint( + concrete_ty, + opaque_type_generics, + opaque_defn, + def_id, + ); + } + } concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor { tcx: self.tcx, op: |r| self.sub_regions(infer::CallReturn(span), least_region, r), @@ -434,19 +472,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { opaque_type_generics: &ty::Generics, opaque_defn: &OpaqueTypeDecl<'tcx>, opaque_type_def_id: DefId, - conflict1: ty::Region<'tcx>, - conflict2: ty::Region<'tcx>, ) { - // For now, enforce a feature gate outside of async functions. - if self.member_constraint_feature_gate( - opaque_defn, - opaque_type_def_id, - conflict1, - conflict2, - ) { - return; - } - // Create the set of choice regions: each region in the hidden // type can be equal to any of the region parameters of the // opaque type definition. diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 85bc032606f..2a2d8642760 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -6,6 +6,7 @@ use std::{fmt, iter, mem}; use either::Either; use rustc::infer::canonical::QueryRegionConstraints; +use rustc::infer::opaque_types::GenerateMemberConstraints; use rustc::infer::outlives::env::RegionBoundPairs; use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; @@ -1345,6 +1346,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { infcx.constrain_opaque_type( opaque_def_id, &opaque_decl, + GenerateMemberConstraints::IfNoStaticBound, universal_region_relations, ); Ok(InferOk { value: (), obligations: vec![] }) From 78e0ab53fb4ac444e7d62735f0b8dcc9a42004f6 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 11 Jan 2020 17:18:58 +0000 Subject: [PATCH 0174/1250] Update tests --- .../issues/issue-63388-1.nll.stderr | 11 +-- src/test/ui/impl-trait/auto-trait-leak.stderr | 70 ++++++++++++++++--- .../multiple-lifetimes/error-handling-2.rs | 29 ++++++++ .../error-handling-2.stderr | 15 ++++ .../multiple-lifetimes/error-handling.rs | 2 +- .../multiple-lifetimes/error-handling.stderr | 17 ++--- .../ordinary-bounds-unrelated.nll.stderr | 2 + .../ordinary-bounds-unsuited.nll.stderr | 2 + ...pes_pin_lifetime_mismatch-async.nll.stderr | 19 +---- .../self/elision/lt-ref-self-async.nll.stderr | 51 +------------- .../elision/ref-mut-self-async.nll.stderr | 51 +------------- .../elision/ref-mut-struct-async.nll.stderr | 43 +----------- .../self/elision/ref-struct-async.nll.stderr | 43 +----------- 13 files changed, 124 insertions(+), 231 deletions(-) create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs create mode 100644 src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr 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 index 4ae3971e90e..8e0e1ce3dc3 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr @@ -1,11 +1,3 @@ -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 | @@ -19,6 +11,5 @@ LL | | foo LL | | } | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` -error: aborting due to 2 previous errors +error: aborting due to previous error -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/auto-trait-leak.stderr b/src/test/ui/impl-trait/auto-trait-leak.stderr index 981fad57b0f..3d60cbff320 100644 --- a/src/test/ui/impl-trait/auto-trait-leak.stderr +++ b/src/test/ui/impl-trait/auto-trait-leak.stderr @@ -41,7 +41,7 @@ note: ...which requires processing `cycle2::{{opaque}}#0`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires borrow-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -51,22 +51,22 @@ note: ...which requires processing `cycle2`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires unsafety-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building MIR for... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -127,13 +127,33 @@ note: ...which requires processing `cycle2::{{opaque}}#0`... LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ note: ...which requires borrow-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:22:1 | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle2`... + --> $DIR/auto-trait-leak.rs:22:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:22:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:22:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:22:1 + | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which again requires processing `cycle1::{{opaque}}#0`, completing the cycle @@ -155,9 +175,34 @@ error[E0391]: cycle detected when processing `cycle1::{{opaque}}#0` LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^ | +note: ...which requires borrow-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires processing `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle1`... --> $DIR/auto-trait-leak.rs:12:1 | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires unsafety-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires building MIR for... + --> $DIR/auto-trait-leak.rs:12:1 + | +LL | fn cycle1() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires type-checking `cycle1`... + --> $DIR/auto-trait-leak.rs:12:1 + | LL | fn cycle1() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires evaluating trait selection obligation `impl std::clone::Clone: std::marker::Send`... @@ -166,28 +211,33 @@ note: ...which requires processing `cycle2::{{opaque}}#0`... | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^ +note: ...which requires borrow-checking `cycle2`... + --> $DIR/auto-trait-leak.rs:22:1 + | +LL | fn cycle2() -> impl Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires processing `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires unsafety-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires building MIR for... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires type-checking `cycle2`... - --> $DIR/auto-trait-leak.rs:21:1 + --> $DIR/auto-trait-leak.rs:22:1 | LL | fn cycle2() -> impl Clone { | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs new file mode 100644 index 00000000000..96d891b2cf1 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.rs @@ -0,0 +1,29 @@ +// compile-flags:-Zborrowck=mir + +#![feature(member_constraints)] +#![feature(type_alias_impl_trait)] + +#[derive(Clone)] +struct CopyIfEq(T, U); + +impl Copy for CopyIfEq {} + +type E<'a, 'b> = impl Sized; + +fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds + let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); + + // This assignment requires that `x` and `y` have the same type due to the + // `Copy` impl. The reason why we are using a copy to create a constraint + // is that only borrow checking (not regionck in type checking) enforces + // this bound. + let u = v; + let _: *mut &'a i32 = u.1; + unsafe { + let _: &'b i32 = *u.0; + } + u.0 +} + +fn main() {} diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr new file mode 100644 index 00000000000..59105f11805 --- /dev/null +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr @@ -0,0 +1,15 @@ +error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds + --> $DIR/error-handling-2.rs:13:60 + | +LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | ^^^^^^^^^ + | +note: hidden type `*mut &'a i32` captures the lifetime `'a` as defined on the function body at 13:8 + --> $DIR/error-handling-2.rs:13:8 + | +LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { + | ^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs index 8fb4794e891..8d02d635094 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.rs @@ -11,7 +11,6 @@ impl Copy for CopyIfEq {} type E<'a, 'b> = impl Sized; fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - //~^ ERROR lifetime may not live long enough let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y); // This assignment requires that `x` and `y` have the same type due to the @@ -22,6 +21,7 @@ fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { let _: *mut &'a i32 = u.1; unsafe { let _: &'b i32 = *u.0; + //~^ ERROR lifetime may not live long enough } u.0 } diff --git a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr index 5957ecbdc5f..6ce3aaf49eb 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -1,14 +1,15 @@ error: lifetime may not live long enough - --> $DIR/error-handling.rs:13:56 + --> $DIR/error-handling.rs:23:16 | LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { - | -- lifetime `'a` defined here ^^^^^^^^^ opaque type requires that `'a` must outlive `'static` - | - = help: consider replacing `'a` with `'static` -help: to allow this `impl Trait` to capture borrowed data with lifetime `'a`, add `'a` as a bound - | -LL | type E<'a, 'b> = impl Sized + 'a; - | + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | let _: &'b i32 = *u.0; + | ^^^^^^^ type annotation requires that `'a` must outlive `'b` + | + = help: consider adding the following bound: `'a: 'b` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr index a255c48ec6e..5bfc446f6a5 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unrelated.nll.stderr @@ -3,6 +3,8 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea | LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e> | ^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Ordinary<'_>` captures lifetime '_#8r error: aborting due to previous error diff --git a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr index af42ed1c5c1..7291eee7b9e 100644 --- a/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr +++ b/src/test/ui/impl-trait/multiple-lifetimes/ordinary-bounds-unsuited.nll.stderr @@ -3,6 +3,8 @@ error[E0700]: hidden type for `impl Trait` captures lifetime that does not appea | LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b> | ^^^^^^^^^^^^^^^^^^ + | + = note: hidden type `Ordinary<'_>` captures lifetime '_#5r 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 index b05940fd273..61f6680d5a4 100644 --- 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 @@ -1,11 +1,3 @@ -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:52 | @@ -24,14 +16,6 @@ LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { ( | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` -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:64 | @@ -41,6 +25,5 @@ LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } | | let's call the lifetime of this reference `'1` | lifetime `'a` defined here -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0700`. 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 index 8dd823a2204..e66711076e8 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -1,11 +1,3 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:12: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:9 | @@ -16,14 +8,6 @@ LL | async fn ref_self(&self, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:18: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:9 | @@ -34,14 +18,6 @@ LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:22: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:9 | @@ -52,14 +28,6 @@ LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:26: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:9 | @@ -70,14 +38,6 @@ LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:30:66 - | -LL | async fn box_box_ref_Self(self: Box>, 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:9 | @@ -88,14 +48,6 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/lt-ref-self-async.rs:34:62 - | -LL | async fn box_pin_Self(self: Box>, 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:9 | @@ -106,6 +58,5 @@ LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0700`. 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 index 768f532c183..82098cd4f07 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -1,11 +1,3 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:12: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:9 | @@ -16,14 +8,6 @@ LL | async fn ref_self(&mut self, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:18: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:9 | @@ -34,14 +18,6 @@ LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:22: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:9 | @@ -52,14 +28,6 @@ LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:26: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:9 | @@ -70,14 +38,6 @@ LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:30:70 - | -LL | async fn box_box_ref_Self(self: Box>, 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:9 | @@ -88,14 +48,6 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-self-async.rs:34:70 - | -LL | async fn box_pin_ref_Self(self: Box>, 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:9 | @@ -106,6 +58,5 @@ LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0700`. 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 index 9e26e411d30..736cebae4bc 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -1,11 +1,3 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-struct-async.rs:12: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:9 | @@ -16,14 +8,6 @@ LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-struct-async.rs:16: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:9 | @@ -34,14 +18,6 @@ LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-struct-async.rs:20: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:9 | @@ -52,14 +28,6 @@ LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-struct-async.rs:24:74 - | -LL | async fn box_box_ref_Struct(self: Box>, 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:9 | @@ -70,14 +38,6 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-mut-struct-async.rs:28:74 - | -LL | async fn box_pin_ref_Struct(self: Box>, 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:9 | @@ -88,6 +48,5 @@ LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0700`. diff --git a/src/test/ui/self/elision/ref-struct-async.nll.stderr b/src/test/ui/self/elision/ref-struct-async.nll.stderr index cbf051205ed..5d7dd76827a 100644 --- a/src/test/ui/self/elision/ref-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -1,11 +1,3 @@ -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-struct-async.rs:12: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:9 | @@ -16,14 +8,6 @@ LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-struct-async.rs:16: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:9 | @@ -34,14 +18,6 @@ LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-struct-async.rs:20: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:9 | @@ -52,14 +28,6 @@ LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-struct-async.rs:24:70 - | -LL | async fn box_box_ref_Struct(self: Box>, 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:9 | @@ -70,14 +38,6 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds - --> $DIR/ref-struct-async.rs:28:66 - | -LL | async fn box_pin_Struct(self: Box>, 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:9 | @@ -88,6 +48,5 @@ LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { LL | f | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` -error: aborting due to 10 previous errors +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0700`. From 6d9e270a4ddf517b008537f0d8b3768db20d5436 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 12 Jan 2020 10:19:19 +0000 Subject: [PATCH 0175/1250] Fix and test nested impl Trait --- .../borrow_check/region_infer/opaque_types.rs | 18 +++++++++++++----- src/test/ui/impl-trait/nested-return-type.rs | 16 ++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/impl-trait/nested-return-type.rs diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index 71702eb84e7..52d54f7b53c 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -13,8 +13,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// For example consider `fn f<'a>(x: &'a i32) -> impl Sized + 'a { x }`. /// This is lowered to give HIR something like /// - /// type _Return<'_a> = impl Sized + '_a; - /// fn f<'a>(x: &'a i32) -> _Return<'a> { x } + /// type f<'a>::_Return<'_a> = impl Sized + '_a; + /// fn f<'a>(x: &'a i32) -> f<'static>::_Return<'a> { x } /// /// When checking the return type record the type from the return and the /// type used in the return value. In this case they might be `_Return<'1>` @@ -34,9 +34,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }` /// /// Then we map the regions in both the type and the subst to their - /// `external_name` giving `concrete_type = &'a i32, substs = ['a]`. This - /// will then allow `infer_opaque_definition_from_instantiation` to - /// determine that `_Return<'_a> = &'_a i32`. + /// `external_name` giving `concrete_type = &'a i32`, + /// `substs = ['static, 'a]`. This will then allow + /// `infer_opaque_definition_from_instantiation` to determine that + /// `_Return<'_a> = &'_a i32`. /// /// There's a slight complication around closures. Given /// `fn f<'a: 'a>() { || {} }` the closure's type is something like @@ -72,6 +73,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { infcx.tcx.lifetimes.re_static }) } + // We don't fold regions in the predicates of opaque + // types to `ReVar`s. This means that in a case like + // + // fn f<'a: 'a>() -> impl Iterator + // + // The inner opaque type has `'static` in its substs. + ty::ReStatic => region, _ => { infcx.tcx.sess.delay_span_bug( span, diff --git a/src/test/ui/impl-trait/nested-return-type.rs b/src/test/ui/impl-trait/nested-return-type.rs new file mode 100644 index 00000000000..7d7a084b890 --- /dev/null +++ b/src/test/ui/impl-trait/nested-return-type.rs @@ -0,0 +1,16 @@ +// Check that nested impl Trait items work in functions with generic parameters. +// check-pass + +trait Captures<'a> {} + +impl Captures<'_> for T {} + +fn nested_assoc_type<'a: 'a, T>() -> impl Iterator { + [1].iter() +} + +fn nested_assoc_lifetime<'a: 'a, T>() -> impl Iterator> { + [1].iter() +} + +fn main() {} From 223a2ee3061a4bfe31df8aee70c682618ef28fe1 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 17 Jan 2020 20:11:51 +0000 Subject: [PATCH 0176/1250] Add fast path to eq_opaque_type_and_type --- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/fold.rs | 3 +++ src/librustc/ty/mod.rs | 5 ++++- src/librustc/ty/util.rs | 2 +- src/librustc_mir/borrow_check/type_check/mod.rs | 16 ++++++++++++++++ 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 4a4280ba7dc..4546eadc6e6 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -138,7 +138,7 @@ impl FlagComputation { } &ty::Opaque(_, substs) => { - self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_OPAQUE); self.add_substs(substs); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 5ff0d04c1ed..3212bc72417 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -78,6 +78,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_projections(&self) -> bool { self.has_type_flags(TypeFlags::HAS_PROJECTION) } + fn has_opaque_types(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_OPAQUE) + } fn references_error(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_ERR) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 6d36116d782..45ea05efd4a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -481,6 +481,8 @@ bitflags! { const HAS_CT_INFER = 1 << 14; const HAS_CT_PLACEHOLDER = 1 << 15; + /// Does this have any [Opaque] types. + const HAS_TY_OPAQUE = 1 << 16; const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits; @@ -503,7 +505,8 @@ bitflags! { TypeFlags::HAS_RE_ERASED.bits | TypeFlags::HAS_TY_PLACEHOLDER.bits | TypeFlags::HAS_CT_INFER.bits | - TypeFlags::HAS_CT_PLACEHOLDER.bits; + TypeFlags::HAS_CT_PLACEHOLDER.bits | + TypeFlags::HAS_TY_OPAQUE.bits; } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index db7b8d8cfd9..f3c3d04931a 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -615,7 +615,7 @@ impl<'tcx> TyCtxt<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { if let ty::Opaque(def_id, substs) = t.kind { self.expand_opaque_ty(def_id, substs).unwrap_or(t) - } else if t.has_projections() { + } else if t.has_opaque_types() { t.super_fold_with(self) } else { t diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 2a2d8642760..88fe6d1a3a4 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1196,6 +1196,22 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { anon_ty={:?})", revealed_ty, anon_ty ); + + // Fast path for the common case. + if !anon_ty.has_opaque_types() { + if let Err(terr) = self.eq_types(anon_ty, revealed_ty, locations, category) { + span_mirbug!( + self, + locations, + "eq_opaque_type_and_type: `{:?}=={:?}` failed with `{:?}`", + revealed_ty, + anon_ty, + terr + ); + } + return Ok(()); + } + let infcx = self.infcx; let tcx = infcx.tcx; let param_env = self.param_env; From edddb62099056abae853aa1157919d3ec112eeb4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 17 Jan 2020 21:15:03 +0000 Subject: [PATCH 0177/1250] Split `type_of` out of collect.rs --- src/librustc_typeck/collect.rs | 658 +----------------------- src/librustc_typeck/collect/type_of.rs | 661 +++++++++++++++++++++++++ 2 files changed, 666 insertions(+), 653 deletions(-) create mode 100644 src/librustc_typeck/collect/type_of.rs diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 899527ebb95..1a505a39e46 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1,5 +1,3 @@ -// ignore-tidy-filelength - //! "Collection" is the process of determining the type and other external //! details of each item in Rust. Collection is specifically concerned //! with *inter-procedural* things -- for example, for a function @@ -27,18 +25,16 @@ use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::mir::mono::Linkage; use rustc::session::parse::feature_err; -use rustc::traits; use rustc::ty::query::Providers; -use rustc::ty::subst::GenericArgKind; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::Discr; use rustc::ty::util::IntTypeExt; -use rustc::ty::{self, AdtKind, Const, DefIdTree, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr}; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{struct_span_err, Applicability, StashKey}; +use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -50,6 +46,8 @@ use rustc_target::spec::abi; use syntax::ast; use syntax::ast::{Ident, MetaItemKind}; +mod type_of; + struct OnlySelfBounds(bool); /////////////////////////////////////////////////////////////////////////// @@ -64,7 +62,7 @@ fn collect_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) { pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { - type_of, + type_of: type_of::type_of, generics_of, predicates_of, predicates_defined_on, @@ -1329,652 +1327,6 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { }) } -fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) { - struct_span_err!( - tcx.sess, - span, - E0202, - "associated types are not yet supported in inherent impls (see #8995)" - ) - .emit(); -} - -fn infer_placeholder_type( - tcx: TyCtxt<'_>, - def_id: DefId, - body_id: hir::BodyId, - span: Span, - item_ident: Ident, -) -> Ty<'_> { - let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id); - - // If this came from a free `const` or `static mut?` item, - // then the user may have written e.g. `const A = 42;`. - // In this case, the parser has stashed a diagnostic for - // us to improve in typeck so we do that now. - match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { - Some(mut err) => { - // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. - // We are typeck and have the real type, so remove that and suggest the actual type. - err.suggestions.clear(); - err.span_suggestion( - span, - "provide a type for the item", - format!("{}: {}", item_ident, ty), - Applicability::MachineApplicable, - ) - .emit(); - } - None => { - let mut diag = bad_placeholder_type(tcx, vec![span]); - if ty != tcx.types.err { - diag.span_suggestion( - span, - "replace `_` with the correct type", - ty.to_string(), - Applicability::MaybeIncorrect, - ); - } - diag.emit(); - } - } - - ty -} - -fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { - use rustc_hir::*; - - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - - let icx = ItemCtxt::new(tcx, def_id); - - match tcx.hir().get(hir_id) { - Node::TraitItem(item) => match item.kind { - TraitItemKind::Method(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - TraitItemKind::Const(ref ty, body_id) => body_id - .and_then(|body_id| { - if is_suggestable_infer_ty(ty) { - Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) - } else { - None - } - }) - .unwrap_or_else(|| icx.to_ty(ty)), - TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), - TraitItemKind::Type(_, None) => { - span_bug!(item.span, "associated type missing default"); - } - }, - - Node::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - ImplItemKind::Const(ref ty, body_id) => { - if is_suggestable_infer_ty(ty) { - infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) - } else { - icx.to_ty(ty) - } - } - ImplItemKind::OpaqueTy(_) => { - if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); - } - - find_opaque_ty_constraints(tcx, def_id) - } - ImplItemKind::TyAlias(ref ty) => { - if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() { - report_assoc_ty_on_inherent_impl(tcx, item.span); - } - - icx.to_ty(ty) - } - }, - - Node::Item(item) => { - match item.kind { - ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { - if is_suggestable_infer_ty(ty) { - infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) - } else { - icx.to_ty(ty) - } - } - ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => { - icx.to_ty(self_ty) - } - ItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { - let def = tcx.adt_def(def_id); - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_adt(def, substs) - } - ItemKind::OpaqueTy(hir::OpaqueTy { impl_trait_fn: None, .. }) => { - find_opaque_ty_constraints(tcx, def_id) - } - // Opaque types desugared from `impl Trait`. - ItemKind::OpaqueTy(hir::OpaqueTy { - impl_trait_fn: Some(owner), origin, .. - }) => { - let concrete_types = match origin { - hir::OpaqueTyOrigin::FnReturn | hir::OpaqueTyOrigin::AsyncFn => { - &tcx.mir_borrowck(owner).concrete_opaque_types - } - hir::OpaqueTyOrigin::Misc => { - // We shouldn't leak borrowck results through impl trait in bindings. - // For example, we shouldn't be able to tell if `x` in - // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`. - &tcx.typeck_tables_of(owner).concrete_opaque_types - } - hir::OpaqueTyOrigin::TypeAlias => { - span_bug!(item.span, "Type alias impl trait shouldn't have an owner") - } - }; - let concrete_ty = concrete_types - .get(&def_id) - .map(|opaque| opaque.concrete_type) - .unwrap_or_else(|| { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!( - "owner {:?} has no opaque type for {:?} in its tables", - owner, def_id, - ), - ); - if tcx.typeck_tables_of(owner).tainted_by_errors { - // Some error in the - // owner fn prevented us from populating - // the `concrete_opaque_types` table. - tcx.types.err - } else { - // We failed to resolve the opaque type or it - // resolves to itself. Return the non-revealed - // type, which should result in E0720. - tcx.mk_opaque( - def_id, - InternalSubsts::identity_for_item(tcx, def_id), - ) - } - }); - debug!("concrete_ty = {:?}", concrete_ty); - if concrete_ty.has_erased_regions() { - // FIXME(impl_trait_in_bindings) Handle this case. - tcx.sess.span_fatal( - item.span, - "lifetimes in impl Trait types in bindings are not currently supported", - ); - } - concrete_ty - } - ItemKind::Trait(..) - | ItemKind::TraitAlias(..) - | ItemKind::Mod(..) - | ItemKind::ForeignMod(..) - | ItemKind::GlobalAsm(..) - | ItemKind::ExternCrate(..) - | ItemKind::Use(..) => { - span_bug!( - item.span, - "compute_type_of_item: unexpected item type: {:?}", - item.kind - ); - } - } - } - - Node::ForeignItem(foreign_item) => match foreign_item.kind { - ForeignItemKind::Fn(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - ForeignItemKind::Static(ref t, _) => icx.to_ty(t), - ForeignItemKind::Type => tcx.mk_foreign(def_id), - }, - - 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)) - } - VariantData::Tuple(..) => { - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_fn_def(def_id, substs) - } - }, - - Node::Field(field) => icx.to_ty(&field.ty), - - Node::Expr(&hir::Expr { kind: hir::ExprKind::Closure(.., gen), .. }) => { - if gen.is_some() { - return tcx.typeck_tables_of(def_id).node_type(hir_id); - } - - let substs = InternalSubsts::identity_for_item(tcx, def_id); - tcx.mk_closure(def_id, substs) - } - - Node::AnonConst(_) => { - let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); - match parent_node { - Node::Ty(&hir::Ty { kind: hir::TyKind::Array(_, ref constant), .. }) - | Node::Ty(&hir::Ty { kind: hir::TyKind::Typeof(ref constant), .. }) - | Node::Expr(&hir::Expr { kind: ExprKind::Repeat(_, ref constant), .. }) - if constant.hir_id == hir_id => - { - tcx.types.usize - } - - Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { - tcx.adt_def(tcx.hir().get_parent_did(hir_id)).repr.discr_type().to_ty(tcx) - } - - Node::Ty(&hir::Ty { kind: hir::TyKind::Path(_), .. }) - | Node::Expr(&hir::Expr { kind: ExprKind::Struct(..), .. }) - | Node::Expr(&hir::Expr { kind: ExprKind::Path(_), .. }) - | Node::TraitRef(..) => { - let path = match parent_node { - Node::Ty(&hir::Ty { - kind: hir::TyKind::Path(QPath::Resolved(_, ref path)), - .. - }) - | Node::Expr(&hir::Expr { - kind: ExprKind::Path(QPath::Resolved(_, ref path)), - .. - }) => Some(&**path), - Node::Expr(&hir::Expr { kind: ExprKind::Struct(ref path, ..), .. }) => { - if let QPath::Resolved(_, ref path) = **path { - Some(&**path) - } else { - None - } - } - Node::TraitRef(&hir::TraitRef { ref path, .. }) => Some(&**path), - _ => None, - }; - - if let Some(path) = path { - let arg_index = path - .segments - .iter() - .filter_map(|seg| seg.args.as_ref()) - .map(|generic_args| generic_args.args.as_ref()) - .find_map(|args| { - args.iter() - .filter(|arg| arg.is_const()) - .enumerate() - .filter(|(_, arg)| arg.id() == hir_id) - .map(|(index, _)| index) - .next() - }) - .unwrap_or_else(|| { - bug!("no arg matching AnonConst in path"); - }); - - // We've encountered an `AnonConst` in some path, so we need to - // figure out which generic parameter it corresponds to and return - // the relevant type. - let generics = match path.res { - Res::Def(DefKind::Ctor(..), def_id) => { - tcx.generics_of(tcx.parent(def_id).unwrap()) - } - Res::Def(_, def_id) => tcx.generics_of(def_id), - Res::Err => return tcx.types.err, - res => { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!("unexpected const parent path def {:?}", res,), - ); - return tcx.types.err; - } - }; - - generics - .params - .iter() - .filter(|param| { - if let ty::GenericParamDefKind::Const = param.kind { - true - } else { - false - } - }) - .nth(arg_index) - .map(|param| tcx.type_of(param.def_id)) - // This is no generic parameter associated with the arg. This is - // probably from an extra arg where one is not needed. - .unwrap_or(tcx.types.err) - } else { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!("unexpected const parent path {:?}", parent_node,), - ); - return tcx.types.err; - } - } - - x => { - tcx.sess.delay_span_bug( - DUMMY_SP, - &format!("unexpected const parent in type_of_def_id(): {:?}", x), - ); - tcx.types.err - } - } - } - - Node::GenericParam(param) => match ¶m.kind { - hir::GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), - hir::GenericParamKind::Const { ty: ref hir_ty, .. } => { - let ty = icx.to_ty(hir_ty); - if !tcx.features().const_compare_raw_pointers { - let err = match ty.peel_refs().kind { - ty::FnPtr(_) => Some("function pointers"), - ty::RawPtr(_) => Some("raw pointers"), - _ => None, - }; - if let Some(unsupported_type) = err { - feature_err( - &tcx.sess.parse_sess, - sym::const_compare_raw_pointers, - hir_ty.span, - &format!( - "using {} as const generic parameters is unstable", - unsupported_type - ), - ) - .emit(); - }; - } - if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty) - .is_some() - { - struct_span_err!( - tcx.sess, - hir_ty.span, - E0741, - "the types of const generic parameters must derive `PartialEq` and `Eq`", - ) - .span_label( - hir_ty.span, - format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), - ) - .emit(); - } - ty - } - x => bug!("unexpected non-type Node::GenericParam: {:?}", x), - }, - - x => { - bug!("unexpected sort of node in type_of_def_id(): {:?}", x); - } - } -} - -fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { - use rustc_hir::{Expr, ImplItem, Item, TraitItem}; - - debug!("find_opaque_ty_constraints({:?})", def_id); - - struct ConstraintLocator<'tcx> { - tcx: TyCtxt<'tcx>, - def_id: DefId, - // (first found type span, actual type, mapping from the opaque type's generic - // parameters to the concrete type's generic parameters) - // - // The mapping is an index for each use site of a generic parameter in the concrete type - // - // The indices index into the generic parameters on the opaque type. - found: Option<(Span, Ty<'tcx>, Vec)>, - } - - impl ConstraintLocator<'tcx> { - fn check(&mut self, def_id: DefId) { - // Don't try to check items that cannot possibly constrain the type. - if !self.tcx.has_typeck_tables(def_id) { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables", - self.def_id, def_id, - ); - return; - } - // Calling `mir_borrowck` can lead to cycle errors through - // const-checking, avoid calling it if we don't have to. - if !self.tcx.typeck_tables_of(def_id).concrete_opaque_types.contains_key(&self.def_id) { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", - self.def_id, def_id, - ); - return; - } - // Use borrowck to get the type with unerased regions. - let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id); - if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty { - debug!( - "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", - self.def_id, def_id, ty, - ); - - // FIXME(oli-obk): trace the actual span from inference to improve errors. - let span = self.tcx.def_span(def_id); - // used to quickly look up the position of a generic parameter - let mut index_map: FxHashMap = FxHashMap::default(); - // Skipping binder is ok, since we only use this to find generic parameters and - // their positions. - for (idx, subst) in substs.iter().enumerate() { - if let GenericArgKind::Type(ty) = subst.unpack() { - if let ty::Param(p) = ty.kind { - if index_map.insert(p, idx).is_some() { - // There was already an entry for `p`, meaning a generic parameter - // was used twice. - self.tcx.sess.span_err( - span, - &format!( - "defining opaque type use restricts opaque \ - type by using the generic parameter `{}` twice", - p, - ), - ); - return; - } - } else { - self.tcx.sess.delay_span_bug( - span, - &format!( - "non-defining opaque ty use in defining scope: {:?}, {:?}", - concrete_type, substs, - ), - ); - } - } - } - // Compute the index within the opaque type for each generic parameter used in - // the concrete type. - let indices = concrete_type - .subst(self.tcx, substs) - .walk() - .filter_map(|t| match &t.kind { - ty::Param(p) => Some(*index_map.get(p).unwrap()), - _ => None, - }) - .collect(); - let is_param = |ty: Ty<'_>| match ty.kind { - ty::Param(_) => true, - _ => false, - }; - let bad_substs: Vec<_> = substs - .iter() - .enumerate() - .filter_map(|(i, k)| { - if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None } - }) - .filter(|(_, ty)| !is_param(ty)) - .collect(); - - if !bad_substs.is_empty() { - let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id); - for (i, bad_subst) in bad_substs { - self.tcx.sess.span_err( - span, - &format!( - "defining opaque type use does not fully define opaque type: \ - generic parameter `{}` is specified as concrete type `{}`", - identity_substs.type_at(i), - bad_subst - ), - ); - } - } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { - let mut ty = concrete_type.walk().fuse(); - let mut p_ty = prev_ty.walk().fuse(); - let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) { - // Type parameters are equal to any other type parameter for the purpose of - // concrete type equality, as it is possible to obtain the same type just - // by passing matching parameters to a function. - (ty::Param(_), ty::Param(_)) => true, - _ => t == p, - }); - if !iter_eq || ty.next().is_some() || p_ty.next().is_some() { - debug!("find_opaque_ty_constraints: span={:?}", span); - // Found different concrete types for the opaque type. - let mut err = self.tcx.sess.struct_span_err( - span, - "concrete type differs from previous defining opaque type use", - ); - err.span_label( - span, - format!("expected `{}`, got `{}`", prev_ty, concrete_type), - ); - err.span_note(prev_span, "previous use here"); - err.emit(); - } else if indices != *prev_indices { - // Found "same" concrete types, but the generic parameter order differs. - let mut err = self.tcx.sess.struct_span_err( - span, - "concrete type's generic parameters differ from previous defining use", - ); - use std::fmt::Write; - let mut s = String::new(); - write!(s, "expected [").unwrap(); - let list = |s: &mut String, indices: &Vec| { - let mut indices = indices.iter().cloned(); - if let Some(first) = indices.next() { - write!(s, "`{}`", substs[first]).unwrap(); - for i in indices { - write!(s, ", `{}`", substs[i]).unwrap(); - } - } - }; - list(&mut s, prev_indices); - write!(s, "], got [").unwrap(); - list(&mut s, &indices); - write!(s, "]").unwrap(); - err.span_label(span, s); - err.span_note(prev_span, "previous use here"); - err.emit(); - } - } else { - self.found = Some((span, concrete_type, indices)); - } - } else { - debug!( - "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", - self.def_id, def_id, - ); - } - } - } - - impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { - type Map = Map<'tcx>; - - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) - } - fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { - if let hir::ExprKind::Closure(..) = ex.kind { - let def_id = self.tcx.hir().local_def_id(ex.hir_id); - self.check(def_id); - } - intravisit::walk_expr(self, ex); - } - fn visit_item(&mut self, it: &'tcx Item<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); - let def_id = self.tcx.hir().local_def_id(it.hir_id); - // The opaque type itself or its children are not within its reveal scope. - if def_id != self.def_id { - self.check(def_id); - intravisit::walk_item(self, it); - } - } - fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); - let def_id = self.tcx.hir().local_def_id(it.hir_id); - // The opaque type itself or its children are not within its reveal scope. - if def_id != self.def_id { - self.check(def_id); - intravisit::walk_impl_item(self, it); - } - } - fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { - debug!("find_existential_constraints: visiting {:?}", it); - let def_id = self.tcx.hir().local_def_id(it.hir_id); - self.check(def_id); - intravisit::walk_trait_item(self, it); - } - } - - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let scope = tcx.hir().get_defining_scope(hir_id); - let mut locator = ConstraintLocator { def_id, tcx, found: None }; - - debug!("find_opaque_ty_constraints: scope={:?}", scope); - - if scope == hir::CRATE_HIR_ID { - intravisit::walk_crate(&mut locator, tcx.hir().krate()); - } else { - debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope)); - match tcx.hir().get(scope) { - // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods - // This allows our visitor to process the defining item itself, causing - // it to pick up any 'sibling' defining uses. - // - // For example, this code: - // ``` - // fn foo() { - // type Blah = impl Debug; - // let my_closure = || -> Blah { true }; - // } - // ``` - // - // requires us to explicitly process `foo()` in order - // to notice the defining usage of `Blah`. - Node::Item(ref it) => locator.visit_item(it), - Node::ImplItem(ref it) => locator.visit_impl_item(it), - Node::TraitItem(ref it) => locator.visit_trait_item(it), - other => bug!("{:?} is not a valid scope for an opaque type item", other), - } - } - - match locator.found { - Some((_, ty, _)) => ty, - None => { - let span = tcx.def_span(def_id); - tcx.sess.span_err(span, "could not find defining uses"); - tcx.types.err - } - } -} - fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { generic_args .iter() diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs new file mode 100644 index 00000000000..8b6dba749a6 --- /dev/null +++ b/src/librustc_typeck/collect/type_of.rs @@ -0,0 +1,661 @@ +use rustc::hir::map::Map; +use rustc::session::parse::feature_err; +use rustc::traits; +use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst}; +use rustc::ty::util::IntTypeExt; +use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{struct_span_err, Applicability, StashKey}; +use rustc_hir as hir; +use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit; +use rustc_hir::intravisit::Visitor; +use rustc_hir::Node; +use rustc_span::symbol::{sym, Ident}; +use rustc_span::{Span, DUMMY_SP}; + +use super::ItemCtxt; +use super::{bad_placeholder_type, is_suggestable_infer_ty}; + +pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { + use rustc_hir::*; + + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + + let icx = ItemCtxt::new(tcx, def_id); + + match tcx.hir().get(hir_id) { + Node::TraitItem(item) => match item.kind { + TraitItemKind::Method(..) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + TraitItemKind::Const(ref ty, body_id) => body_id + .and_then(|body_id| { + if is_suggestable_infer_ty(ty) { + Some(infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident)) + } else { + None + } + }) + .unwrap_or_else(|| icx.to_ty(ty)), + TraitItemKind::Type(_, Some(ref ty)) => icx.to_ty(ty), + TraitItemKind::Type(_, None) => { + span_bug!(item.span, "associated type missing default"); + } + }, + + Node::ImplItem(item) => match item.kind { + ImplItemKind::Method(..) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + ImplItemKind::Const(ref ty, body_id) => { + if is_suggestable_infer_ty(ty) { + infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + } else { + icx.to_ty(ty) + } + } + ImplItemKind::OpaqueTy(_) => { + if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() { + report_assoc_ty_on_inherent_impl(tcx, item.span); + } + + find_opaque_ty_constraints(tcx, def_id) + } + ImplItemKind::TyAlias(ref ty) => { + if tcx.impl_trait_ref(tcx.hir().get_parent_did(hir_id)).is_none() { + report_assoc_ty_on_inherent_impl(tcx, item.span); + } + + icx.to_ty(ty) + } + }, + + Node::Item(item) => { + match item.kind { + ItemKind::Static(ref ty, .., body_id) | ItemKind::Const(ref ty, body_id) => { + if is_suggestable_infer_ty(ty) { + infer_placeholder_type(tcx, def_id, body_id, ty.span, item.ident) + } else { + icx.to_ty(ty) + } + } + ItemKind::TyAlias(ref self_ty, _) | ItemKind::Impl { ref self_ty, .. } => { + icx.to_ty(self_ty) + } + ItemKind::Fn(..) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + ItemKind::Enum(..) | ItemKind::Struct(..) | ItemKind::Union(..) => { + let def = tcx.adt_def(def_id); + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_adt(def, substs) + } + ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: None, .. }) => { + find_opaque_ty_constraints(tcx, def_id) + } + // Opaque types desugared from `impl Trait`. + ItemKind::OpaqueTy(OpaqueTy { impl_trait_fn: Some(owner), origin, .. }) => { + let concrete_types = match origin { + OpaqueTyOrigin::FnReturn | OpaqueTyOrigin::AsyncFn => { + &tcx.mir_borrowck(owner).concrete_opaque_types + } + OpaqueTyOrigin::Misc => { + // We shouldn't leak borrowck results through impl trait in bindings. + // For example, we shouldn't be able to tell if `x` in + // `let x: impl Sized + 'a = &()` has type `&'static ()` or `&'a ()`. + &tcx.typeck_tables_of(owner).concrete_opaque_types + } + OpaqueTyOrigin::TypeAlias => { + span_bug!(item.span, "Type alias impl trait shouldn't have an owner") + } + }; + let concrete_ty = concrete_types + .get(&def_id) + .map(|opaque| opaque.concrete_type) + .unwrap_or_else(|| { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!( + "owner {:?} has no opaque type for {:?} in its tables", + owner, def_id, + ), + ); + if tcx.typeck_tables_of(owner).tainted_by_errors { + // Some error in the + // owner fn prevented us from populating + // the `concrete_opaque_types` table. + tcx.types.err + } else { + // We failed to resolve the opaque type or it + // resolves to itself. Return the non-revealed + // type, which should result in E0720. + tcx.mk_opaque( + def_id, + InternalSubsts::identity_for_item(tcx, def_id), + ) + } + }); + debug!("concrete_ty = {:?}", concrete_ty); + if concrete_ty.has_erased_regions() { + // FIXME(impl_trait_in_bindings) Handle this case. + tcx.sess.span_fatal( + item.span, + "lifetimes in impl Trait types in bindings are not currently supported", + ); + } + concrete_ty + } + ItemKind::Trait(..) + | ItemKind::TraitAlias(..) + | ItemKind::Mod(..) + | ItemKind::ForeignMod(..) + | ItemKind::GlobalAsm(..) + | ItemKind::ExternCrate(..) + | ItemKind::Use(..) => { + span_bug!( + item.span, + "compute_type_of_item: unexpected item type: {:?}", + item.kind + ); + } + } + } + + Node::ForeignItem(foreign_item) => match foreign_item.kind { + ForeignItemKind::Fn(..) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + ForeignItemKind::Static(ref t, _) => icx.to_ty(t), + ForeignItemKind::Type => tcx.mk_foreign(def_id), + }, + + Node::Ctor(&ref def) | Node::Variant(Variant { data: ref def, .. }) => match *def { + VariantData::Unit(..) | VariantData::Struct(..) => { + tcx.type_of(tcx.hir().get_parent_did(hir_id)) + } + VariantData::Tuple(..) => { + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_fn_def(def_id, substs) + } + }, + + Node::Field(field) => icx.to_ty(&field.ty), + + Node::Expr(&Expr { kind: ExprKind::Closure(.., gen), .. }) => { + if gen.is_some() { + return tcx.typeck_tables_of(def_id).node_type(hir_id); + } + + let substs = InternalSubsts::identity_for_item(tcx, def_id); + tcx.mk_closure(def_id, substs) + } + + Node::AnonConst(_) => { + let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id)); + match parent_node { + Node::Ty(&Ty { kind: TyKind::Array(_, ref constant), .. }) + | Node::Ty(&Ty { kind: TyKind::Typeof(ref constant), .. }) + | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. }) + if constant.hir_id == hir_id => + { + tcx.types.usize + } + + Node::Variant(Variant { disr_expr: Some(ref e), .. }) if e.hir_id == hir_id => { + tcx.adt_def(tcx.hir().get_parent_did(hir_id)).repr.discr_type().to_ty(tcx) + } + + Node::Ty(&Ty { kind: TyKind::Path(_), .. }) + | Node::Expr(&Expr { kind: ExprKind::Struct(..), .. }) + | Node::Expr(&Expr { kind: ExprKind::Path(_), .. }) + | Node::TraitRef(..) => { + let path = match parent_node { + Node::Ty(&Ty { + kind: TyKind::Path(QPath::Resolved(_, ref path)), .. + }) + | Node::Expr(&Expr { + kind: ExprKind::Path(QPath::Resolved(_, ref path)), + .. + }) => Some(&**path), + Node::Expr(&Expr { kind: ExprKind::Struct(ref path, ..), .. }) => { + if let QPath::Resolved(_, ref path) = **path { + Some(&**path) + } else { + None + } + } + Node::TraitRef(&TraitRef { ref path, .. }) => Some(&**path), + _ => None, + }; + + if let Some(path) = path { + let arg_index = path + .segments + .iter() + .filter_map(|seg| seg.args.as_ref()) + .map(|generic_args| generic_args.args.as_ref()) + .find_map(|args| { + args.iter() + .filter(|arg| arg.is_const()) + .enumerate() + .filter(|(_, arg)| arg.id() == hir_id) + .map(|(index, _)| index) + .next() + }) + .unwrap_or_else(|| { + bug!("no arg matching AnonConst in path"); + }); + + // We've encountered an `AnonConst` in some path, so we need to + // figure out which generic parameter it corresponds to and return + // the relevant type. + let generics = match path.res { + Res::Def(DefKind::Ctor(..), def_id) => { + tcx.generics_of(tcx.parent(def_id).unwrap()) + } + Res::Def(_, def_id) => tcx.generics_of(def_id), + Res::Err => return tcx.types.err, + res => { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!("unexpected const parent path def {:?}", res,), + ); + return tcx.types.err; + } + }; + + generics + .params + .iter() + .filter(|param| { + if let ty::GenericParamDefKind::Const = param.kind { + true + } else { + false + } + }) + .nth(arg_index) + .map(|param| tcx.type_of(param.def_id)) + // This is no generic parameter associated with the arg. This is + // probably from an extra arg where one is not needed. + .unwrap_or(tcx.types.err) + } else { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!("unexpected const parent path {:?}", parent_node,), + ); + return tcx.types.err; + } + } + + x => { + tcx.sess.delay_span_bug( + DUMMY_SP, + &format!("unexpected const parent in type_of_def_id(): {:?}", x), + ); + tcx.types.err + } + } + } + + Node::GenericParam(param) => match ¶m.kind { + GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty), + GenericParamKind::Const { ty: ref hir_ty, .. } => { + let ty = icx.to_ty(hir_ty); + if !tcx.features().const_compare_raw_pointers { + let err = match ty.peel_refs().kind { + ty::FnPtr(_) => Some("function pointers"), + ty::RawPtr(_) => Some("raw pointers"), + _ => None, + }; + if let Some(unsupported_type) = err { + feature_err( + &tcx.sess.parse_sess, + sym::const_compare_raw_pointers, + hir_ty.span, + &format!( + "using {} as const generic parameters is unstable", + unsupported_type + ), + ) + .emit(); + }; + } + if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty) + .is_some() + { + struct_span_err!( + tcx.sess, + hir_ty.span, + E0741, + "the types of const generic parameters must derive `PartialEq` and `Eq`", + ) + .span_label( + hir_ty.span, + format!("`{}` doesn't derive both `PartialEq` and `Eq`", ty), + ) + .emit(); + } + ty + } + x => bug!("unexpected non-type Node::GenericParam: {:?}", x), + }, + + x => { + bug!("unexpected sort of node in type_of_def_id(): {:?}", x); + } + } +} + +fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { + use rustc_hir::{Expr, ImplItem, Item, TraitItem}; + + debug!("find_opaque_ty_constraints({:?})", def_id); + + struct ConstraintLocator<'tcx> { + tcx: TyCtxt<'tcx>, + def_id: DefId, + // (first found type span, actual type, mapping from the opaque type's generic + // parameters to the concrete type's generic parameters) + // + // The mapping is an index for each use site of a generic parameter in the concrete type + // + // The indices index into the generic parameters on the opaque type. + found: Option<(Span, Ty<'tcx>, Vec)>, + } + + impl ConstraintLocator<'_> { + fn check(&mut self, def_id: DefId) { + // Don't try to check items that cannot possibly constrain the type. + if !self.tcx.has_typeck_tables(def_id) { + debug!( + "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`: no tables", + self.def_id, def_id, + ); + return; + } + // Calling `mir_borrowck` can lead to cycle errors through + // const-checking, avoid calling it if we don't have to. + if !self.tcx.typeck_tables_of(def_id).concrete_opaque_types.contains_key(&self.def_id) { + debug!( + "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", + self.def_id, def_id, + ); + return; + } + // Use borrowck to get the type with unerased regions. + let ty = self.tcx.mir_borrowck(def_id).concrete_opaque_types.get(&self.def_id); + if let Some(ty::ResolvedOpaqueTy { concrete_type, substs }) = ty { + debug!( + "find_opaque_ty_constraints: found constraint for `{:?}` at `{:?}`: {:?}", + self.def_id, def_id, ty, + ); + + // FIXME(oli-obk): trace the actual span from inference to improve errors. + let span = self.tcx.def_span(def_id); + // used to quickly look up the position of a generic parameter + let mut index_map: FxHashMap = FxHashMap::default(); + // Skipping binder is ok, since we only use this to find generic parameters and + // their positions. + for (idx, subst) in substs.iter().enumerate() { + if let GenericArgKind::Type(ty) = subst.unpack() { + if let ty::Param(p) = ty.kind { + if index_map.insert(p, idx).is_some() { + // There was already an entry for `p`, meaning a generic parameter + // was used twice. + self.tcx.sess.span_err( + span, + &format!( + "defining opaque type use restricts opaque \ + type by using the generic parameter `{}` twice", + p, + ), + ); + return; + } + } else { + self.tcx.sess.delay_span_bug( + span, + &format!( + "non-defining opaque ty use in defining scope: {:?}, {:?}", + concrete_type, substs, + ), + ); + } + } + } + // Compute the index within the opaque type for each generic parameter used in + // the concrete type. + let indices = concrete_type + .subst(self.tcx, substs) + .walk() + .filter_map(|t| match &t.kind { + ty::Param(p) => Some(*index_map.get(p).unwrap()), + _ => None, + }) + .collect(); + let is_param = |ty: Ty<'_>| match ty.kind { + ty::Param(_) => true, + _ => false, + }; + let bad_substs: Vec<_> = substs + .iter() + .enumerate() + .filter_map(|(i, k)| { + if let GenericArgKind::Type(ty) = k.unpack() { Some((i, ty)) } else { None } + }) + .filter(|(_, ty)| !is_param(ty)) + .collect(); + if !bad_substs.is_empty() { + let identity_substs = InternalSubsts::identity_for_item(self.tcx, self.def_id); + for (i, bad_subst) in bad_substs { + self.tcx.sess.span_err( + span, + &format!( + "defining opaque type use does not fully define opaque type: \ + generic parameter `{}` is specified as concrete type `{}`", + identity_substs.type_at(i), + bad_subst + ), + ); + } + } else if let Some((prev_span, prev_ty, ref prev_indices)) = self.found { + let mut ty = concrete_type.walk().fuse(); + let mut p_ty = prev_ty.walk().fuse(); + let iter_eq = (&mut ty).zip(&mut p_ty).all(|(t, p)| match (&t.kind, &p.kind) { + // Type parameters are equal to any other type parameter for the purpose of + // concrete type equality, as it is possible to obtain the same type just + // by passing matching parameters to a function. + (ty::Param(_), ty::Param(_)) => true, + _ => t == p, + }); + if !iter_eq || ty.next().is_some() || p_ty.next().is_some() { + debug!("find_opaque_ty_constraints: span={:?}", span); + // Found different concrete types for the opaque type. + let mut err = self.tcx.sess.struct_span_err( + span, + "concrete type differs from previous defining opaque type use", + ); + err.span_label( + span, + format!("expected `{}`, got `{}`", prev_ty, concrete_type), + ); + err.span_note(prev_span, "previous use here"); + err.emit(); + } else if indices != *prev_indices { + // Found "same" concrete types, but the generic parameter order differs. + let mut err = self.tcx.sess.struct_span_err( + span, + "concrete type's generic parameters differ from previous defining use", + ); + use std::fmt::Write; + let mut s = String::new(); + write!(s, "expected [").unwrap(); + let list = |s: &mut String, indices: &Vec| { + let mut indices = indices.iter().cloned(); + if let Some(first) = indices.next() { + write!(s, "`{}`", substs[first]).unwrap(); + for i in indices { + write!(s, ", `{}`", substs[i]).unwrap(); + } + } + }; + list(&mut s, prev_indices); + write!(s, "], got [").unwrap(); + list(&mut s, &indices); + write!(s, "]").unwrap(); + err.span_label(span, s); + err.span_note(prev_span, "previous use here"); + err.emit(); + } + } else { + self.found = Some((span, concrete_type, indices)); + } + } else { + debug!( + "find_opaque_ty_constraints: no constraint for `{:?}` at `{:?}`", + self.def_id, def_id, + ); + } + } + } + + impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { + type Map = Map<'tcx>; + + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + intravisit::NestedVisitorMap::All(&self.tcx.hir()) + } + fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { + if let hir::ExprKind::Closure(..) = ex.kind { + let def_id = self.tcx.hir().local_def_id(ex.hir_id); + self.check(def_id); + } + intravisit::walk_expr(self, ex); + } + fn visit_item(&mut self, it: &'tcx Item<'tcx>) { + debug!("find_existential_constraints: visiting {:?}", it); + let def_id = self.tcx.hir().local_def_id(it.hir_id); + // The opaque type itself or its children are not within its reveal scope. + if def_id != self.def_id { + self.check(def_id); + intravisit::walk_item(self, it); + } + } + fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) { + debug!("find_existential_constraints: visiting {:?}", it); + let def_id = self.tcx.hir().local_def_id(it.hir_id); + // The opaque type itself or its children are not within its reveal scope. + if def_id != self.def_id { + self.check(def_id); + intravisit::walk_impl_item(self, it); + } + } + fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) { + debug!("find_existential_constraints: visiting {:?}", it); + let def_id = self.tcx.hir().local_def_id(it.hir_id); + self.check(def_id); + intravisit::walk_trait_item(self, it); + } + } + + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + let scope = tcx.hir().get_defining_scope(hir_id); + let mut locator = ConstraintLocator { def_id, tcx, found: None }; + + debug!("find_opaque_ty_constraints: scope={:?}", scope); + + if scope == hir::CRATE_HIR_ID { + intravisit::walk_crate(&mut locator, tcx.hir().krate()); + } else { + debug!("find_opaque_ty_constraints: scope={:?}", tcx.hir().get(scope)); + match tcx.hir().get(scope) { + // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods + // This allows our visitor to process the defining item itself, causing + // it to pick up any 'sibling' defining uses. + // + // For example, this code: + // ``` + // fn foo() { + // type Blah = impl Debug; + // let my_closure = || -> Blah { true }; + // } + // ``` + // + // requires us to explicitly process `foo()` in order + // to notice the defining usage of `Blah`. + Node::Item(ref it) => locator.visit_item(it), + Node::ImplItem(ref it) => locator.visit_impl_item(it), + Node::TraitItem(ref it) => locator.visit_trait_item(it), + other => bug!("{:?} is not a valid scope for an opaque type item", other), + } + } + + match locator.found { + Some((_, ty, _)) => ty, + None => { + let span = tcx.def_span(def_id); + tcx.sess.span_err(span, "could not find defining uses"); + tcx.types.err + } + } +} + +fn infer_placeholder_type( + tcx: TyCtxt<'_>, + def_id: DefId, + body_id: hir::BodyId, + span: Span, + item_ident: Ident, +) -> Ty<'_> { + let ty = tcx.diagnostic_only_typeck_tables_of(def_id).node_type(body_id.hir_id); + + // If this came from a free `const` or `static mut?` item, + // then the user may have written e.g. `const A = 42;`. + // In this case, the parser has stashed a diagnostic for + // us to improve in typeck so we do that now. + match tcx.sess.diagnostic().steal_diagnostic(span, StashKey::ItemNoType) { + Some(mut err) => { + // The parser provided a sub-optimal `HasPlaceholders` suggestion for the type. + // We are typeck and have the real type, so remove that and suggest the actual type. + err.suggestions.clear(); + err.span_suggestion( + span, + "provide a type for the item", + format!("{}: {}", item_ident, ty), + Applicability::MachineApplicable, + ) + .emit(); + } + None => { + let mut diag = bad_placeholder_type(tcx, vec![span]); + if ty != tcx.types.err { + diag.span_suggestion( + span, + "replace `_` with the correct type", + ty.to_string(), + Applicability::MaybeIncorrect, + ); + } + diag.emit(); + } + } + + ty +} + +fn report_assoc_ty_on_inherent_impl(tcx: TyCtxt<'_>, span: Span) { + struct_span_err!( + tcx.sess, + span, + E0202, + "associated types are not yet supported in inherent impls (see #8995)" + ) + .emit(); +} From d863978f89c74bd5cb90baa47331d421bbfd3936 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 14 Feb 2020 22:39:55 +0000 Subject: [PATCH 0178/1250] Fix tests after rebase --- src/libstd/future.rs | 3 +- src/test/ui/async-await/no-const-async.rs | 1 + src/test/ui/async-await/no-const-async.stderr | 12 +++- ...row-immutable-upvar-mutation-impl-trait.rs | 14 +++++ ...immutable-upvar-mutation-impl-trait.stderr | 16 +++++ .../borrow-immutable-upvar-mutation.rs | 26 ++++---- .../borrow-immutable-upvar-mutation.stderr | 61 ++++++++----------- 7 files changed, 82 insertions(+), 51 deletions(-) create mode 100644 src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs create mode 100644 src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr diff --git a/src/libstd/future.rs b/src/libstd/future.rs index f74c84e6dfd..7b1beb1ecda 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -16,9 +16,10 @@ pub use core::future::*; /// /// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give /// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`). +// This is `const` to avoid extra errors after we recover from `const async fn` #[doc(hidden)] #[unstable(feature = "gen_future", issue = "50547")] -pub fn from_generator>(x: T) -> impl Future { +pub const fn from_generator>(x: T) -> impl Future { GenFuture(x) } diff --git a/src/test/ui/async-await/no-const-async.rs b/src/test/ui/async-await/no-const-async.rs index b3c59734e03..57a9f175ca3 100644 --- a/src/test/ui/async-await/no-const-async.rs +++ b/src/test/ui/async-await/no-const-async.rs @@ -3,3 +3,4 @@ pub const async fn x() {} //~^ ERROR functions cannot be both `const` and `async` +//~| ERROR `impl Trait` in const fn is unstable diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index f6ae0f1447c..07559cd240b 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -7,5 +7,15 @@ LL | pub const async fn x() {} | | `async` because of this | `const` because of this -error: aborting due to previous error +error[E0723]: `impl Trait` in const fn is unstable + --> $DIR/no-const-async.rs:4:24 + | +LL | pub const async fn x() {} + | ^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs new file mode 100644 index 00000000000..57198cb95e7 --- /dev/null +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.rs @@ -0,0 +1,14 @@ +#![feature(unboxed_closures)] + +// Tests that we can't assign to or mutably borrow upvars from `Fn` +// closures (issue #17780) + +fn main() {} + +fn bar() -> impl Fn() -> usize { + let mut x = 0; + move || { + x += 1; //~ ERROR cannot assign + x + } +} diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr new file mode 100644 index 00000000000..003c40d2773 --- /dev/null +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation-impl-trait.stderr @@ -0,0 +1,16 @@ +error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure + --> $DIR/borrow-immutable-upvar-mutation-impl-trait.rs:11:9 + | +LL | fn bar() -> impl Fn() -> usize { + | --- ------------------ change this to return `FnMut` instead of `Fn` +LL | let mut x = 0; +LL | / move || { +LL | | x += 1; + | | ^^^^^^ cannot assign +LL | | x +LL | | } + | |_____- in this closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0594`. diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs index 62e27bcf164..e2f016614bf 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.rs @@ -3,10 +3,16 @@ // Tests that we can't assign to or mutably borrow upvars from `Fn` // closures (issue #17780) -fn set(x: &mut usize) { *x = 5; } +fn set(x: &mut usize) { + *x = 5; +} -fn to_fn>(f: F) -> F { f } -fn to_fn_mut>(f: F) -> F { f } +fn to_fn>(f: F) -> F { + f +} +fn to_fn_mut>(f: F) -> F { + f +} fn main() { // By-ref captures @@ -33,7 +39,11 @@ fn main() { let _g = to_fn(move || set(&mut y)); //~ ERROR cannot borrow let mut z = 0; - let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); //~ ERROR cannot assign + let _h = to_fn_mut(move || { + set(&mut z); + to_fn(move || z = 42); + //~^ ERROR cannot assign + }); } } @@ -44,11 +54,3 @@ fn foo() -> Box usize> { x }) } - -fn bar() -> impl Fn() -> usize { - let mut x = 0; - move || { - x += 1; //~ ERROR cannot assign - x - } -} diff --git a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr index 3046b047d00..a28cb7431e6 100644 --- a/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/src/test/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -1,8 +1,8 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:15:27 + --> $DIR/borrow-immutable-upvar-mutation.rs:21:27 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(|| x = 42); | ----- ^^^^^^ cannot assign @@ -10,10 +10,10 @@ LL | let _f = to_fn(|| x = 42); | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:18:31 + --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(|| set(&mut y)); | ----- ^^^^^^ cannot borrow as mutable @@ -21,10 +21,10 @@ LL | let _g = to_fn(|| set(&mut y)); | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:23:22 + --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | to_fn(|| z = 42); | ----- ^^^^^^ cannot assign @@ -32,10 +32,10 @@ LL | to_fn(|| z = 42); | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:30:32 + --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _f = to_fn(move || x = 42); | ----- ^^^^^^ cannot assign @@ -43,10 +43,10 @@ LL | let _f = to_fn(move || x = 42); | expects `Fn` instead of `FnMut` error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:33:36 + --> $DIR/borrow-immutable-upvar-mutation.rs:39:36 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... LL | let _g = to_fn(move || set(&mut y)); | ----- ^^^^^^ cannot borrow as mutable @@ -54,18 +54,18 @@ LL | let _g = to_fn(move || set(&mut y)); | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:36:65 + --> $DIR/borrow-immutable-upvar-mutation.rs:44:27 | -LL | fn to_fn>(f: F) -> F { f } - | - change this to accept `FnMut` instead of `Fn` +LL | fn to_fn>(f: F) -> F { + | - change this to accept `FnMut` instead of `Fn` ... -LL | let _h = to_fn_mut(move || { set(&mut z); to_fn(move || z = 42); }); - | ----- ^^^^^^ cannot assign - | | - | expects `Fn` instead of `FnMut` +LL | to_fn(move || z = 42); + | ----- ^^^^^^ cannot assign + | | + | expects `Fn` instead of `FnMut` error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:43:9 + --> $DIR/borrow-immutable-upvar-mutation.rs:53:9 | LL | fn foo() -> Box usize> { | --- ---------------------- change this to return `FnMut` instead of `Fn` @@ -78,20 +78,7 @@ LL | | x LL | | }) | |_____- in this closure -error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure - --> $DIR/borrow-immutable-upvar-mutation.rs:51:9 - | -LL | fn bar() -> impl Fn() -> usize { - | --- ------------------ change this to return `FnMut` instead of `Fn` -LL | let mut x = 0; -LL | / move || { -LL | | x += 1; - | | ^^^^^^ cannot assign -LL | | x -LL | | } - | |_____- in this closure - -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0594, E0596. For more information about an error, try `rustc --explain E0594`. From c423a8649c0bac16fd4d1b9cbea657e4245bb5ac Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 15 Feb 2020 11:56:23 +1300 Subject: [PATCH 0179/1250] Change const eval to return `ConstValue`, instead of `Const` as the type inside it shouldn't be used. --- src/librustc/mir/interpret/error.rs | 3 +- src/librustc/mir/interpret/value.rs | 33 ++++++++++++++++++++- src/librustc/ty/mod.rs | 6 ++-- src/librustc/ty/sty.rs | 4 ++- src/librustc_codegen_llvm/consts.rs | 8 ++--- src/librustc_codegen_llvm/intrinsic.rs | 3 +- src/librustc_codegen_ssa/mir/constant.rs | 8 ++++- src/librustc_codegen_ssa/mir/operand.rs | 2 +- src/librustc_mir/const_eval.rs | 6 ++-- src/librustc_mir/const_eval/eval_queries.rs | 18 +++++------ src/librustc_mir/interpret/eval_context.rs | 4 ++- src/librustc_mir/interpret/intrinsics.rs | 22 +++++--------- src/librustc_mir/interpret/operand.rs | 4 +-- src/librustc_mir/monomorphize/collector.rs | 32 ++++++++++++-------- src/librustc_mir_build/hair/cx/expr.rs | 12 +++++++- src/librustc_mir_build/hair/pattern/mod.rs | 9 ++++-- src/librustc_typeck/check/expr.rs | 9 ++++-- src/librustc_typeck/check/mod.rs | 17 +++++------ src/librustdoc/clean/mod.rs | 6 +++- src/librustdoc/clean/utils.rs | 19 +++++++----- 20 files changed, 145 insertions(+), 80 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index e747eee30f9..a23ff6bd66d 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -2,6 +2,7 @@ use super::{CheckInAllocMsg, Pointer, RawConst, ScalarMaybeUndef}; use crate::hir::map::definitions::DefPathData; use crate::mir; +use crate::mir::interpret::ConstValue; use crate::ty::layout::{Align, LayoutError, Size}; use crate::ty::query::TyCtxtAt; use crate::ty::{self, layout, Ty}; @@ -40,7 +41,7 @@ CloneTypeFoldableImpls! { } pub type ConstEvalRawResult<'tcx> = Result, ErrorHandled>; -pub type ConstEvalResult<'tcx> = Result<&'tcx ty::Const<'tcx>, ErrorHandled>; +pub type ConstEvalResult<'tcx> = Result, ErrorHandled>; #[derive(Debug)] pub struct ConstEvalErr<'tcx> { diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2be36ad418a..538d955762e 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -7,7 +7,7 @@ use std::fmt; use crate::ty::{ layout::{HasDataLayout, Size}, - Ty, + ParamEnv, Ty, TyCtxt, }; use super::{sign_extend, truncate, AllocId, Allocation, InterpResult, Pointer, PointerArithmetic}; @@ -66,6 +66,32 @@ impl<'tcx> ConstValue<'tcx> { ConstValue::Scalar(val) => Some(val), } } + + pub fn try_to_bits(&self, size: Size) -> Option { + self.try_to_scalar()?.to_bits(size).ok() + } + + pub fn try_to_bits_for_ty( + &self, + tcx: TyCtxt<'tcx>, + param_env: ParamEnv<'tcx>, + ty: Ty<'tcx>, + ) -> Option { + let size = tcx.layout_of(param_env.with_reveal_all().and(ty)).ok()?.size; + self.try_to_bits(size) + } + + pub fn from_bool(b: bool) -> Self { + ConstValue::Scalar(Scalar::from_bool(b)) + } + + pub fn from_u64(i: u64) -> Self { + ConstValue::Scalar(Scalar::from_u64(i)) + } + + pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self { + ConstValue::Scalar(Scalar::from_machine_usize(cx, i)) + } } /// A `Scalar` represents an immediate, primitive value existing outside of a @@ -287,6 +313,11 @@ impl<'tcx, Tag> Scalar { Scalar::Raw { data: i as u128, size: 8 } } + #[inline] + pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self { + Self::from_uint(i, cx.data_layout().pointer_size) + } + #[inline] pub fn try_from_int(i: impl Into, size: Size) -> Option { let i = i.into(); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ad51c60ab01..605baae6c24 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2380,10 +2380,10 @@ impl<'tcx> AdtDef { let repr_type = self.repr.discr_type(); match tcx.const_eval_poly(expr_did) { Ok(val) => { - // FIXME: Find the right type and use it instead of `val.ty` here - if let Some(b) = val.try_eval_bits(tcx, param_env, val.ty) { + let ty = repr_type.to_ty(tcx); + if let Some(b) = val.try_to_bits_for_ty(tcx, param_env, ty) { trace!("discriminants: {} ({:?})", b, repr_type); - Some(Discr { val: b, ty: val.ty }) + Some(Discr { val: b, ty }) } else { info!("invalid enum discriminant: {:#?}", val); crate::mir::interpret::struct_error( diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0718853b1df..57b55c0f897 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2471,7 +2471,9 @@ impl<'tcx> Const<'tcx> { // try to resolve e.g. associated constants to their definition on an impl, and then // evaluate the const. - tcx.const_eval_resolve(param_env, did, substs, promoted, None).ok() + tcx.const_eval_resolve(param_env, did, substs, promoted, None) + .ok() + .map(|val| tcx.mk_const(Const { val: ConstKind::Value(val), ty: self.ty })) }; match self.val { diff --git a/src/librustc_codegen_llvm/consts.rs b/src/librustc_codegen_llvm/consts.rs index 38090cb26bc..09a84aff168 100644 --- a/src/librustc_codegen_llvm/consts.rs +++ b/src/librustc_codegen_llvm/consts.rs @@ -78,11 +78,9 @@ pub fn codegen_static_initializer( cx: &CodegenCx<'ll, 'tcx>, def_id: DefId, ) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> { - let static_ = cx.tcx.const_eval_poly(def_id)?; - - let alloc = match static_.val { - ty::ConstKind::Value(ConstValue::ByRef { alloc, offset }) if offset.bytes() == 0 => alloc, - _ => bug!("static const eval returned {:#?}", static_), + let alloc = match cx.tcx.const_eval_poly(def_id)? { + ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc, + val => bug!("static const eval returned {:#?}", val), }; Ok((const_alloc_to_llvm(cx, alloc), alloc)) } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 031837c1efb..341a4a77c3c 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -193,7 +193,8 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { .tcx .const_eval_instance(ty::ParamEnv::reveal_all(), instance, None) .unwrap(); - OperandRef::from_const(self, ty_name).immediate_or_packed_pair(self) + let const_ = ty::Const { val: ty::ConstKind::Value(ty_name), ty: ret_ty }; + OperandRef::from_const(self, &const_).immediate_or_packed_pair(self) } "init" => { let ty = substs.type_at(0); diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 3ce916d7812..d7e87419c17 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { let val = self.eval_mir_constant(constant)?; - Ok(OperandRef::from_const(bx, val)) + Ok(OperandRef::from_const(bx, &val)) } } } @@ -45,6 +45,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.cx .tcx() .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None) + .map(|val| { + self.cx.tcx().mk_const(ty::Const { + val: ty::ConstKind::Value(val), + ty: constant.literal.ty, + }) + }) .map_err(|err| { if promoted.is_none() { self.cx diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index a33cd2ddad9..7745606b841 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -66,7 +66,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: &'tcx ty::Const<'tcx>, + val: &ty::Const<'tcx>, ) -> Self { let layout = bx.layout_of(val.ty); diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index aad0e162935..5e6db565a7d 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -40,7 +40,8 @@ pub(crate) fn const_field<'tcx>( let field = ecx.operand_field(down, field.index() as u64).unwrap(); // and finally move back to the const world, always normalizing because // this is not called for statics. - op_to_const(&ecx, field) + let val = op_to_const(&ecx, field); + tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty }) } pub(crate) fn const_caller_location<'tcx>( @@ -84,7 +85,8 @@ pub(crate) fn destructure_const<'tcx>( let down = ecx.operand_downcast(op, variant).unwrap(); let fields_iter = (0..field_count).map(|i| { let field_op = ecx.operand_field(down, i).unwrap(); - op_to_const(&ecx, field_op) + let val = op_to_const(&ecx, field_op); + tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: field_op.layout.ty }) }); let fields = tcx.arena.alloc_from_iter(fields_iter); diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 2e8e4dac237..6ac828521f3 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -97,7 +97,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( pub(super) fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>, op: OpTy<'tcx>, -) -> &'tcx ty::Const<'tcx> { +) -> ConstValue<'tcx> { // We do not have value optimizations for everything. // Only scalars and slices, since they are very common. // Note that further down we turn scalars of undefined bits back to `ByRef`. These can result @@ -144,7 +144,7 @@ pub(super) fn op_to_const<'tcx>( ConstValue::Scalar(Scalar::zst()) } }; - let val = match immediate { + match immediate { Ok(mplace) => to_const_value(mplace), // see comment on `let try_as_immediate` above Err(ImmTy { imm: Immediate::Scalar(x), .. }) => match x { @@ -166,8 +166,7 @@ pub(super) fn op_to_const<'tcx>( let len: usize = len.try_into().unwrap(); ConstValue::Slice { data, start, end: start + len } } - }; - ecx.tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty }) + } } fn validate_and_turn_into_const<'tcx>( @@ -195,13 +194,10 @@ fn validate_and_turn_into_const<'tcx>( // whether they become immediates. if is_static || cid.promoted.is_some() { let ptr = mplace.ptr.assert_ptr(); - Ok(tcx.mk_const(ty::Const { - val: ty::ConstKind::Value(ConstValue::ByRef { - alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), - offset: ptr.offset, - }), - ty: mplace.layout.ty, - })) + Ok(ConstValue::ByRef { + alloc: ecx.tcx.alloc_map.lock().unwrap_memory(ptr.alloc_id), + offset: ptr.offset, + }) } else { Ok(op_to_const(&ecx, mplace.into())) } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 206d3d15673..fc4ba4d6cd9 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -756,6 +756,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub(super) fn const_eval( &self, gid: GlobalId<'tcx>, + ty: Ty<'tcx>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { // For statics we pick `ParamEnv::reveal_all`, because statics don't have generics // and thus don't care about the parameter environment. While we could just use @@ -777,7 +778,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not // return `ConstValue::Unevaluated`, which is the only way that `eval_const_to_op` will call // `ecx.const_eval`. - self.eval_const_to_op(val, None) + let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; + self.eval_const_to_op(&const_, None) } pub fn const_eval_raw( diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 1085b85d7cd..1b1481580a9 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -48,22 +48,15 @@ crate fn eval_nullary_intrinsic<'tcx>( param_env: ty::ParamEnv<'tcx>, def_id: DefId, substs: SubstsRef<'tcx>, -) -> InterpResult<'tcx, &'tcx ty::Const<'tcx>> { +) -> InterpResult<'tcx, ConstValue<'tcx>> { let tp_ty = substs.type_at(0); let name = tcx.item_name(def_id); Ok(match name { sym::type_name => { let alloc = type_name::alloc_type_name(tcx, tp_ty); - tcx.mk_const(ty::Const { - val: ty::ConstKind::Value(ConstValue::Slice { - data: alloc, - start: 0, - end: alloc.len(), - }), - ty: tcx.mk_static_str(), - }) + ConstValue::Slice { data: alloc, start: 0, end: alloc.len() } } - sym::needs_drop => ty::Const::from_bool(tcx, tp_ty.needs_drop(tcx, param_env)), + sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)), sym::size_of | sym::min_align_of | sym::pref_align_of => { let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; let n = match name { @@ -72,11 +65,9 @@ crate fn eval_nullary_intrinsic<'tcx>( sym::size_of => layout.size.bytes(), _ => bug!(), }; - ty::Const::from_usize(tcx, n) - } - sym::type_id => { - ty::Const::from_bits(tcx, tcx.type_id_hash(tp_ty).into(), param_env.and(tcx.types.u64)) + ConstValue::from_machine_usize(&tcx, n) } + sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()), other => bug!("`{}` is not a zero arg intrinsic", other), }) } @@ -119,7 +110,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::type_id | sym::type_name => { let gid = GlobalId { instance, promoted: None }; - let val = self.const_eval(gid)?; + let ty = instance.ty_env(*self.tcx, self.param_env); + let val = self.const_eval(gid, ty)?; self.copy_op(val, dest)?; } diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index d1c08da6cbe..14b8a341e26 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -518,7 +518,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { /// "universe" (param_env). crate fn eval_const_to_op( &self, - val: &'tcx ty::Const<'tcx>, + val: &ty::Const<'tcx>, layout: Option>, ) -> InterpResult<'tcx, OpTy<'tcx, M::PointerTag>> { let tag_scalar = |scalar| match scalar { @@ -536,7 +536,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // potentially requiring the current static to be evaluated again. This is not a // problem here, because we are building an operand which means an actual read is // happening. - return Ok(OpTy::from(self.const_eval(GlobalId { instance, promoted })?)); + return Ok(self.const_eval(GlobalId { instance, promoted }, val.ty)?); } ty::ConstKind::Infer(..) | ty::ConstKind::Bound(..) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index dd2071a6c59..0fa7d6a9b72 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -357,7 +357,7 @@ fn collect_items_rec<'tcx>( recursion_depth_reset = None; if let Ok(val) = tcx.const_eval_poly(def_id) { - collect_const(tcx, val, InternalSubsts::empty(), &mut neighbors); + collect_const_value(tcx, val, &mut neighbors); } } MonoItem::Fn(instance) => { @@ -971,7 +971,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { let def_id = self.tcx.hir().local_def_id(item.hir_id); if let Ok(val) = self.tcx.const_eval_poly(def_id) { - collect_const(self.tcx, val, InternalSubsts::empty(), &mut self.output); + collect_const_value(self.tcx, val, &mut self.output); } } hir::ItemKind::Fn(..) => { @@ -1185,18 +1185,10 @@ fn collect_const<'tcx>( tcx.subst_and_normalize_erasing_regions(param_substs, param_env, &constant); match substituted_constant.val { - ty::ConstKind::Value(ConstValue::Scalar(Scalar::Ptr(ptr))) => { - collect_miri(tcx, ptr.alloc_id, output) - } - ty::ConstKind::Value(ConstValue::Slice { data: alloc, start: _, end: _ }) - | ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) => { - for &((), id) in alloc.relocations().values() { - collect_miri(tcx, id, output); - } - } + ty::ConstKind::Value(val) => collect_const_value(tcx, val, output), ty::ConstKind::Unevaluated(def_id, substs, promoted) => { match tcx.const_eval_resolve(param_env, def_id, substs, promoted, None) { - Ok(val) => collect_const(tcx, val, param_substs, output), + Ok(val) => collect_const_value(tcx, val, output), Err(ErrorHandled::Reported) => {} Err(ErrorHandled::TooGeneric) => { span_bug!(tcx.def_span(def_id), "collection encountered polymorphic constant",) @@ -1206,3 +1198,19 @@ fn collect_const<'tcx>( _ => {} } } + +fn collect_const_value<'tcx>( + tcx: TyCtxt<'tcx>, + value: ConstValue<'tcx>, + output: &mut Vec>, +) { + match value { + ConstValue::Scalar(Scalar::Ptr(ptr)) => collect_miri(tcx, ptr.alloc_id, output), + ConstValue::Slice { data: alloc, start: _, end: _ } | ConstValue::ByRef { alloc, .. } => { + for &((), id) in alloc.relocations().values() { + collect_miri(tcx, id, output); + } + } + _ => {} + } +} diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index d6786ea2479..74006c88371 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -418,7 +418,17 @@ fn make_mirror_unadjusted<'a, 'tcx>( None, Some(span), ) { - Ok(cv) => cv.eval_usize(cx.tcx, ty::ParamEnv::reveal_all()), + Ok(cv) => { + if let Some(count) = cv.try_to_bits_for_ty( + cx.tcx, + ty::ParamEnv::reveal_all(), + cx.tcx.types.usize, + ) { + count as u64 + } else { + bug!("repeat count constant value can't be converted to usize"); + } + } Err(ErrorHandled::Reported) => 0, Err(ErrorHandled::TooGeneric) => { let span = cx.tcx.def_span(def_id); diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index bd8a9877719..f403b1432c4 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -769,7 +769,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Some(span), ) { Ok(value) => { - let pattern = self.const_to_pat(value, id, span); + let const_ = self.tcx.mk_const(ty::Const { + val: ty::ConstKind::Value(value), + ty: self.tables.node_type(id), + }); + + let pattern = self.const_to_pat(&const_, id, span); if !is_associated_const { return pattern; } @@ -789,7 +794,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { user_ty_span: span, }, }), - ty: value.ty, + ty: const_.ty, } } else { pattern diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 90b7b300da9..dc9d5003a41 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -25,7 +25,7 @@ use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; use rustc::ty::TypeFoldable; -use rustc::ty::{AdtKind, Visibility}; +use rustc::ty::{AdtKind, ConstKind, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; @@ -1011,7 +1011,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count = if self.const_param_def_id(count).is_some() { Ok(self.to_const(count, tcx.type_of(count_def_id))) } else { - tcx.const_eval_poly(count_def_id) + tcx.const_eval_poly(count_def_id).map(|val| { + tcx.mk_const(ty::Const { + val: ConstKind::Value(val), + ty: tcx.type_of(count_def_id), + }) + }) }; let uty = match expected { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a825856e38a..7862154a0be 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1832,18 +1832,17 @@ fn maybe_check_static_with_link_section(tcx: TyCtxt<'_>, id: DefId, span: Span) // `#[link_section]` may contain arbitrary, or even undefined bytes, but it is // the consumer's responsibility to ensure all bytes that have been read // have defined values. - if let Ok(static_) = tcx.const_eval_poly(id) { - let alloc = if let ty::ConstKind::Value(ConstValue::ByRef { alloc, .. }) = static_.val { - alloc - } else { - bug!("Matching on non-ByRef static") - }; - if alloc.relocations().len() != 0 { - let msg = "statics with a custom `#[link_section]` must be a \ + match tcx.const_eval_poly(id) { + Ok(ConstValue::ByRef { alloc, .. }) => { + if alloc.relocations().len() != 0 { + let msg = "statics with a custom `#[link_section]` must be a \ simple list of bytes on the wasm target with no \ extra levels of indirection such as references"; - tcx.sess.span_err(span, msg); + tcx.sess.span_err(span, msg); + } } + Ok(_) => bug!("Matching on non-ByRef static"), + Err(_) => {} } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 87edc88611f..79019d0b950 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1332,7 +1332,11 @@ impl Clean for hir::Ty<'_> { TyKind::Array(ref ty, ref length) => { let def_id = cx.tcx.hir().local_def_id(length.hir_id); let length = match cx.tcx.const_eval_poly(def_id) { - Ok(length) => print_const(cx, length), + Ok(length) => { + let const_ = + ty::Const { val: ty::ConstKind::Value(length), ty: cx.tcx.types.usize }; + print_const(cx, &const_) + } Err(_) => cx .sess() .source_map() diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index ef357056504..f8c657477f7 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -487,15 +487,18 @@ pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { } pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option { - let value = - cx.tcx.const_eval_poly(def_id).ok().and_then(|value| match (value.val, &value.ty.kind) { - (_, ty::Ref(..)) => None, - (ty::ConstKind::Value(ConstValue::Scalar(_)), ty::Adt(_, _)) => None, - (ty::ConstKind::Value(ConstValue::Scalar(_)), _) => { - Some(print_const_with_custom_print_scalar(cx, value)) + let value = cx.tcx.const_eval_poly(def_id).ok().and_then(|val| { + let ty = cx.tcx.type_of(def_id); + match (val, &ty.kind) { + (_, &ty::Ref(..)) => None, + (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, + (ConstValue::Scalar(_), _) => { + let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; + Some(print_const_with_custom_print_scalar(cx, &const_)) } _ => None, - }); + } + }); value } @@ -510,7 +513,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String { .collect() } -fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String { +fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &ty::Const<'tcx>) -> String { // Use a slightly different format for integer types which always shows the actual value. // For all other types, fallback to the original `pretty_print_const`. match (ct.val, &ct.ty.kind) { From c7aadcfa567f363e302ac797a4805668eb7bc77c Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 15 Feb 2020 12:57:46 +1300 Subject: [PATCH 0180/1250] Change `const_field` and `const_caller_location` to return `ConstValue` instead of `Const` as the type in the returned const isn't needed. --- src/librustc/query/mod.rs | 4 +-- src/librustc/ty/query/mod.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 3 +- src/librustc_codegen_ssa/mir/block.rs | 2 +- src/librustc_codegen_ssa/mir/constant.rs | 35 +++++++++++++----------- src/librustc_codegen_ssa/mir/operand.rs | 14 ++++------ src/librustc_mir/const_eval.rs | 15 +++------- 7 files changed, 33 insertions(+), 42 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11b079806af..d9bf93dd679 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -517,7 +517,7 @@ rustc_queries! { /// Extracts a field of a (variant of a) const. query const_field( key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)> - ) -> &'tcx ty::Const<'tcx> { + ) -> ConstValue<'tcx> { no_force desc { "extract field of const" } } @@ -531,7 +531,7 @@ rustc_queries! { desc { "destructure constant" } } - query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> &'tcx ty::Const<'tcx> { + query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { no_force desc { "get a &core::panic::Location referring to a span" } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index ddaaab412a4..33312e730f2 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -14,7 +14,7 @@ use crate::middle::resolve_lifetime::{ObjectLifetimeDefault, Region, ResolveLife use crate::middle::stability::{self, DeprecationEntry}; use crate::mir; use crate::mir::interpret::GlobalId; -use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult}; +use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue}; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 341a4a77c3c..3d1e72e1c73 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -193,8 +193,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> { .tcx .const_eval_instance(ty::ParamEnv::reveal_all(), instance, None) .unwrap(); - let const_ = ty::Const { val: ty::ConstKind::Value(ty_name), ty: ret_ty }; - OperandRef::from_const(self, &const_).immediate_or_packed_pair(self) + OperandRef::from_const(self, ty_name, ret_ty).immediate_or_packed_pair(self) } "init" => { let ty = substs.type_at(0); diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 916c15eb1b6..d684f842ddc 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -991,7 +991,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { caller.line as u32, caller.col_display as u32 + 1, )); - OperandRef::from_const(bx, const_loc) + OperandRef::from_const(bx, const_loc, bx.tcx().caller_location_ty()) }) } diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index d7e87419c17..8722aacca72 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -1,7 +1,7 @@ use crate::mir::operand::OperandRef; use crate::traits::*; use rustc::mir; -use rustc::mir::interpret::ErrorHandled; +use rustc::mir::interpret::{ConstValue, ErrorHandled}; use rustc::ty::layout::{self, HasTyCtxt}; use rustc::ty::{self, Ty}; use rustc_index::vec::Idx; @@ -30,7 +30,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { let val = self.eval_mir_constant(constant)?; - Ok(OperandRef::from_const(bx, &val)) + Ok(OperandRef::from_const(bx, val.clone(), constant.literal.ty)) } } } @@ -38,19 +38,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn eval_mir_constant( &mut self, constant: &mir::Constant<'tcx>, - ) -> Result<&'tcx ty::Const<'tcx>, ErrorHandled> { + ) -> Result, ErrorHandled> { match constant.literal.val { ty::ConstKind::Unevaluated(def_id, substs, promoted) => { let substs = self.monomorphize(&substs); self.cx .tcx() .const_eval_resolve(ty::ParamEnv::reveal_all(), def_id, substs, promoted, None) - .map(|val| { - self.cx.tcx().mk_const(ty::Const { - val: ty::ConstKind::Value(val), - ty: constant.literal.ty, - }) - }) .map_err(|err| { if promoted.is_none() { self.cx @@ -61,7 +55,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { err }) } - _ => Ok(self.monomorphize(&constant.literal)), + ty::ConstKind::Value(value) => Ok(value), + _ => { + let const_ = self.monomorphize(&constant.literal); + if let ty::ConstKind::Value(value) = const_.val { + Ok(value) + } else { + bug!("encountered bad ConstKind in codegen"); + } + } } } @@ -71,21 +73,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx: &Bx, span: Span, ty: Ty<'tcx>, - constant: Result<&'tcx ty::Const<'tcx>, ErrorHandled>, + constant: Result, ErrorHandled>, ) -> (Bx::Value, Ty<'tcx>) { constant - .map(|c| { - let field_ty = c.ty.builtin_index().unwrap(); - let fields = match c.ty.kind { + .map(|val| { + let field_ty = ty.builtin_index().unwrap(); + let fields = match ty.kind { ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()), - _ => bug!("invalid simd shuffle type: {}", c.ty), + _ => bug!("invalid simd shuffle type: {}", ty), }; + let c = bx.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(val), ty }); let values: Vec<_> = (0..fields) .map(|field| { let field = bx.tcx().const_field( ty::ParamEnv::reveal_all().and((&c, mir::Field::new(field as usize))), ); - if let Some(prim) = field.val.try_to_scalar() { + if let Some(prim) = field.try_to_scalar() { let layout = bx.layout_of(field_ty); let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 7745606b841..07c8829e7d8 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -8,8 +8,8 @@ use crate::MemFlags; use rustc::mir; use rustc::mir::interpret::{ConstValue, ErrorHandled, Pointer, Scalar}; -use rustc::ty; use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout}; +use rustc::ty::Ty; use std::fmt; @@ -66,20 +66,16 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn from_const>( bx: &mut Bx, - val: &ty::Const<'tcx>, + val: ConstValue<'tcx>, + ty: Ty<'tcx>, ) -> Self { - let layout = bx.layout_of(val.ty); + let layout = bx.layout_of(ty); if layout.is_zst() { return OperandRef::new_zst(bx, layout); } - let val_val = match val.val { - ty::ConstKind::Value(val_val) => val_val, - _ => bug!("encountered bad ConstKind in codegen"), - }; - - let val = match val_val { + let val = match val { ConstValue::Scalar(x) => { let scalar = match layout.abi { layout::Abi::Scalar(ref x) => x, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 5e6db565a7d..5915520535d 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -26,7 +26,7 @@ pub(crate) fn const_field<'tcx>( variant: Option, field: mir::Field, value: &'tcx ty::Const<'tcx>, -) -> &'tcx ty::Const<'tcx> { +) -> ConstValue<'tcx> { trace!("const_field: {:?}, {:?}", field, value); let ecx = mk_eval_cx(tcx, DUMMY_SP, param_env, false); // get the operand again @@ -40,26 +40,19 @@ pub(crate) fn const_field<'tcx>( let field = ecx.operand_field(down, field.index() as u64).unwrap(); // and finally move back to the const world, always normalizing because // this is not called for statics. - let val = op_to_const(&ecx, field); - tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: op.layout.ty }) + op_to_const(&ecx, field) } pub(crate) fn const_caller_location<'tcx>( tcx: TyCtxt<'tcx>, (file, line, col): (Symbol, u32, u32), -) -> &'tcx ty::Const<'tcx> { +) -> ConstValue<'tcx> { trace!("const_caller_location: {}:{}:{}", file, line, col); let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); - let loc_ty = tcx.caller_location_ty(); let loc_place = ecx.alloc_caller_location(file, line, col); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap(); - let loc_const = ty::Const { - ty: loc_ty, - val: ty::ConstKind::Value(ConstValue::Scalar(loc_place.ptr.into())), - }; - - tcx.mk_const(loc_const) + ConstValue::Scalar(loc_place.ptr.into()) } // this function uses `unwrap` copiously, because an already validated constant From 6b17330ef4f9a97bd539b55edb4e7ccdb6c00133 Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Fri, 14 Feb 2020 16:05:45 -0800 Subject: [PATCH 0181/1250] Merged apple_tvos_base and apple_ios_base into apple_sdk_base. --- src/librustc_target/spec/aarch64_apple_ios.rs | 4 +- .../spec/aarch64_apple_tvos.rs | 4 +- .../{apple_ios_base.rs => apple_sdk_base.rs} | 43 ++++-- src/librustc_target/spec/apple_tvos_base.rs | 123 ------------------ src/librustc_target/spec/armv7_apple_ios.rs | 4 +- src/librustc_target/spec/armv7s_apple_ios.rs | 4 +- src/librustc_target/spec/i386_apple_ios.rs | 4 +- src/librustc_target/spec/mod.rs | 3 +- src/librustc_target/spec/x86_64_apple_ios.rs | 4 +- .../spec/x86_64_apple_ios_macabi.rs | 4 +- src/librustc_target/spec/x86_64_apple_tvos.rs | 4 +- 11 files changed, 51 insertions(+), 150 deletions(-) rename src/librustc_target/spec/{apple_ios_base.rs => apple_sdk_base.rs} (74%) delete mode 100644 src/librustc_target/spec/apple_tvos_base.rs diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index 6549be41ea9..2216af428fa 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Arm64)?; + let base = opts(Arch::Arm64, AppleOS::iOS)?; Ok(Target { llvm_target: "arm64-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index 420e0d1c64c..a87d5965c3d 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -1,8 +1,8 @@ -use super::apple_tvos_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Arm64)?; + let base = opts(Arch::Arm64, AppleOS::tvOS)?; Ok(Target { llvm_target: "arm64-apple-tvos".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/apple_ios_base.rs b/src/librustc_target/spec/apple_sdk_base.rs similarity index 74% rename from src/librustc_target/spec/apple_ios_base.rs rename to src/librustc_target/spec/apple_sdk_base.rs index 2673748321d..2c93cbc4d85 100644 --- a/src/librustc_target/spec/apple_ios_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -1,3 +1,4 @@ + use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; use std::env; use std::io; @@ -5,7 +6,6 @@ use std::path::Path; use std::process::Command; use Arch::*; - #[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub enum Arch { @@ -17,6 +17,13 @@ pub enum Arch { X86_64_macabi, } +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub enum AppleOS { + tvOS, + iOS, +} + impl Arch { pub fn to_string(self) -> &'static str { match self { @@ -41,6 +48,17 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { let p = Path::new(&sdkroot); match sdk_name { // Ignore `SDKROOT` if it's clearly set for the wrong platform. + "appletvos" + if sdkroot.contains("TVSimulator.platform") + || sdkroot.contains("MacOSX.platform") => + { + () + } + "appletvsimulator" + if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => + { + () + } "iphoneos" if sdkroot.contains("iPhoneSimulator.platform") || sdkroot.contains("MacOSX.platform") => @@ -82,11 +100,17 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { } } -fn build_pre_link_args(arch: Arch) -> Result { - let sdk_name = match arch { - Armv7 | Armv7s | Arm64 => "iphoneos", - I386 | X86_64 => "iphonesimulator", - X86_64_macabi => "macosx10.15", +fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result { + let sdk_name = match (arch, os) { + (Arm64, AppleOS::tvOS) => "appletvos", + (X86_64, AppleOS::tvOS) => "appletvsimulator", + (Armv7, AppleOS::iOS) => "iphoneos", + (Armv7s, AppleOS::iOS) => "iphoneos", + (Arm64, AppleOS::iOS) => "iphoneos", + (I386, AppleOS::iOS) => "iphonesimulator", + (X86_64, AppleOS::iOS) => "iphonesimulator", + (X86_64_macabi, AppleOS::iOS) => "macosx10.15", + _ => unreachable!(), }; let arch_name = arch.to_string(); @@ -121,15 +145,16 @@ fn target_cpu(arch: Arch) -> String { .to_string() } + fn link_env_remove(arch: Arch) -> Vec { match arch { Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], - X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()], + X86_64_macabi => vec![ "IPHONEOS_DEPLOYMENT_TARGET".to_string() ,], } } -pub fn opts(arch: Arch) -> Result { - let pre_link_args = build_pre_link_args(arch)?; +pub fn opts(arch: Arch, os: AppleOS) -> Result { + let pre_link_args = build_pre_link_args(arch, os)?; Ok(TargetOptions { cpu: target_cpu(arch), dynamic_linking: false, diff --git a/src/librustc_target/spec/apple_tvos_base.rs b/src/librustc_target/spec/apple_tvos_base.rs deleted file mode 100644 index 70dc8093f88..00000000000 --- a/src/librustc_target/spec/apple_tvos_base.rs +++ /dev/null @@ -1,123 +0,0 @@ -use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; -use std::env; -use std::io; -use std::path::Path; -use std::process::Command; - -use Arch::*; - -#[allow(non_camel_case_types)] -#[derive(Copy, Clone)] -pub enum Arch { - Arm64, - X86_64, -} - -impl Arch { - pub fn to_string(self) -> &'static str { - match self { - Arm64 => "arm64", - X86_64 => "x86_64", - } - } -} - -pub fn get_sdk_root(sdk_name: &str) -> Result { - // Following what clang does - // (https://github.com/llvm/llvm-project/blob/ - // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678) - // to allow the SDK path to be set. (For clang, xcrun sets - // SDKROOT; for rustc, the user or build system can set it, or we - // can fall back to checking for xcrun on PATH.) - if let Some(sdkroot) = env::var("SDKROOT").ok() { - let p = Path::new(&sdkroot); - match sdk_name { - // Ignore `SDKROOT` if it's clearly set for the wrong platform. - "appletvos" - if sdkroot.contains("TVSimulator.platform") - || sdkroot.contains("MacOSX.platform") => - { - () - } - "appletvsimulator" - if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => - { - () - } - // Ignore `SDKROOT` if it's not a valid path. - _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => (), - _ => return Ok(sdkroot), - } - } - let res = - Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then( - |output| { - if output.status.success() { - Ok(String::from_utf8(output.stdout).unwrap()) - } else { - let error = String::from_utf8(output.stderr); - let error = format!("process exit with error: {}", error.unwrap()); - Err(io::Error::new(io::ErrorKind::Other, &error[..])) - } - }, - ); - - match res { - Ok(output) => Ok(output.trim().to_string()), - Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)), - } -} - -fn build_pre_link_args(arch: Arch) -> Result { - let sdk_name = match arch { - Arm64 => "appletvos", - X86_64 => "appletvsimulator", - }; - - let arch_name = arch.to_string(); - - let sdk_root = get_sdk_root(sdk_name)?; - - let mut args = LinkArgs::new(); - args.insert( - LinkerFlavor::Gcc, - vec![ - "-arch".to_string(), - arch_name.to_string(), - "-isysroot".to_string(), - sdk_root.clone(), - "-Wl,-syslibroot".to_string(), - sdk_root, - ], - ); - - Ok(args) -} - -fn target_cpu(arch: Arch) -> String { - match arch { - Arm64 => "cyclone", - X86_64 => "core2", - } - .to_string() -} - -fn link_env_remove(arch: Arch) -> Vec { - match arch { - Arm64 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], - } -} - -pub fn opts(arch: Arch) -> Result { - let pre_link_args = build_pre_link_args(arch)?; - Ok(TargetOptions { - cpu: target_cpu(arch), - dynamic_linking: false, - executables: true, - pre_link_args, - link_env_remove: link_env_remove(arch), - has_elf_tls: false, - eliminate_frame_pointer: false, - ..super::apple_base::opts() - }) -} diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs index aa2d32e2d79..19d189e2543 100644 --- a/src/librustc_target/spec/armv7_apple_ios.rs +++ b/src/librustc_target/spec/armv7_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Armv7)?; + let base = opts(Arch::Armv7, AppleOS::iOS)?; Ok(Target { llvm_target: "armv7-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs index 6514643a64d..53fb8a9ff9f 100644 --- a/src/librustc_target/spec/armv7s_apple_ios.rs +++ b/src/librustc_target/spec/armv7s_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::Armv7s)?; + let base = opts(Arch::Armv7s, AppleOS::iOS)?; Ok(Target { llvm_target: "armv7s-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs index a6c1d24fa62..eb0c68bc7b8 100644 --- a/src/librustc_target/spec/i386_apple_ios.rs +++ b/src/librustc_target/spec/i386_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::I386)?; + let base = opts(Arch::I386, AppleOS::iOS)?; Ok(Target { llvm_target: "i386-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index a110fd03673..37eabb4f26d 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -47,8 +47,7 @@ use rustc_macros::HashStable_Generic; pub mod abi; mod android_base; mod apple_base; -mod apple_ios_base; -mod apple_tvos_base; +mod apple_sdk_base; mod arm_base; mod cloudabi_base; mod dragonfly_base; diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs index ca02e2deabc..db5361f1d81 100644 --- a/src/librustc_target/spec/x86_64_apple_ios.rs +++ b/src/librustc_target/spec/x86_64_apple_ios.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::X86_64)?; + let base = opts(Arch::X86_64, AppleOS::iOS)?; Ok(Target { llvm_target: "x86_64-apple-ios".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs index 5f4f6ade682..cce6221134d 100644 --- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs +++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs @@ -1,8 +1,8 @@ -use super::apple_ios_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::X86_64_macabi)?; + let base = opts(Arch::X86_64_macabi, AppleOS::iOS)?; Ok(Target { llvm_target: "x86_64-apple-ios13.0-macabi".to_string(), target_endian: "little".to_string(), diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs index e40d978e750..794df42f43e 100644 --- a/src/librustc_target/spec/x86_64_apple_tvos.rs +++ b/src/librustc_target/spec/x86_64_apple_tvos.rs @@ -1,8 +1,8 @@ -use super::apple_tvos_base::{opts, Arch}; +use super::apple_sdk_base::{opts, Arch, AppleOS}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { - let base = opts(Arch::X86_64)?; + let base = opts(Arch::X86_64, AppleOS::iOS)?; Ok(Target { llvm_target: "x86_64-apple-tvos".to_string(), target_endian: "little".to_string(), From 99a864be39d551362bc29bb76ac06d639afedb42 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 15 Feb 2020 14:45:36 +1300 Subject: [PATCH 0182/1250] Fix emulate intrinsics return type. --- src/librustc_mir/interpret/intrinsics.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 1b1481580a9..b7333ac3aae 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -110,8 +110,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::type_id | sym::type_name => { let gid = GlobalId { instance, promoted: None }; - let ty = instance.ty_env(*self.tcx, self.param_env); - let val = self.const_eval(gid, ty)?; + let val = self.const_eval(gid, dest.layout.ty)?; self.copy_op(val, dest)?; } From a8fe47d1756df0fb68f6ed2edd2cedfb3cc66d7c Mon Sep 17 00:00:00 2001 From: Max Blachman Date: Sun, 24 Nov 2019 14:30:56 -0800 Subject: [PATCH 0183/1250] implement LowerExp and UpperExp for integers --- src/libcore/fmt/num.rs | 163 +++++++++++++++++++++++++++++++++++ src/libcore/tests/fmt/num.rs | 80 +++++++++++++++++ 2 files changed, 243 insertions(+) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index d562639a658..c187471fb5f 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -4,6 +4,7 @@ use crate::fmt; use crate::mem::MaybeUninit; +use crate::num::flt2dec; use crate::ops::{Div, Rem, Sub}; use crate::ptr; use crate::slice; @@ -256,6 +257,161 @@ macro_rules! impl_Display { }; } +macro_rules! impl_Exp { + ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { + fn $name( + mut n: $u, + is_nonnegative: bool, + upper: bool, + f: &mut fmt::Formatter<'_> + ) -> fmt::Result { + let (mut n, mut exponent, trailing_zeros, added_precision) = { + let mut exponent = 0; + // count and remove trailing decimal zeroes + while n % 10 == 0 && n >= 10 { + n /= 10; + exponent += 1; + } + let trailing_zeros = exponent; + + let (added_precision, subtracted_precision) = match f.precision() { + Some(fmt_prec) => { + // number of decimal digits minus 1 + let mut tmp = n; + let mut prec = 0; + while tmp >= 10 { + tmp /= 10; + prec += 1; + } + (fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec)) + } + None => (0,0) + }; + for _ in 1..subtracted_precision { + n/=10; + exponent += 1; + } + if subtracted_precision != 0 { + let rem = n % 10; + n /= 10; + exponent += 1; + // round up last digit + if rem >= 5 { + n += 1; + } + } + (n, exponent, trailing_zeros, added_precision) + }; + + // 39 digits (worst case u128) + . = 40 + let mut buf = [MaybeUninit::::uninit(); 40]; + let mut curr = buf.len() as isize; //index for buf + let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); + let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + + // decode 2 chars at a time + while n >= 100 { + let d1 = ((n % 100) as isize) << 1; + curr -= 2; + unsafe { + ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); + } + n /= 100; + exponent += 2; + } + // n is <= 99, so at most 2 chars long + let mut n = n as isize; // possibly reduce 64bit math + // decode second-to-last character + if n >= 10 { + curr -= 1; + unsafe { + *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0'; + } + n /= 10; + exponent += 1; + } + // add decimal point iff >1 mantissa digit will be printed + if exponent != trailing_zeros || added_precision != 0 { + curr -= 1; + unsafe { + *buf_ptr.offset(curr) = b'.'; + } + } + + let buf_slice = unsafe { + // decode last character + curr -= 1; + *buf_ptr.offset(curr) = (n as u8) + b'0'; + + let len = buf.len() - curr as usize; + slice::from_raw_parts(buf_ptr.offset(curr), len) + }; + + // stores 'e' (or 'E') and the up to 2-digit exponent + let mut exp_buf = [MaybeUninit::::uninit(); 3]; + let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf); + let exp_slice = unsafe { + *exp_ptr.offset(0) = if upper {b'E'} else {b'e'}; + let len = if exponent < 10 { + *exp_ptr.offset(1) = (exponent as u8) + b'0'; + 2 + } else { + let off = exponent << 1; + ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2); + 3 + }; + slice::from_raw_parts(exp_ptr, len) + }; + + let parts = &[ + flt2dec::Part::Copy(buf_slice), + flt2dec::Part::Zero(added_precision), + flt2dec::Part::Copy(exp_slice) + ]; + let sign = if !is_nonnegative { + &b"-"[..] + } else if f.sign_plus() { + &b"+"[..] + } else { + &b""[..] + }; + let formatted = flt2dec::Formatted{sign, parts}; + f.pad_formatted_parts(&formatted) + } + + $( + #[stable(feature = "integer_exp_format", since = "1.42.0")] + impl fmt::LowerExp for $t { + #[allow(unused_comparisons)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.$conv_fn() + } else { + // convert the negative num to positive by summing 1 to it's 2 complement + (!self.$conv_fn()).wrapping_add(1) + }; + $name(n, is_nonnegative, false, f) + } + })* + $( + #[stable(feature = "integer_exp_format", since = "1.42.0")] + impl fmt::UpperExp for $t { + #[allow(unused_comparisons)] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let is_nonnegative = *self >= 0; + let n = if is_nonnegative { + self.$conv_fn() + } else { + // convert the negative num to positive by summing 1 to it's 2 complement + (!self.$conv_fn()).wrapping_add(1) + }; + $name(n, is_nonnegative, true, f) + } + })* + }; +} + // Include wasm32 in here since it doesn't reflect the native pointer size, and // often cares strongly about getting a smaller code size. #[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))] @@ -265,6 +421,10 @@ mod imp { i8, u8, i16, u16, i32, u32, i64, u64, usize, isize as u64 via to_u64 named fmt_u64 ); + impl_Exp!( + i8, u8, i16, u16, i32, u32, i64, u64, usize, isize + as u64 via to_u64 named exp_u64 + ); } #[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))] @@ -272,6 +432,9 @@ mod imp { use super::*; impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32); impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64); + impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32); + impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64); } impl_Display!(i128, u128 as u128 via to_u128 named fmt_u128); +impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128); diff --git a/src/libcore/tests/fmt/num.rs b/src/libcore/tests/fmt/num.rs index 10fcf8b76cc..a50c2b46a91 100644 --- a/src/libcore/tests/fmt/num.rs +++ b/src/libcore/tests/fmt/num.rs @@ -38,6 +38,16 @@ fn test_format_int() { assert_eq!(format!("{:o}", 1i16), "1"); assert_eq!(format!("{:o}", 1i32), "1"); assert_eq!(format!("{:o}", 1i64), "1"); + assert_eq!(format!("{:e}", 1isize), "1e0"); + assert_eq!(format!("{:e}", 1i8), "1e0"); + assert_eq!(format!("{:e}", 1i16), "1e0"); + assert_eq!(format!("{:e}", 1i32), "1e0"); + assert_eq!(format!("{:e}", 1i64), "1e0"); + assert_eq!(format!("{:E}", 1isize), "1E0"); + assert_eq!(format!("{:E}", 1i8), "1E0"); + assert_eq!(format!("{:E}", 1i16), "1E0"); + assert_eq!(format!("{:E}", 1i32), "1E0"); + assert_eq!(format!("{:E}", 1i64), "1E0"); assert_eq!(format!("{}", 1usize), "1"); assert_eq!(format!("{}", 1u8), "1"); @@ -69,6 +79,14 @@ fn test_format_int() { assert_eq!(format!("{:o}", 1u16), "1"); assert_eq!(format!("{:o}", 1u32), "1"); assert_eq!(format!("{:o}", 1u64), "1"); + assert_eq!(format!("{:e}", 1u8), "1e0"); + assert_eq!(format!("{:e}", 1u16), "1e0"); + assert_eq!(format!("{:e}", 1u32), "1e0"); + assert_eq!(format!("{:e}", 1u64), "1e0"); + assert_eq!(format!("{:E}", 1u8), "1E0"); + assert_eq!(format!("{:E}", 1u16), "1E0"); + assert_eq!(format!("{:E}", 1u32), "1E0"); + assert_eq!(format!("{:E}", 1u64), "1E0"); // Test a larger number assert_eq!(format!("{:b}", 55), "110111"); @@ -76,6 +94,64 @@ fn test_format_int() { assert_eq!(format!("{}", 55), "55"); assert_eq!(format!("{:x}", 55), "37"); assert_eq!(format!("{:X}", 55), "37"); + assert_eq!(format!("{:e}", 55), "5.5e1"); + assert_eq!(format!("{:E}", 55), "5.5E1"); + assert_eq!(format!("{:e}", 10000000000u64), "1e10"); + assert_eq!(format!("{:E}", 10000000000u64), "1E10"); + assert_eq!(format!("{:e}", 10000000001u64), "1.0000000001e10"); + assert_eq!(format!("{:E}", 10000000001u64), "1.0000000001E10"); +} + +#[test] +fn test_format_int_exp_limits() { + use core::{i128, i16, i32, i64, i8, u128, u16, u32, u64, u8}; + assert_eq!(format!("{:e}", i8::MIN), "-1.28e2"); + assert_eq!(format!("{:e}", i8::MAX), "1.27e2"); + assert_eq!(format!("{:e}", i16::MIN), "-3.2768e4"); + assert_eq!(format!("{:e}", i16::MAX), "3.2767e4"); + assert_eq!(format!("{:e}", i32::MIN), "-2.147483648e9"); + assert_eq!(format!("{:e}", i32::MAX), "2.147483647e9"); + assert_eq!(format!("{:e}", i64::MIN), "-9.223372036854775808e18"); + assert_eq!(format!("{:e}", i64::MAX), "9.223372036854775807e18"); + assert_eq!(format!("{:e}", i128::MIN), "-1.70141183460469231731687303715884105728e38"); + assert_eq!(format!("{:e}", i128::MAX), "1.70141183460469231731687303715884105727e38"); + + assert_eq!(format!("{:e}", u8::MAX), "2.55e2"); + assert_eq!(format!("{:e}", u16::MAX), "6.5535e4"); + assert_eq!(format!("{:e}", u32::MAX), "4.294967295e9"); + assert_eq!(format!("{:e}", u64::MAX), "1.8446744073709551615e19"); + assert_eq!(format!("{:e}", u128::MAX), "3.40282366920938463463374607431768211455e38"); +} + +#[test] +fn test_format_int_exp_precision() { + use core::{i128, i16, i32, i64, i8}; + + //test that float and integer match + let big_int: u32 = 314_159_265; + assert_eq!(format!("{:.1e}", big_int), format!("{:.1e}", f64::from(big_int))); + + //test adding precision + assert_eq!(format!("{:.10e}", i8::MIN), "-1.2800000000e2"); + assert_eq!(format!("{:.10e}", i16::MIN), "-3.2768000000e4"); + assert_eq!(format!("{:.10e}", i32::MIN), "-2.1474836480e9"); + assert_eq!(format!("{:.20e}", i64::MIN), "-9.22337203685477580800e18"); + assert_eq!(format!("{:.40e}", i128::MIN), "-1.7014118346046923173168730371588410572800e38"); + + //test rounding + assert_eq!(format!("{:.1e}", i8::MIN), "-1.3e2"); + assert_eq!(format!("{:.1e}", i16::MIN), "-3.3e4"); + assert_eq!(format!("{:.1e}", i32::MIN), "-2.1e9"); + assert_eq!(format!("{:.1e}", i64::MIN), "-9.2e18"); + assert_eq!(format!("{:.1e}", i128::MIN), "-1.7e38"); + + //test huge precision + assert_eq!(format!("{:.1000e}", 1), format!("1.{}e0", "0".repeat(1000))); + //test zero precision + assert_eq!(format!("{:.0e}", 1), format!("1e0",)); + + //test padding with precision (and sign) + assert_eq!(format!("{:+10.3e}", 1), " +1.000e0"); } #[test] @@ -86,6 +162,8 @@ fn test_format_int_zero() { assert_eq!(format!("{:o}", 0), "0"); assert_eq!(format!("{:x}", 0), "0"); assert_eq!(format!("{:X}", 0), "0"); + assert_eq!(format!("{:e}", 0), "0e0"); + assert_eq!(format!("{:E}", 0), "0E0"); assert_eq!(format!("{}", 0u32), "0"); assert_eq!(format!("{:?}", 0u32), "0"); @@ -93,6 +171,8 @@ fn test_format_int_zero() { assert_eq!(format!("{:o}", 0u32), "0"); assert_eq!(format!("{:x}", 0u32), "0"); assert_eq!(format!("{:X}", 0u32), "0"); + assert_eq!(format!("{:e}", 0u32), "0e0"); + assert_eq!(format!("{:E}", 0u32), "0E0"); } #[test] From 98757f14d0242e6dcae258df8aeb7e17580702ef Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 14 Feb 2020 22:28:13 -0500 Subject: [PATCH 0184/1250] Suggest a comma if a struct initializer field fails to parse Currently, we emit a "try adding a comma" suggestion if a comma is missing in a struct definition. However, we emit no such suggestion if a comma is missing in a struct initializer. This commit adds a "try adding a comma" suggestion when we don't find a comma during the parsing of a struct initializer field. The change to `src/test/ui/parser/removed-syntax-with-1.stderr` isn't great, but I don't see a good way of avoiding it. --- src/librustc_parse/parser/expr.rs | 8 ++++++- .../ui/parser/removed-syntax-with-1.stderr | 5 ++-- .../suggestions/struct-initializer-comma.rs | 13 +++++++++++ .../struct-initializer-comma.stderr | 23 +++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/suggestions/struct-initializer-comma.rs create mode 100644 src/test/ui/suggestions/struct-initializer-comma.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 5a4225ece65..20b9df0a2d9 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1832,10 +1832,16 @@ impl<'a> Parser<'a> { } } Err(mut e) => { + e.span_label(struct_sp, "while parsing this struct"); if let Some(f) = recovery_field { fields.push(f); + e.span_suggestion( + self.prev_span.shrink_to_hi(), + "try adding a comma", + ",".into(), + Applicability::MachineApplicable, + ); } - e.span_label(struct_sp, "while parsing this struct"); e.emit(); self.recover_stmt_(SemiColonMode::Comma, BlockMode::Ignore); self.eat(&token::Comma); diff --git a/src/test/ui/parser/removed-syntax-with-1.stderr b/src/test/ui/parser/removed-syntax-with-1.stderr index 193138d7460..c3f747b61b9 100644 --- a/src/test/ui/parser/removed-syntax-with-1.stderr +++ b/src/test/ui/parser/removed-syntax-with-1.stderr @@ -2,8 +2,9 @@ error: expected one of `,`, `.`, `?`, `}`, or an operator, found `with` --> $DIR/removed-syntax-with-1.rs:8:25 | LL | let b = S { foo: () with a, bar: () }; - | - ^^^^ expected one of `,`, `.`, `?`, `}`, or an operator - | | + | - -^^^^ expected one of `,`, `.`, `?`, `}`, or an operator + | | | + | | help: try adding a comma: `,` | while parsing this struct error: aborting due to previous error diff --git a/src/test/ui/suggestions/struct-initializer-comma.rs b/src/test/ui/suggestions/struct-initializer-comma.rs new file mode 100644 index 00000000000..613b976848f --- /dev/null +++ b/src/test/ui/suggestions/struct-initializer-comma.rs @@ -0,0 +1,13 @@ +struct Foo { + first: bool, + second: u8, +} + +fn main() { + let a = Foo { + //~^ ERROR missing field + first: true + second: 25 + //~^ ERROR expected one of + }; +} diff --git a/src/test/ui/suggestions/struct-initializer-comma.stderr b/src/test/ui/suggestions/struct-initializer-comma.stderr new file mode 100644 index 00000000000..731e8e10ab3 --- /dev/null +++ b/src/test/ui/suggestions/struct-initializer-comma.stderr @@ -0,0 +1,23 @@ +error: expected one of `,`, `.`, `?`, `}`, or an operator, found `second` + --> $DIR/struct-initializer-comma.rs:10:9 + | +LL | let a = Foo { + | --- while parsing this struct +LL | +LL | first: true + | - + | | + | expected one of `,`, `.`, `?`, `}`, or an operator + | help: try adding a comma: `,` +LL | second: 25 + | ^^^^^^ unexpected token + +error[E0063]: missing field `second` in initializer of `Foo` + --> $DIR/struct-initializer-comma.rs:7:13 + | +LL | let a = Foo { + | ^^^ missing `second` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0063`. From 821f4a9dfb38dab30df861d3c19788b2e7ed0d95 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 15 Feb 2020 17:43:14 +1300 Subject: [PATCH 0185/1250] Monomorphize const type during codegen. --- src/librustc_codegen_ssa/mir/constant.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 8722aacca72..3bd1755927b 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -30,7 +30,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => { let val = self.eval_mir_constant(constant)?; - Ok(OperandRef::from_const(bx, val.clone(), constant.literal.ty)) + let ty = self.monomorphize(&constant.literal.ty); + Ok(OperandRef::from_const(bx, val.clone(), ty)) } } } From bcd7e2b38b3eb26004bf94a63814341329233491 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 15 Feb 2020 12:38:34 +0300 Subject: [PATCH 0186/1250] rustc_lint: Move `unused_doc_comments` from pre-expansion to early lints --- src/librustc_lint/lib.rs | 3 ++- src/test/ui/useless-comment.rs | 4 ++-- src/test/ui/useless-comment.stderr | 31 ++++++------------------------ 3 files changed, 10 insertions(+), 28 deletions(-) diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2204e104803..d3670056c1a 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -94,7 +94,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: DefId) { macro_rules! pre_expansion_lint_passes { ($macro:path, $args:tt) => { - $macro!($args, [KeywordIdents: KeywordIdents, UnusedDocComment: UnusedDocComment,]); + $macro!($args, [KeywordIdents: KeywordIdents,]); }; } @@ -114,6 +114,7 @@ macro_rules! early_lint_passes { NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, RedundantSemicolon: RedundantSemicolon, + UnusedDocComment: UnusedDocComment, ] ); }; diff --git a/src/test/ui/useless-comment.rs b/src/test/ui/useless-comment.rs index 7d2e5ab6f2b..f19c97e0102 100644 --- a/src/test/ui/useless-comment.rs +++ b/src/test/ui/useless-comment.rs @@ -6,7 +6,7 @@ macro_rules! mac { () => {} } -/// foo //~ ERROR unused doc comment +/// foo //FIXME ERROR unused doc comment mac!(); fn foo() { @@ -29,7 +29,7 @@ fn foo() { #[doc = "bar"] //~ ERROR unused doc comment 3; - /// bar //~ ERROR unused doc comment + /// bar //FIXME ERROR unused doc comment mac!(); let x = /** comment */ 47; //~ ERROR unused doc comment diff --git a/src/test/ui/useless-comment.stderr b/src/test/ui/useless-comment.stderr index e5e4290d0e1..beb2a09f10e 100644 --- a/src/test/ui/useless-comment.stderr +++ b/src/test/ui/useless-comment.stderr @@ -1,25 +1,16 @@ error: unused doc comment - --> $DIR/useless-comment.rs:9:1 + --> $DIR/useless-comment.rs:13:5 | -LL | /// foo - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | mac!(); - | ------- rustdoc does not generate documentation for macro expansions +LL | /// a + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements | note: the lint level is defined here --> $DIR/useless-comment.rs:3:9 | LL | #![deny(unused_doc_comments)] | ^^^^^^^^^^^^^^^^^^^ - = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion - -error: unused doc comment - --> $DIR/useless-comment.rs:13:5 - | -LL | /// a - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let x = 12; - | ----------- rustdoc does not generate documentation for statements error: unused doc comment --> $DIR/useless-comment.rs:16:5 @@ -68,16 +59,6 @@ LL | #[doc = "bar"] LL | 3; | - rustdoc does not generate documentation for expressions -error: unused doc comment - --> $DIR/useless-comment.rs:32:5 - | -LL | /// bar - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | mac!(); - | ------- rustdoc does not generate documentation for macro expansions - | - = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion - error: unused doc comment --> $DIR/useless-comment.rs:35:13 | @@ -94,5 +75,5 @@ LL | | LL | | } | |_____- rustdoc does not generate documentation for expressions -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors From bd485223149e35c1c4e6b3ecf58653e38de4b6c9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 10:47:27 +0100 Subject: [PATCH 0187/1250] fix tests, and use variants to test debug and release builds together --- src/test/ui/consts/array-literal-index-oob.rs | 4 +- .../ui/consts/array-literal-index-oob.stderr | 16 +- ...st-err2.stderr => const-err2.debug.stderr} | 38 ++- src/test/ui/consts/const-err2.opt.stderr | 48 ++++ ...const-err2.opt_with_overflow_checks.stderr | 48 ++++ src/test/ui/consts/const-err2.rs | 23 +- src/test/ui/consts/const-err3.rs | 38 --- src/test/ui/consts/const-err3.stderr | 50 ---- .../index_out_of_bounds_propagated.rs | 2 +- .../index_out_of_bounds_propagated.stderr | 6 +- .../const-eval/promoted_errors.debug.stderr | 78 ++++++ .../const-eval/promoted_errors.opt.stderr | 72 ++++++ ...ted_errors.opt_with_overflow_checks.stderr | 78 ++++++ .../ui/consts/const-eval/promoted_errors.rs | 23 +- .../consts/const-eval/promoted_errors.stderr | 60 ----- .../ui/consts/const-eval/promoted_errors2.rs | 24 -- .../consts/const-eval/promoted_errors2.stderr | 66 ------ src/test/ui/consts/const-prop-ice.rs | 2 +- src/test/ui/consts/const-prop-ice.stderr | 6 +- src/test/ui/consts/const-prop-ice2.rs | 2 +- src/test/ui/consts/const-prop-ice2.stderr | 6 +- .../ui/issues/issue-8460-const.debug.stderr | 150 ++++++++++++ .../ui/issues/issue-8460-const.opt.stderr | 150 ++++++++++++ ...8460-const.opt_with_overflow_checks.stderr | 150 ++++++++++++ src/test/ui/issues/issue-8460-const.rs | 66 +++--- src/test/ui/issues/issue-8460-const.stderr | 224 ------------------ src/test/ui/issues/issue-8460-const2.rs | 58 ----- src/test/ui/issues/issue-8460-const2.stderr | 152 ------------ 28 files changed, 872 insertions(+), 768 deletions(-) rename src/test/ui/consts/{const-err2.stderr => const-err2.debug.stderr} (51%) create mode 100644 src/test/ui/consts/const-err2.opt.stderr create mode 100644 src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr delete mode 100644 src/test/ui/consts/const-err3.rs delete mode 100644 src/test/ui/consts/const-err3.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors.debug.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors.opt.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr delete mode 100644 src/test/ui/consts/const-eval/promoted_errors.stderr delete mode 100644 src/test/ui/consts/const-eval/promoted_errors2.rs delete mode 100644 src/test/ui/consts/const-eval/promoted_errors2.stderr create mode 100644 src/test/ui/issues/issue-8460-const.debug.stderr create mode 100644 src/test/ui/issues/issue-8460-const.opt.stderr create mode 100644 src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr delete mode 100644 src/test/ui/issues/issue-8460-const.stderr delete mode 100644 src/test/ui/issues/issue-8460-const2.rs delete mode 100644 src/test/ui/issues/issue-8460-const2.stderr diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index af63d1f75a7..978f2333101 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -1,11 +1,11 @@ // build-pass // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) -#![warn(const_err)] +#![warn(const_err, panic)] fn main() { &{ [1, 2, 3][4] }; - //~^ WARN index out of bounds + //~^ WARN operation will panic //~| WARN reaching this expression at runtime will panic or abort //~| WARN erroneous constant used [const_err] } diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 59e11697015..605cd73db1f 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -1,14 +1,14 @@ -warning: index out of bounds: the len is 3 but the index is 4 +warning: this operation will panic at runtime --> $DIR/array-literal-index-oob.rs:7:8 | LL | &{ [1, 2, 3][4] }; - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4 | note: the lint level is defined here - --> $DIR/array-literal-index-oob.rs:4:9 + --> $DIR/array-literal-index-oob.rs:4:20 | -LL | #![warn(const_err)] - | ^^^^^^^^^ +LL | #![warn(const_err, panic)] + | ^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/array-literal-index-oob.rs:7:8 @@ -17,6 +17,12 @@ LL | &{ [1, 2, 3][4] }; | ---^^^^^^^^^^^^-- | | | indexing out of bounds: the len is 3 but the index is 4 + | +note: the lint level is defined here + --> $DIR/array-literal-index-oob.rs:4:9 + | +LL | #![warn(const_err, panic)] + | ^^^^^^^^^ warning: erroneous constant used --> $DIR/array-literal-index-oob.rs:7:5 diff --git a/src/test/ui/consts/const-err2.stderr b/src/test/ui/consts/const-err2.debug.stderr similarity index 51% rename from src/test/ui/consts/const-err2.stderr rename to src/test/ui/consts/const-err2.debug.stderr index f135bf0b06c..226874c29da 100644 --- a/src/test/ui/consts/const-err2.stderr +++ b/src/test/ui/consts/const-err2.debug.stderr @@ -1,50 +1,48 @@ -error: this expression will panic at runtime - --> $DIR/const-err2.rs:18:13 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 | LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | -note: the lint level is defined here - --> $DIR/const-err2.rs:11:9 - | -LL | #![deny(const_err)] - | ^^^^^^^^^ + = note: `#[deny(overflow)]` on by default -error: this expression will panic at runtime - --> $DIR/const-err2.rs:20:18 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 | LL | let a_i128 = -std::i128::MIN; | ^^^^^^^^^^^^^^^ attempt to negate with overflow -error: this expression will panic at runtime - --> $DIR/const-err2.rs:22:13 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 | LL | let b = 200u8 + 200u8 + 200u8; | ^^^^^^^^^^^^^ attempt to add with overflow -error: this expression will panic at runtime - --> $DIR/const-err2.rs:24:18 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 | LL | let b_i128 = std::i128::MIN - std::i128::MAX; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow -error: this expression will panic at runtime - --> $DIR/const-err2.rs:26:13 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 | LL | let c = 200u8 * 4; | ^^^^^^^^^ attempt to multiply with overflow -error: this expression will panic at runtime - --> $DIR/const-err2.rs:28:13 +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 | LL | let d = 42u8 - (42u8 + 1); | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow -error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err2.rs:30:14 +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 | LL | let _e = [5u8][1]; - | ^^^^^^^^ + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + | + = note: `#[deny(panic)]` on by default error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-err2.opt.stderr b/src/test/ui/consts/const-err2.opt.stderr new file mode 100644 index 00000000000..226874c29da --- /dev/null +++ b/src/test/ui/consts/const-err2.opt.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -std::i128::MIN; + | ^^^^^^^^^^^^^^^ attempt to negate with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to add with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = std::i128::MIN - std::i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to multiply with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + | + = note: `#[deny(panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr new file mode 100644 index 00000000000..226874c29da --- /dev/null +++ b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -std::i128::MIN; + | ^^^^^^^^^^^^^^^ attempt to negate with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to add with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = std::i128::MIN - std::i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to multiply with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + | + = note: `#[deny(panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index 7c5aaedda35..6ef4e17df83 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -2,13 +2,14 @@ // optimized compilation and unoptimized compilation and thus would // lead to different lints being emitted +// revisions: debug opt opt_with_overflow_checks +//[debug]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + // build-fail -// compile-flags: -O #![feature(rustc_attrs)] -#![allow(exceeding_bitshifts)] - -#![deny(const_err)] fn black_box(_: T) { unimplemented!() @@ -16,19 +17,19 @@ fn black_box(_: T) { fn main() { let a = -std::i8::MIN; - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let a_i128 = -std::i128::MIN; - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let b = 200u8 + 200u8 + 200u8; - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let b_i128 = std::i128::MIN - std::i128::MAX; - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let c = 200u8 * 4; - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let d = 42u8 - (42u8 + 1); - //~^ ERROR const_err + //~^ ERROR arithmetic operation will overflow let _e = [5u8][1]; - //~^ ERROR const_err + //~^ ERROR operation will panic black_box(a); black_box(a_i128); black_box(b); diff --git a/src/test/ui/consts/const-err3.rs b/src/test/ui/consts/const-err3.rs deleted file mode 100644 index 43aba4a8b01..00000000000 --- a/src/test/ui/consts/const-err3.rs +++ /dev/null @@ -1,38 +0,0 @@ -// needed because negating int::MIN will behave differently between -// optimized compilation and unoptimized compilation and thus would -// lead to different lints being emitted - -// build-fail -// compile-flags: -C overflow-checks=on -O - -#![feature(rustc_attrs)] -#![allow(exceeding_bitshifts)] - -#![deny(const_err)] - -fn black_box(_: T) { - unimplemented!() -} - -fn main() { - let a = -std::i8::MIN; - //~^ ERROR const_err - let a_i128 = -std::i128::MIN; - //~^ ERROR const_err - let b = 200u8 + 200u8 + 200u8; - //~^ ERROR const_err - let b_i128 = std::i128::MIN - std::i128::MAX; - //~^ ERROR const_err - let c = 200u8 * 4; - //~^ ERROR const_err - let d = 42u8 - (42u8 + 1); - //~^ ERROR const_err - let _e = [5u8][1]; - //~^ ERROR const_err - black_box(a); - black_box(a_i128); - black_box(b); - black_box(b_i128); - black_box(c); - black_box(d); -} diff --git a/src/test/ui/consts/const-err3.stderr b/src/test/ui/consts/const-err3.stderr deleted file mode 100644 index 05f64b87fcc..00000000000 --- a/src/test/ui/consts/const-err3.stderr +++ /dev/null @@ -1,50 +0,0 @@ -error: attempt to negate with overflow - --> $DIR/const-err3.rs:18:13 - | -LL | let a = -std::i8::MIN; - | ^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/const-err3.rs:11:9 - | -LL | #![deny(const_err)] - | ^^^^^^^^^ - -error: attempt to negate with overflow - --> $DIR/const-err3.rs:20:18 - | -LL | let a_i128 = -std::i128::MIN; - | ^^^^^^^^^^^^^^^ - -error: attempt to add with overflow - --> $DIR/const-err3.rs:22:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ - -error: attempt to subtract with overflow - --> $DIR/const-err3.rs:24:18 - | -LL | let b_i128 = std::i128::MIN - std::i128::MAX; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: attempt to multiply with overflow - --> $DIR/const-err3.rs:26:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ - -error: attempt to subtract with overflow - --> $DIR/const-err3.rs:28:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ - -error: index out of bounds: the len is 1 but the index is 1 - --> $DIR/const-err3.rs:30:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ - -error: aborting due to 7 previous errors - diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs index 6d6bb94d4df..608e6e112a1 100644 --- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs +++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.rs @@ -2,5 +2,5 @@ fn main() { let array = [std::env::args().len()]; - array[1]; //~ ERROR index out of bounds + array[1]; //~ ERROR operation will panic } diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr index 9519ccd3c24..5da802d30f5 100644 --- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr +++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr @@ -1,10 +1,10 @@ -error: index out of bounds: the len is 1 but the index is 1 +error: this operation will panic at runtime --> $DIR/index_out_of_bounds_propagated.rs:5:5 | LL | array[1]; - | ^^^^^^^^ + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(const_err)]` on by default + = note: `#[deny(panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/promoted_errors.debug.stderr b/src/test/ui/consts/const-eval/promoted_errors.debug.stderr new file mode 100644 index 00000000000..1ed60c1f96e --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors.debug.stderr @@ -0,0 +1,78 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:12:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ attempt to subtract with overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:20 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:14:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ attempt to divide by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:30 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^ + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ dividing by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:9 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^^ + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:20:14 + | +LL | let _x = 1 / (1 - 1); + | ^^^^^^^^^^^ attempt to divide by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ dividing by zero + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:26:14 + | +LL | let _x = 1 / (false as u32); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr new file mode 100644 index 00000000000..8f21ce53715 --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr @@ -0,0 +1,72 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:14:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:20 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ attempt to divide by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:30 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^ + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ dividing by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:9 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^^ + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:20:14 + | +LL | let _x = 1 / (1 - 1); + | ^^^^^^^^^^^ attempt to divide by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ dividing by zero + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:26:14 + | +LL | let _x = 1 / (false as u32); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr new file mode 100644 index 00000000000..1ed60c1f96e --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr @@ -0,0 +1,78 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:12:20 + | +LL | println!("{}", 0u32 - 1); + | ^^^^^^^^ attempt to subtract with overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:20 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^ + +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:14:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ attempt to divide by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:30 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^ + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ dividing by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:9 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^^ + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:20:14 + | +LL | let _x = 1 / (1 - 1); + | ^^^^^^^^^^^ attempt to divide by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ dividing by zero + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:26:14 + | +LL | let _x = 1 / (false as u32); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index 22f863fb15a..5a4c7a66bf5 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,23 +1,28 @@ +// revisions: debug opt opt_with_overflow_checks +//[debug]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + // build-pass // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) -// compile-flags: -O -#![warn(const_err)] +#![warn(const_err, overflow, panic)] fn main() { println!("{}", 0u32 - 1); + //[opt_with_overflow_checks,debug]~^ WARN [overflow] let _x = 0u32 - 1; - //~^ WARN const_err + //~^ WARN [overflow] println!("{}", 1 / (1 - 1)); - //~^ WARN attempt to divide by zero [const_err] - //~| WARN const_err + //~^ WARN [panic] + //~| WARN panic or abort [const_err] //~| WARN erroneous constant used [const_err] let _x = 1 / (1 - 1); - //~^ WARN const_err + //~^ WARN [panic] println!("{}", 1 / (false as u32)); - //~^ WARN attempt to divide by zero [const_err] - //~| WARN const_err + //~^ WARN [panic] + //~| WARN panic or abort [const_err] //~| WARN erroneous constant used [const_err] let _x = 1 / (false as u32); - //~^ WARN const_err + //~^ WARN [panic] } diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr deleted file mode 100644 index 08ae5c7a32b..00000000000 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ /dev/null @@ -1,60 +0,0 @@ -warning: this expression will panic at runtime - --> $DIR/promoted_errors.rs:9:14 - | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempt to subtract with overflow - | -note: the lint level is defined here - --> $DIR/promoted_errors.rs:5:9 - | -LL | #![warn(const_err)] - | ^^^^^^^^^ - -warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:11:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:11:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ dividing by zero - -warning: erroneous constant used - --> $DIR/promoted_errors.rs:11:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ referenced constant has errors - -warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:15:14 - | -LL | let _x = 1 / (1 - 1); - | ^^^^^^^^^^^ - -warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:17:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:17:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ dividing by zero - -warning: erroneous constant used - --> $DIR/promoted_errors.rs:17:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ referenced constant has errors - -warning: attempt to divide by zero - --> $DIR/promoted_errors.rs:21:14 - | -LL | let _x = 1 / (false as u32); - | ^^^^^^^^^^^^^^^^^^ - diff --git a/src/test/ui/consts/const-eval/promoted_errors2.rs b/src/test/ui/consts/const-eval/promoted_errors2.rs deleted file mode 100644 index 62c77f76d90..00000000000 --- a/src/test/ui/consts/const-eval/promoted_errors2.rs +++ /dev/null @@ -1,24 +0,0 @@ -// build-pass -// ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) -// compile-flags: -C overflow-checks=on -O - -#![warn(const_err)] - -fn main() { - println!("{}", 0u32 - 1); - //~^ WARN attempt to subtract with overflow - let _x = 0u32 - 1; - //~^ WARN attempt to subtract with overflow - println!("{}", 1 / (1 - 1)); - //~^ WARN attempt to divide by zero [const_err] - //~| WARN const_err - //~| WARN erroneous constant used [const_err] - let _x = 1 / (1 - 1); - //~^ WARN const_err - println!("{}", 1 / (false as u32)); - //~^ WARN attempt to divide by zero [const_err] - //~| WARN const_err - //~| WARN erroneous constant used [const_err] - let _x = 1 / (false as u32); - //~^ WARN const_err -} diff --git a/src/test/ui/consts/const-eval/promoted_errors2.stderr b/src/test/ui/consts/const-eval/promoted_errors2.stderr deleted file mode 100644 index d1a9cb958e1..00000000000 --- a/src/test/ui/consts/const-eval/promoted_errors2.stderr +++ /dev/null @@ -1,66 +0,0 @@ -warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:8:20 - | -LL | println!("{}", 0u32 - 1); - | ^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/promoted_errors2.rs:5:9 - | -LL | #![warn(const_err)] - | ^^^^^^^^^ - -warning: attempt to subtract with overflow - --> $DIR/promoted_errors2.rs:10:14 - | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ - -warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:12:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors2.rs:12:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ dividing by zero - -warning: erroneous constant used - --> $DIR/promoted_errors2.rs:12:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ referenced constant has errors - -warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:16:14 - | -LL | let _x = 1 / (1 - 1); - | ^^^^^^^^^^^ - -warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:18:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors2.rs:18:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ dividing by zero - -warning: erroneous constant used - --> $DIR/promoted_errors2.rs:18:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ referenced constant has errors - -warning: attempt to divide by zero - --> $DIR/promoted_errors2.rs:22:14 - | -LL | let _x = 1 / (false as u32); - | ^^^^^^^^^^^^^^^^^^ - diff --git a/src/test/ui/consts/const-prop-ice.rs b/src/test/ui/consts/const-prop-ice.rs index 8682d2ee901..5bffe020629 100644 --- a/src/test/ui/consts/const-prop-ice.rs +++ b/src/test/ui/consts/const-prop-ice.rs @@ -1,5 +1,5 @@ // build-fail fn main() { - [0; 3][3u64 as usize]; //~ ERROR the len is 3 but the index is 3 + [0; 3][3u64 as usize]; //~ ERROR this operation will panic at runtime } diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr index 65502a4ff71..855b9e6b64b 100644 --- a/src/test/ui/consts/const-prop-ice.stderr +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -1,10 +1,10 @@ -error: index out of bounds: the len is 3 but the index is 3 +error: this operation will panic at runtime --> $DIR/const-prop-ice.rs:4:5 | LL | [0; 3][3u64 as usize]; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3 | - = note: `#[deny(const_err)]` on by default + = note: `#[deny(panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/consts/const-prop-ice2.rs b/src/test/ui/consts/const-prop-ice2.rs index 6a73483026f..d533e394c06 100644 --- a/src/test/ui/consts/const-prop-ice2.rs +++ b/src/test/ui/consts/const-prop-ice2.rs @@ -3,5 +3,5 @@ fn main() { enum Enum { One=1 } let xs=[0;1 as usize]; - println!("{}", xs[Enum::One as usize]); //~ ERROR the len is 1 but the index is 1 + println!("{}", xs[Enum::One as usize]); //~ ERROR this operation will panic at runtime } diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr index cbb8fde80f9..07faa39edc2 100644 --- a/src/test/ui/consts/const-prop-ice2.stderr +++ b/src/test/ui/consts/const-prop-ice2.stderr @@ -1,10 +1,10 @@ -error: index out of bounds: the len is 1 but the index is 1 +error: this operation will panic at runtime --> $DIR/const-prop-ice2.rs:6:20 | LL | println!("{}", xs[Enum::One as usize]); - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(const_err)]` on by default + = note: `#[deny(panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/issues/issue-8460-const.debug.stderr b/src/test/ui/issues/issue-8460-const.debug.stderr new file mode 100644 index 00000000000..33d846e3e91 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const.debug.stderr @@ -0,0 +1,150 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:14:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:18:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:20:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:22:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:24:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to divide with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:26:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:30:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:32:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:34:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:36:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide by zero + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:38:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:44:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:48:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:52:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:54:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:58:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:60:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/issues/issue-8460-const.opt.stderr new file mode 100644 index 00000000000..33d846e3e91 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const.opt.stderr @@ -0,0 +1,150 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:14:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:18:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:20:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:22:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:24:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to divide with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:26:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:30:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:32:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:34:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:36:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide by zero + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:38:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:44:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:48:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:52:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:54:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:58:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:60:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr new file mode 100644 index 00000000000..33d846e3e91 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr @@ -0,0 +1,150 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:14:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:18:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:20:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:22:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:24:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to divide with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:26:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:30:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:32:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:34:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:36:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide by zero + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:38:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:44:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:48:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:52:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:54:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:58:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:60:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 5866cef2d2c..3ab873952e2 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,5 +1,9 @@ +// revisions: debug opt opt_with_overflow_checks +//[debug]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + // build-fail -// compile-flags: -O #![deny(const_err)] @@ -8,63 +12,51 @@ use std::thread; fn main() { assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - //~| ERROR this expression will panic at runtime + //~^ ERROR arithmetic operation will overflow assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero + //~^ ERROR operation will panic } diff --git a/src/test/ui/issues/issue-8460-const.stderr b/src/test/ui/issues/issue-8460-const.stderr deleted file mode 100644 index d7373948cb9..00000000000 --- a/src/test/ui/issues/issue-8460-const.stderr +++ /dev/null @@ -1,224 +0,0 @@ -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:10:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-8460-const.rs:4:9 - | -LL | #![deny(const_err)] - | ^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:10:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:13:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:13:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:19:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:19:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:22:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:22:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide with overflow - --> $DIR/issue-8460-const.rs:25:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:25:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ attempt to divide with overflow - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:28:36 - | -LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - | ^^^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:30:36 - | -LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - | ^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:32:36 - | -LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:34:36 - | -LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:36:36 - | -LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const.rs:38:36 - | -LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); - | ^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:40:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:40:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:43:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:43:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:46:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:46:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:49:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:49:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:52:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const.rs:55:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ - -error: this expression will panic at runtime - --> $DIR/issue-8460-const.rs:55:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:58:36 - | -LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - | ^^^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:60:36 - | -LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - | ^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:62:36 - | -LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:64:36 - | -LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:66:36 - | -LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const.rs:68:36 - | -LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); - | ^^^^^^^^^ - -error: aborting due to 36 previous errors - diff --git a/src/test/ui/issues/issue-8460-const2.rs b/src/test/ui/issues/issue-8460-const2.rs deleted file mode 100644 index afea859bb65..00000000000 --- a/src/test/ui/issues/issue-8460-const2.rs +++ /dev/null @@ -1,58 +0,0 @@ -// build-fail -// compile-flags: -C overflow-checks=on -O - -#![deny(const_err)] - -use std::{isize, i8, i16, i32, i64, i128}; -use std::thread; - -fn main() { - assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - //~^ ERROR attempt to divide with overflow - assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); - //~^ ERROR attempt to divide by zero - assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with overflow - assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero - assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero - assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero - assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero - assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero - assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); - //~^ ERROR attempt to calculate the remainder with a divisor of zero -} diff --git a/src/test/ui/issues/issue-8460-const2.stderr b/src/test/ui/issues/issue-8460-const2.stderr deleted file mode 100644 index e25d560fe0c..00000000000 --- a/src/test/ui/issues/issue-8460-const2.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:10:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/issue-8460-const2.rs:4:9 - | -LL | #![deny(const_err)] - | ^^^^^^^^^ - -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:12:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ - -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:14:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:18:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to divide with overflow - --> $DIR/issue-8460-const2.rs:20:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:22:36 - | -LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - | ^^^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:24:36 - | -LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - | ^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:26:36 - | -LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:28:36 - | -LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:30:36 - | -LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to divide by zero - --> $DIR/issue-8460-const2.rs:32:36 - | -LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); - | ^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:34:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:36:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:38:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:40:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:42:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ - -error: attempt to calculate the remainder with overflow - --> $DIR/issue-8460-const2.rs:44:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:46:36 - | -LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - | ^^^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:48:36 - | -LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - | ^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:50:36 - | -LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:52:36 - | -LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:54:36 - | -LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - | ^^^^^^^^ - -error: attempt to calculate the remainder with a divisor of zero - --> $DIR/issue-8460-const2.rs:56:36 - | -LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); - | ^^^^^^^^^ - -error: aborting due to 24 previous errors - From 9c7639492ff4b3f6b812f355d4b8fe08cc81571d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 10:51:51 +0100 Subject: [PATCH 0188/1250] more revisions and use them for another test --- ...debug.stderr => const-err2.default.stderr} | 0 src/test/ui/consts/const-err2.noopt.stderr | 48 ++++++ src/test/ui/consts/const-err2.rs | 4 +- .../const-eval/promoted_errors.default.stderr | 72 +++++++++ ...ug.stderr => promoted_errors.noopt.stderr} | 0 .../ui/consts/const-eval/promoted_errors.rs | 6 +- src/test/ui/consts/issue-64059-2.rs | 6 - src/test/ui/consts/issue-64059.rs | 5 + ...stderr => issue-8460-const.default.stderr} | 0 .../ui/issues/issue-8460-const.noopt.stderr | 150 ++++++++++++++++++ src/test/ui/issues/issue-8460-const.rs | 4 +- 11 files changed, 282 insertions(+), 13 deletions(-) rename src/test/ui/consts/{const-err2.debug.stderr => const-err2.default.stderr} (100%) create mode 100644 src/test/ui/consts/const-err2.noopt.stderr create mode 100644 src/test/ui/consts/const-eval/promoted_errors.default.stderr rename src/test/ui/consts/const-eval/{promoted_errors.debug.stderr => promoted_errors.noopt.stderr} (100%) delete mode 100644 src/test/ui/consts/issue-64059-2.rs rename src/test/ui/issues/{issue-8460-const.debug.stderr => issue-8460-const.default.stderr} (100%) create mode 100644 src/test/ui/issues/issue-8460-const.noopt.stderr diff --git a/src/test/ui/consts/const-err2.debug.stderr b/src/test/ui/consts/const-err2.default.stderr similarity index 100% rename from src/test/ui/consts/const-err2.debug.stderr rename to src/test/ui/consts/const-err2.default.stderr diff --git a/src/test/ui/consts/const-err2.noopt.stderr b/src/test/ui/consts/const-err2.noopt.stderr new file mode 100644 index 00000000000..226874c29da --- /dev/null +++ b/src/test/ui/consts/const-err2.noopt.stderr @@ -0,0 +1,48 @@ +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:19:13 + | +LL | let a = -std::i8::MIN; + | ^^^^^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:21:18 + | +LL | let a_i128 = -std::i128::MIN; + | ^^^^^^^^^^^^^^^ attempt to negate with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:23:13 + | +LL | let b = 200u8 + 200u8 + 200u8; + | ^^^^^^^^^^^^^ attempt to add with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:25:18 + | +LL | let b_i128 = std::i128::MIN - std::i128::MAX; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:27:13 + | +LL | let c = 200u8 * 4; + | ^^^^^^^^^ attempt to multiply with overflow + +error: this arithmetic operation will overflow + --> $DIR/const-err2.rs:29:13 + | +LL | let d = 42u8 - (42u8 + 1); + | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow + +error: this operation will panic at runtime + --> $DIR/const-err2.rs:31:14 + | +LL | let _e = [5u8][1]; + | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 + | + = note: `#[deny(panic)]` on by default + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index 6ef4e17df83..2c0cae0e451 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -2,8 +2,8 @@ // optimized compilation and unoptimized compilation and thus would // lead to different lints being emitted -// revisions: debug opt opt_with_overflow_checks -//[debug]compile-flags: -C opt-level=0 +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/consts/const-eval/promoted_errors.default.stderr b/src/test/ui/consts/const-eval/promoted_errors.default.stderr new file mode 100644 index 00000000000..8f21ce53715 --- /dev/null +++ b/src/test/ui/consts/const-eval/promoted_errors.default.stderr @@ -0,0 +1,72 @@ +warning: this arithmetic operation will overflow + --> $DIR/promoted_errors.rs:14:14 + | +LL | let _x = 0u32 - 1; + | ^^^^^^^^ attempt to subtract with overflow + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:20 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^ + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ attempt to divide by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:30 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^ + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ dividing by zero + | +note: the lint level is defined here + --> $DIR/promoted_errors.rs:9:9 + | +LL | #![warn(const_err, overflow, panic)] + | ^^^^^^^^^ + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:16:20 + | +LL | println!("{}", 1 / (1 - 1)); + | ^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:20:14 + | +LL | let _x = 1 / (1 - 1); + | ^^^^^^^^^^^ attempt to divide by zero + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + +warning: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ dividing by zero + +warning: erroneous constant used + --> $DIR/promoted_errors.rs:22:20 + | +LL | println!("{}", 1 / (false as u32)); + | ^^^^^^^^^^^^^^^^^^ referenced constant has errors + +warning: this operation will panic at runtime + --> $DIR/promoted_errors.rs:26:14 + | +LL | let _x = 1 / (false as u32); + | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero + diff --git a/src/test/ui/consts/const-eval/promoted_errors.debug.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr similarity index 100% rename from src/test/ui/consts/const-eval/promoted_errors.debug.stderr rename to src/test/ui/consts/const-eval/promoted_errors.noopt.stderr diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index 5a4c7a66bf5..3133e9b380b 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,5 +1,5 @@ -// revisions: debug opt opt_with_overflow_checks -//[debug]compile-flags: -C opt-level=0 +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O @@ -10,7 +10,7 @@ fn main() { println!("{}", 0u32 - 1); - //[opt_with_overflow_checks,debug]~^ WARN [overflow] + //[opt_with_overflow_checks,noopt]~^ WARN [overflow] let _x = 0u32 - 1; //~^ WARN [overflow] println!("{}", 1 / (1 - 1)); diff --git a/src/test/ui/consts/issue-64059-2.rs b/src/test/ui/consts/issue-64059-2.rs deleted file mode 100644 index 38911c3dcf6..00000000000 --- a/src/test/ui/consts/issue-64059-2.rs +++ /dev/null @@ -1,6 +0,0 @@ -// compile-flags: -C overflow-checks=on -O -// run-pass - -fn main() { - let _ = -(-0.0); -} diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs index c4c895fef66..16bfda3b961 100644 --- a/src/test/ui/consts/issue-64059.rs +++ b/src/test/ui/consts/issue-64059.rs @@ -1,3 +1,8 @@ +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + // run-pass fn main() { diff --git a/src/test/ui/issues/issue-8460-const.debug.stderr b/src/test/ui/issues/issue-8460-const.default.stderr similarity index 100% rename from src/test/ui/issues/issue-8460-const.debug.stderr rename to src/test/ui/issues/issue-8460-const.default.stderr diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/issues/issue-8460-const.noopt.stderr new file mode 100644 index 00000000000..33d846e3e91 --- /dev/null +++ b/src/test/ui/issues/issue-8460-const.noopt.stderr @@ -0,0 +1,150 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:14:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to divide with overflow + | + = note: `#[deny(overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:16:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:18:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:20:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:22:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to divide with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:24:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to divide with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:26:36 + | +LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:28:36 + | +LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); + | ^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:30:36 + | +LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:32:36 + | +LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:34:36 + | +LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); + | ^^^^^^^^ attempt to divide by zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:36:36 + | +LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); + | ^^^^^^^^^ attempt to divide by zero + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:38:36 + | +LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:40:36 + | +LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:42:36 + | +LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:44:36 + | +LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:46:36 + | +LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-8460-const.rs:48:36 + | +LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); + | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:50:36 + | +LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); + | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:52:36 + | +LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); + | ^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:54:36 + | +LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:56:36 + | +LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:58:36 + | +LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); + | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: this operation will panic at runtime + --> $DIR/issue-8460-const.rs:60:36 + | +LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); + | ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero + +error: aborting due to 24 previous errors + diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index 3ab873952e2..d7276af40a7 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,5 +1,5 @@ -// revisions: debug opt opt_with_overflow_checks -//[debug]compile-flags: -C opt-level=0 +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O From 4b8c78496815e22652fdf0da216659fe06936b50 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 11:00:14 +0100 Subject: [PATCH 0189/1250] add test for issue 69020 --- src/test/ui/consts/issue-69020.default.stderr | 10 ++++++++++ src/test/ui/consts/issue-69020.noopt.stderr | 10 ++++++++++ src/test/ui/consts/issue-69020.opt.stderr | 10 ++++++++++ .../issue-69020.opt_with_overflow_checks.stderr | 10 ++++++++++ src/test/ui/consts/issue-69020.rs | 17 +++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 src/test/ui/consts/issue-69020.default.stderr create mode 100644 src/test/ui/consts/issue-69020.noopt.stderr create mode 100644 src/test/ui/consts/issue-69020.opt.stderr create mode 100644 src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr create mode 100644 src/test/ui/consts/issue-69020.rs diff --git a/src/test/ui/consts/issue-69020.default.stderr b/src/test/ui/consts/issue-69020.default.stderr new file mode 100644 index 00000000000..0bf40ce4b31 --- /dev/null +++ b/src/test/ui/consts/issue-69020.default.stderr @@ -0,0 +1,10 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:15:20 + | +LL | const N: i32 = -i32::MIN + T::N; + | ^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-69020.noopt.stderr b/src/test/ui/consts/issue-69020.noopt.stderr new file mode 100644 index 00000000000..0bf40ce4b31 --- /dev/null +++ b/src/test/ui/consts/issue-69020.noopt.stderr @@ -0,0 +1,10 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:15:20 + | +LL | const N: i32 = -i32::MIN + T::N; + | ^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-69020.opt.stderr b/src/test/ui/consts/issue-69020.opt.stderr new file mode 100644 index 00000000000..0bf40ce4b31 --- /dev/null +++ b/src/test/ui/consts/issue-69020.opt.stderr @@ -0,0 +1,10 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:15:20 + | +LL | const N: i32 = -i32::MIN + T::N; + | ^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr new file mode 100644 index 00000000000..0bf40ce4b31 --- /dev/null +++ b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr @@ -0,0 +1,10 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:15:20 + | +LL | const N: i32 = -i32::MIN + T::N; + | ^^^^^^^^^ attempt to negate with overflow + | + = note: `#[deny(overflow)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-69020.rs b/src/test/ui/consts/issue-69020.rs new file mode 100644 index 00000000000..9f1ed862c7b --- /dev/null +++ b/src/test/ui/consts/issue-69020.rs @@ -0,0 +1,17 @@ +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +#![crate_type="lib"] + +use std::i32; + +pub trait Foo { + const N: i32; +} + +impl Foo for Vec { + const N: i32 = -i32::MIN + T::N; + //~^ ERROR arithmetic operation will overflow +} From 2107e73d2f0605e916d7b17b1cc0dbb5a1353765 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 11:43:54 +0100 Subject: [PATCH 0190/1250] fix exceeding_bitshift lint and test --- src/librustc_mir/transform/const_prop.rs | 12 +- .../lint-exceeding-bitshifts.default.stderr | 146 ++++++++++++++++++ .../lint-exceeding-bitshifts.noopt.stderr | 146 ++++++++++++++++++ .../lint/lint-exceeding-bitshifts.opt.stderr | 146 ++++++++++++++++++ ...-bitshifts.opt_with_overflow_checks.stderr | 146 ++++++++++++++++++ src/test/ui/lint/lint-exceeding-bitshifts.rs | 69 ++++++--- .../ui/lint/lint-exceeding-bitshifts.stderr | 116 -------------- src/test/ui/lint/lint-exceeding-bitshifts2.rs | 20 --- .../ui/lint/lint-exceeding-bitshifts2.stderr | 32 ---- 9 files changed, 640 insertions(+), 193 deletions(-) create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.default.stderr create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr create mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr delete mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.stderr delete mode 100644 src/test/ui/lint/lint-exceeding-bitshifts2.rs delete mode 100644 src/test/ui/lint/lint-exceeding-bitshifts2.stderr diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 53acf1490bf..05e70ed217a 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -547,16 +547,18 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { left: &Operand<'tcx>, right: &Operand<'tcx>, source_info: SourceInfo, - place_layout: TyLayout<'tcx>, ) -> Option<()> { let r = self.use_ecx(|this| this.ecx.read_immediate(this.ecx.eval_operand(right, None)?))?; // Check for exceeding shifts *even if* we cannot evaluate the LHS. if op == BinOp::Shr || op == BinOp::Shl { - let left_bits = place_layout.size.bits(); + // We need the type of the LHS. We cannot use `place_layout` as that is the type + // of the result, which for checked binops is not the same! + let left_ty = left.ty(&self.local_decls, self.tcx); + let left_size_bits = self.ecx.layout_of(left_ty).ok()?.size.bits(); let right_size = r.layout.size; let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); - if r_bits.map_or(false, |b| b >= left_bits as u128) { + if r_bits.map_or(false, |b| b >= left_size_bits as u128) { self.report_assert_as_lint( lint::builtin::EXCEEDING_BITSHIFTS, source_info, @@ -618,7 +620,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } Rvalue::BinaryOp(op, left, right) => { trace!("checking BinaryOp(op = {:?}, left = {:?}, right = {:?})", op, left, right); - self.check_binary_op(*op, left, right, source_info, place_layout)?; + self.check_binary_op(*op, left, right, source_info)?; } Rvalue::CheckedBinaryOp(op, left, right) => { trace!( @@ -627,7 +629,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { left, right ); - self.check_binary_op(*op, left, right, source_info, place_layout)?; + self.check_binary_op(*op, left, right, source_info)?; } // Do not try creating references (#67862) diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr new file mode 100644 index 00000000000..5e32466c4e0 --- /dev/null +++ b/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr @@ -0,0 +1,146 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:9:9 + | +LL | #![deny(exceeding_bitshifts, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: aborting due to 23 previous errors + diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr new file mode 100644 index 00000000000..5e32466c4e0 --- /dev/null +++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -0,0 +1,146 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:9:9 + | +LL | #![deny(exceeding_bitshifts, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: aborting due to 23 previous errors + diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr new file mode 100644 index 00000000000..5e32466c4e0 --- /dev/null +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -0,0 +1,146 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:9:9 + | +LL | #![deny(exceeding_bitshifts, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: aborting due to 23 previous errors + diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr new file mode 100644 index 00000000000..5e32466c4e0 --- /dev/null +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -0,0 +1,146 @@ +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:22:13 + | +LL | let _ = x << 42; + | ^^^^^^^ attempt to shift left with overflow + | +note: the lint level is defined here + --> $DIR/lint-exceeding-bitshifts.rs:9:9 + | +LL | #![deny(exceeding_bitshifts, const_err)] + | ^^^^^^^^^^^^^^^^^^^ + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:27:15 + | +LL | let n = 1u8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:29:15 + | +LL | let n = 1u16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:31:15 + | +LL | let n = 1u32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:33:15 + | +LL | let n = 1u64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:35:15 + | +LL | let n = 1i8 << 8; + | ^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:37:15 + | +LL | let n = 1i16 << 16; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:39:15 + | +LL | let n = 1i32 << 32; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:41:15 + | +LL | let n = 1i64 << 64; + | ^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:44:15 + | +LL | let n = 1u8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:46:15 + | +LL | let n = 1u16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:48:15 + | +LL | let n = 1u32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:50:15 + | +LL | let n = 1u64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:52:15 + | +LL | let n = 1i8 >> 8; + | ^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:54:15 + | +LL | let n = 1i16 >> 16; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:56:15 + | +LL | let n = 1i32 >> 32; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:58:15 + | +LL | let n = 1i64 >> 64; + | ^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:62:15 + | +LL | let n = n << 8; + | ^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:64:15 + | +LL | let n = 1u8 << -8; + | ^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:69:15 + | +LL | let n = 1u8 << (4+4); + | ^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:71:15 + | +LL | let n = 1i64 >> [64][0]; + | ^^^^^^^^^^^^^^^ attempt to shift right with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:77:15 + | +LL | let n = 1_isize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: this arithmetic operation will overflow + --> $DIR/lint-exceeding-bitshifts.rs:78:15 + | +LL | let n = 1_usize << BITS; + | ^^^^^^^^^^^^^^^ attempt to shift left with overflow + +error: aborting due to 23 previous errors + diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs index 121e5b796bb..3c6d70e7a6f 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs @@ -1,50 +1,79 @@ +// revisions: default noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + // build-fail -// compile-flags: -O +#![crate_type="lib"] #![deny(exceeding_bitshifts, const_err)] #![allow(unused_variables)] #![allow(dead_code)] -fn main() { +pub trait Foo { + const N: i32; +} + +impl Foo for Vec { + const N: i32 = T::N << 42; // FIXME this should warn +} + +pub fn foo(x: i32) { + let _ = x << 42; //~ ERROR: arithmetic operation will overflow +} + +pub fn main() { let n = 1u8 << 7; - let n = 1u8 << 8; //~ ERROR: attempt to shift left with overflow + let n = 1u8 << 8; //~ ERROR: arithmetic operation will overflow let n = 1u16 << 15; - let n = 1u16 << 16; //~ ERROR: attempt to shift left with overflow + let n = 1u16 << 16; //~ ERROR: arithmetic operation will overflow let n = 1u32 << 31; - let n = 1u32 << 32; //~ ERROR: attempt to shift left with overflow + let n = 1u32 << 32; //~ ERROR: arithmetic operation will overflow let n = 1u64 << 63; - let n = 1u64 << 64; //~ ERROR: attempt to shift left with overflow + let n = 1u64 << 64; //~ ERROR: arithmetic operation will overflow let n = 1i8 << 7; - let n = 1i8 << 8; //~ ERROR: attempt to shift left with overflow + let n = 1i8 << 8; //~ ERROR: arithmetic operation will overflow let n = 1i16 << 15; - let n = 1i16 << 16; //~ ERROR: attempt to shift left with overflow + let n = 1i16 << 16; //~ ERROR: arithmetic operation will overflow let n = 1i32 << 31; - let n = 1i32 << 32; //~ ERROR: attempt to shift left with overflow + let n = 1i32 << 32; //~ ERROR: arithmetic operation will overflow let n = 1i64 << 63; - let n = 1i64 << 64; //~ ERROR: attempt to shift left with overflow + let n = 1i64 << 64; //~ ERROR: arithmetic operation will overflow let n = 1u8 >> 7; - let n = 1u8 >> 8; //~ ERROR: attempt to shift right with overflow + let n = 1u8 >> 8; //~ ERROR: arithmetic operation will overflow let n = 1u16 >> 15; - let n = 1u16 >> 16; //~ ERROR: attempt to shift right with overflow + let n = 1u16 >> 16; //~ ERROR: arithmetic operation will overflow let n = 1u32 >> 31; - let n = 1u32 >> 32; //~ ERROR: attempt to shift right with overflow + let n = 1u32 >> 32; //~ ERROR: arithmetic operation will overflow let n = 1u64 >> 63; - let n = 1u64 >> 64; //~ ERROR: attempt to shift right with overflow + let n = 1u64 >> 64; //~ ERROR: arithmetic operation will overflow let n = 1i8 >> 7; - let n = 1i8 >> 8; //~ ERROR: attempt to shift right with overflow + let n = 1i8 >> 8; //~ ERROR: arithmetic operation will overflow let n = 1i16 >> 15; - let n = 1i16 >> 16; //~ ERROR: attempt to shift right with overflow + let n = 1i16 >> 16; //~ ERROR: arithmetic operation will overflow let n = 1i32 >> 31; - let n = 1i32 >> 32; //~ ERROR: attempt to shift right with overflow + let n = 1i32 >> 32; //~ ERROR: arithmetic operation will overflow let n = 1i64 >> 63; - let n = 1i64 >> 64; //~ ERROR: attempt to shift right with overflow + let n = 1i64 >> 64; //~ ERROR: arithmetic operation will overflow let n = 1u8; let n = n << 7; - let n = n << 8; //~ ERROR: attempt to shift left with overflow + let n = n << 8; //~ ERROR: arithmetic operation will overflow - let n = 1u8 << -8; //~ ERROR: attempt to shift left with overflow + let n = 1u8 << -8; //~ ERROR: arithmetic operation will overflow let n = 1i8<<(1isize+-1); + + let n = 1u8 << (4+3); + let n = 1u8 << (4+4); //~ ERROR: arithmetic operation will overflow + let n = 1i64 >> [63][0]; + let n = 1i64 >> [64][0]; //~ ERROR: arithmetic operation will overflow + + #[cfg(target_pointer_width = "32")] + const BITS: usize = 32; + #[cfg(target_pointer_width = "64")] + const BITS: usize = 64; + let n = 1_isize << BITS; //~ ERROR: arithmetic operation will overflow + let n = 1_usize << BITS; //~ ERROR: arithmetic operation will overflow } diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.stderr deleted file mode 100644 index 658577213b3..00000000000 --- a/src/test/ui/lint/lint-exceeding-bitshifts.stderr +++ /dev/null @@ -1,116 +0,0 @@ -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:10:15 - | -LL | let n = 1u8 << 8; - | ^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts.rs:4:9 - | -LL | #![deny(exceeding_bitshifts, const_err)] - | ^^^^^^^^^^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:12:15 - | -LL | let n = 1u16 << 16; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:14:15 - | -LL | let n = 1u32 << 32; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:16:15 - | -LL | let n = 1u64 << 64; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:18:15 - | -LL | let n = 1i8 << 8; - | ^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:20:15 - | -LL | let n = 1i16 << 16; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:15 - | -LL | let n = 1i32 << 32; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:24:15 - | -LL | let n = 1i64 << 64; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:27:15 - | -LL | let n = 1u8 >> 8; - | ^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 - | -LL | let n = 1u16 >> 16; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 - | -LL | let n = 1u32 >> 32; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 - | -LL | let n = 1u64 >> 64; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 - | -LL | let n = 1i8 >> 8; - | ^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 - | -LL | let n = 1i16 >> 16; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 - | -LL | let n = 1i32 >> 32; - | ^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 - | -LL | let n = 1i64 >> 64; - | ^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:45:15 - | -LL | let n = n << 8; - | ^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts.rs:47:15 - | -LL | let n = 1u8 << -8; - | ^^^^^^^^^ - -error: aborting due to 18 previous errors - diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.rs b/src/test/ui/lint/lint-exceeding-bitshifts2.rs deleted file mode 100644 index 2a7cbc10f77..00000000000 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// build-fail -// compile-flags: -O - -#![deny(exceeding_bitshifts, const_err)] -#![allow(unused_variables)] -#![allow(dead_code)] - -fn main() { - let n = 1u8 << (4+3); - let n = 1u8 << (4+4); //~ ERROR: attempt to shift left with overflow - let n = 1i64 >> [63][0]; - let n = 1i64 >> [64][0]; //~ ERROR: attempt to shift right with overflow - - #[cfg(target_pointer_width = "32")] - const BITS: usize = 32; - #[cfg(target_pointer_width = "64")] - const BITS: usize = 64; - let n = 1_isize << BITS; //~ ERROR: attempt to shift left with overflow - let n = 1_usize << BITS; //~ ERROR: attempt to shift left with overflow -} diff --git a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr b/src/test/ui/lint/lint-exceeding-bitshifts2.stderr deleted file mode 100644 index ac9f3b1e56b..00000000000 --- a/src/test/ui/lint/lint-exceeding-bitshifts2.stderr +++ /dev/null @@ -1,32 +0,0 @@ -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts2.rs:10:15 - | -LL | let n = 1u8 << (4+4); - | ^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts2.rs:4:9 - | -LL | #![deny(exceeding_bitshifts, const_err)] - | ^^^^^^^^^^^^^^^^^^^ - -error: attempt to shift right with overflow - --> $DIR/lint-exceeding-bitshifts2.rs:12:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts2.rs:18:15 - | -LL | let n = 1_isize << BITS; - | ^^^^^^^^^^^^^^^ - -error: attempt to shift left with overflow - --> $DIR/lint-exceeding-bitshifts2.rs:19:15 - | -LL | let n = 1_usize << BITS; - | ^^^^^^^^^^^^^^^ - -error: aborting due to 4 previous errors - From 415218fc8d590063a8c5cd403ff890fb91c0bd2c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 11:47:11 +0100 Subject: [PATCH 0191/1250] expand assoc-const test a bit, just to be sure --- src/test/ui/consts/issue-69020.default.stderr | 28 ++++++++++++++++--- src/test/ui/consts/issue-69020.noopt.stderr | 28 ++++++++++++++++--- src/test/ui/consts/issue-69020.opt.stderr | 28 ++++++++++++++++--- ...ssue-69020.opt_with_overflow_checks.stderr | 28 ++++++++++++++++--- src/test/ui/consts/issue-69020.rs | 16 +++++++++-- 5 files changed, 110 insertions(+), 18 deletions(-) diff --git a/src/test/ui/consts/issue-69020.default.stderr b/src/test/ui/consts/issue-69020.default.stderr index 0bf40ce4b31..1b1987f4dc3 100644 --- a/src/test/ui/consts/issue-69020.default.stderr +++ b/src/test/ui/consts/issue-69020.default.stderr @@ -1,10 +1,30 @@ error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:15:20 + --> $DIR/issue-69020.rs:21:22 | -LL | const N: i32 = -i32::MIN + T::N; - | ^^^^^^^^^ attempt to negate with overflow +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate with overflow | = note: `#[deny(overflow)]` on by default -error: aborting due to previous error +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:23:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to add with overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:25:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:27:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-69020.noopt.stderr b/src/test/ui/consts/issue-69020.noopt.stderr index 0bf40ce4b31..1b1987f4dc3 100644 --- a/src/test/ui/consts/issue-69020.noopt.stderr +++ b/src/test/ui/consts/issue-69020.noopt.stderr @@ -1,10 +1,30 @@ error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:15:20 + --> $DIR/issue-69020.rs:21:22 | -LL | const N: i32 = -i32::MIN + T::N; - | ^^^^^^^^^ attempt to negate with overflow +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate with overflow | = note: `#[deny(overflow)]` on by default -error: aborting due to previous error +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:23:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to add with overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:25:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:27:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-69020.opt.stderr b/src/test/ui/consts/issue-69020.opt.stderr index 0bf40ce4b31..1b1987f4dc3 100644 --- a/src/test/ui/consts/issue-69020.opt.stderr +++ b/src/test/ui/consts/issue-69020.opt.stderr @@ -1,10 +1,30 @@ error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:15:20 + --> $DIR/issue-69020.rs:21:22 | -LL | const N: i32 = -i32::MIN + T::N; - | ^^^^^^^^^ attempt to negate with overflow +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate with overflow | = note: `#[deny(overflow)]` on by default -error: aborting due to previous error +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:23:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to add with overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:25:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:27:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr index 0bf40ce4b31..1b1987f4dc3 100644 --- a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr +++ b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr @@ -1,10 +1,30 @@ error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:15:20 + --> $DIR/issue-69020.rs:21:22 | -LL | const N: i32 = -i32::MIN + T::N; - | ^^^^^^^^^ attempt to negate with overflow +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate with overflow | = note: `#[deny(overflow)]` on by default -error: aborting due to previous error +error: this arithmetic operation will overflow + --> $DIR/issue-69020.rs:23:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to add with overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:25:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide by zero + | + = note: `#[deny(panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020.rs:27:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the len is 1 but the index is 1 + +error: aborting due to 4 previous errors diff --git a/src/test/ui/consts/issue-69020.rs b/src/test/ui/consts/issue-69020.rs index 9f1ed862c7b..963ab01a33c 100644 --- a/src/test/ui/consts/issue-69020.rs +++ b/src/test/ui/consts/issue-69020.rs @@ -8,10 +8,22 @@ use std::i32; pub trait Foo { - const N: i32; + const NEG: i32; + const ADD: i32; + const DIV: i32; + const OOB: i32; } +// These constants cannot be evaluated already (they depend on `T::N`), so +// they can just be linted like normal run-time code. But codegen works +// a bit different in const context, so this test makes sure that we still catch overflow. impl Foo for Vec { - const N: i32 = -i32::MIN + T::N; + const NEG: i32 = -i32::MIN + T::NEG; //~^ ERROR arithmetic operation will overflow + const ADD: i32 = (i32::MAX+1) + T::ADD; + //~^ ERROR arithmetic operation will overflow + const DIV: i32 = (1/0) + T::DIV; + //~^ ERROR operation will panic + const OOB: i32 = [1][1] + T::OOB; + //~^ ERROR operation will panic } From 25870a0b77e8d0e37aecce17f1b37fc5bf630b56 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 13:15:15 +0100 Subject: [PATCH 0192/1250] fix another test --- src/test/ui/issues/issue-54348.rs | 4 ++-- src/test/ui/issues/issue-54348.stderr | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/ui/issues/issue-54348.rs b/src/test/ui/issues/issue-54348.rs index fd9a9e024aa..5c38d7c42f6 100644 --- a/src/test/ui/issues/issue-54348.rs +++ b/src/test/ui/issues/issue-54348.rs @@ -2,6 +2,6 @@ fn main() { [1][0u64 as usize]; - [1][1.5 as usize]; //~ ERROR index out of bounds - [1][1u64 as usize]; //~ ERROR index out of bounds + [1][1.5 as usize]; //~ ERROR operation will panic + [1][1u64 as usize]; //~ ERROR operation will panic } diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr index 7619cd7437e..f2156a35f2a 100644 --- a/src/test/ui/issues/issue-54348.stderr +++ b/src/test/ui/issues/issue-54348.stderr @@ -1,16 +1,16 @@ -error: index out of bounds: the len is 1 but the index is 1 +error: this operation will panic at runtime --> $DIR/issue-54348.rs:5:5 | LL | [1][1.5 as usize]; - | ^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(const_err)]` on by default + = note: `#[deny(panic)]` on by default -error: index out of bounds: the len is 1 but the index is 1 +error: this operation will panic at runtime --> $DIR/issue-54348.rs:6:5 | LL | [1][1u64 as usize]; - | ^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 error: aborting due to 2 previous errors From 1bd6b98220a7d161288f04a03111ca77b0a4845d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 15 Feb 2020 15:29:45 +0300 Subject: [PATCH 0193/1250] Emit some additional `unused_doc_comments` lints outside of the main pass --- src/librustc_expand/expand.rs | 5 +++++ src/librustc_lint/builtin.rs | 17 ++++++++++------- src/librustc_session/lint/builtin.rs | 8 ++++++++ src/test/ui/useless-comment.rs | 4 ++-- src/test/ui/useless-comment.stderr | 26 +++++++++++++++++++------- 5 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 371d1f744dd..3c720271e4b 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -14,6 +14,7 @@ use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_parse::DirectoryOwnership; +use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::source_map::respan; use rustc_span::symbol::{sym, Symbol}; @@ -1090,6 +1091,10 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { .note("this may become a hard error in a future release") .emit(); } + + if attr.doc_str().is_some() { + self.cx.parse_sess.buffer_lint(&UNUSED_DOC_COMMENTS, attr.span, ast::CRATE_NODE_ID, "yep, it's unused"); + } } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 93fca43d67c..c0eee7e05c8 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -738,15 +738,18 @@ impl EarlyLintPass for DeprecatedAttr { } } -declare_lint! { - pub UNUSED_DOC_COMMENTS, - Warn, - "detects doc comments that aren't used by rustdoc" +trait UnusedDocCommentExt { + fn warn_if_doc( + &self, + cx: &EarlyContext<'_>, + node_span: Span, + node_kind: &str, + is_macro_expansion: bool, + attrs: &[ast::Attribute], + ); } -declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); - -impl UnusedDocComment { +impl UnusedDocCommentExt for UnusedDocComment { fn warn_if_doc( &self, cx: &EarlyContext<'_>, diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 5a360b40d61..5e3367f8696 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -557,3 +557,11 @@ declare_lint_pass! { INLINE_NO_SANITIZE, ] } + +declare_lint! { + pub UNUSED_DOC_COMMENTS, + Warn, + "detects doc comments that aren't used by rustdoc" +} + +declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]); diff --git a/src/test/ui/useless-comment.rs b/src/test/ui/useless-comment.rs index f19c97e0102..d13db2f8f78 100644 --- a/src/test/ui/useless-comment.rs +++ b/src/test/ui/useless-comment.rs @@ -6,7 +6,7 @@ macro_rules! mac { () => {} } -/// foo //FIXME ERROR unused doc comment +/// foo //~ ERROR yep, it's unused mac!(); fn foo() { @@ -29,7 +29,7 @@ fn foo() { #[doc = "bar"] //~ ERROR unused doc comment 3; - /// bar //FIXME ERROR unused doc comment + /// bar //~ ERROR yep, it's unused mac!(); let x = /** comment */ 47; //~ ERROR unused doc comment diff --git a/src/test/ui/useless-comment.stderr b/src/test/ui/useless-comment.stderr index beb2a09f10e..76b37cfec71 100644 --- a/src/test/ui/useless-comment.stderr +++ b/src/test/ui/useless-comment.stderr @@ -1,10 +1,8 @@ -error: unused doc comment - --> $DIR/useless-comment.rs:13:5 +error: yep, it's unused + --> $DIR/useless-comment.rs:9:1 | -LL | /// a - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let x = 12; - | ----------- rustdoc does not generate documentation for statements +LL | /// foo + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here --> $DIR/useless-comment.rs:3:9 @@ -12,6 +10,20 @@ note: the lint level is defined here LL | #![deny(unused_doc_comments)] | ^^^^^^^^^^^^^^^^^^^ +error: yep, it's unused + --> $DIR/useless-comment.rs:32:5 + | +LL | /// bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused doc comment + --> $DIR/useless-comment.rs:13:5 + | +LL | /// a + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | let x = 12; + | ----------- rustdoc does not generate documentation for statements + error: unused doc comment --> $DIR/useless-comment.rs:16:5 | @@ -75,5 +87,5 @@ LL | | LL | | } | |_____- rustdoc does not generate documentation for expressions -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors From dcad07af8aa831344fd3be353c71379854637c21 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 15 Feb 2020 15:46:25 +0300 Subject: [PATCH 0194/1250] parser: `macro_rules` is a weak keyword --- src/librustc_expand/mbe/macro_check.rs | 4 ++-- src/librustc_expand/parse/tests.rs | 2 +- src/librustc_parse/parser/item.rs | 4 ++-- src/librustc_span/symbol.rs | 5 ++++- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs index 47865b2fb9f..10cdceefdf5 100644 --- a/src/librustc_expand/mbe/macro_check.rs +++ b/src/librustc_expand/mbe/macro_check.rs @@ -109,7 +109,7 @@ use crate::mbe::{KleeneToken, TokenTree}; use rustc_data_structures::fx::FxHashMap; use rustc_session::lint::builtin::META_VARIABLE_MISUSE; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::kw; use rustc_span::{symbol::Ident, MultiSpan, Span}; use syntax::ast::NodeId; use syntax::token::{DelimToken, Token, TokenKind}; @@ -392,7 +392,7 @@ fn check_nested_occurrences( NestedMacroState::Empty, &TokenTree::Token(Token { kind: TokenKind::Ident(name, false), .. }), ) => { - if name == sym::macro_rules { + if name == kw::MacroRules { state = NestedMacroState::MacroRules; } else if name == kw::Macro { state = NestedMacroState::Macro; diff --git a/src/librustc_expand/parse/tests.rs b/src/librustc_expand/parse/tests.rs index 3641f03cb30..4713c8dcd9a 100644 --- a/src/librustc_expand/parse/tests.rs +++ b/src/librustc_expand/parse/tests.rs @@ -65,7 +65,7 @@ fn string_to_tts_macro() { match tts { [TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }), TokenTree::Token(Token { kind: token::Not, .. }), TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }), TokenTree::Delimited(_, macro_delim, macro_tts)] - if name_macro_rules == &sym::macro_rules && name_zip.as_str() == "zip" => + if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => { let tts = ¯o_tts.trees().collect::>(); match &tts[..] { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 500aaaf43b9..d7b8d9778f0 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1343,14 +1343,14 @@ impl<'a> Parser<'a> { /// Is this unambiguously the start of a `macro_rules! foo` item defnition? fn is_macro_rules_item(&mut self) -> bool { - self.check_keyword(sym::macro_rules) + self.check_keyword(kw::MacroRules) && self.look_ahead(1, |t| *t == token::Not) && self.look_ahead(2, |t| t.is_ident()) } /// Parses a legacy `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { - self.expect_keyword(sym::macro_rules)?; // `macro_rules` + self.expect_keyword(kw::MacroRules)?; // `macro_rules` self.expect(&token::Not)?; // `!` let ident = self.parse_ident()?; diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 1cc4a277880..3c419334d42 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -97,6 +97,7 @@ symbols! { Auto: "auto", Catch: "catch", Default: "default", + MacroRules: "macro_rules", Raw: "raw", Union: "union", } @@ -429,7 +430,6 @@ symbols! { macro_lifetime_matcher, macro_literal_matcher, macro_reexport, - macro_rules, macros_in_extern, macro_use, macro_vis_matcher, @@ -1071,6 +1071,9 @@ pub mod sym { symbols!(); + // Used from a macro in `librustc_feature/accepted.rs` + pub use super::kw::MacroRules as macro_rules; + // Get the symbol for an integer. The first few non-negative integers each // have a static symbol and therefore are fast. pub fn integer + Copy + ToString>(n: N) -> Symbol { From 302b9e4b540cc352e75d3de6f803a99147107a50 Mon Sep 17 00:00:00 2001 From: Amos Onn Date: Sat, 15 Feb 2020 13:58:54 +0100 Subject: [PATCH 0195/1250] Improve #Safety in various methods in core::ptr s/for reads and writes/for both ... --- src/libcore/ptr/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 0ee50966f96..d465ab11c55 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -289,7 +289,7 @@ pub const fn slice_from_raw_parts_mut(data: *mut T, len: usize) -> *mut [T] { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * Both `x` and `y` must be [valid] for reads and writes. +/// * Both `x` and `y` must be [valid] for both reads and writes. /// /// * Both `x` and `y` must be properly aligned. /// @@ -355,7 +355,7 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * Both `x` and `y` must be [valid] for reads and writes of `count * +/// * Both `x` and `y` must be [valid] for both reads and writes of `count * /// size_of::()` bytes. /// /// * Both `x` and `y` must be properly aligned. From 351782d30aaa6e15204e17ecdd51ac1e712685cf Mon Sep 17 00:00:00 2001 From: Amos Onn Date: Fri, 31 Jan 2020 15:18:27 +0100 Subject: [PATCH 0196/1250] Improve #Safety of core::ptr::replace Added missing condition: `dst` must be readable --- src/libcore/ptr/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index d465ab11c55..7faede44020 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -471,7 +471,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `dst` must be [valid] for writes. +/// * `dst` must be [valid] for both reads and writes. /// /// * `dst` must be properly aligned. /// From 40ca16794456e9b1520bba6d887a176395f127f0 Mon Sep 17 00:00:00 2001 From: Amos Onn Date: Fri, 31 Jan 2020 15:22:51 +0100 Subject: [PATCH 0197/1250] Improve #Safety in various methods in core::ptr For all methods which read a value of type T, `read`, `read_unaligned`, `read_volatile` and `replace`, added missing constraint: The value they point to must be properly initialized --- src/libcore/ptr/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 7faede44020..7fb2d4f0399 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -475,6 +475,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) { /// /// * `dst` must be properly aligned. /// +/// * `dst` must point to a properly initialized value of type `T`. +/// /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. /// /// [valid]: ../ptr/index.html#safety @@ -514,6 +516,8 @@ pub unsafe fn replace(dst: *mut T, mut src: T) -> T { /// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the /// case. /// +/// * `src` must point to a properly initialized value of type `T`. +/// /// Note that even if `T` has size `0`, the pointer must be non-NULL and properly aligned. /// /// # Examples @@ -628,6 +632,8 @@ pub unsafe fn read(src: *const T) -> T { /// /// * `src` must be [valid] for reads. /// +/// * `src` must point to a properly initialized value of type `T`. +/// /// Like [`read`], `read_unaligned` creates a bitwise copy of `T`, regardless of /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. @@ -922,6 +928,8 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { /// /// * `src` must be properly aligned. /// +/// * `src` must point to a properly initialized value of type `T`. +/// /// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned /// value and the value at `*src` can [violate memory safety][read-ownership]. From c4a6f84b8065fb0aae240f820b007a22fbaf7a87 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 14:57:13 +0100 Subject: [PATCH 0198/1250] fix compile-fail --- src/test/compile-fail/consts/const-err3.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs index fc10824f0c0..efd51f40224 100644 --- a/src/test/compile-fail/consts/const-err3.rs +++ b/src/test/compile-fail/consts/const-err3.rs @@ -7,13 +7,13 @@ fn black_box(_: T) { fn main() { let b = 200u8 + 200u8 + 200u8; - //~^ ERROR const_err + //~^ ERROR overflow let c = 200u8 * 4; - //~^ ERROR const_err + //~^ ERROR overflow let d = 42u8 - (42u8 + 1); - //~^ ERROR const_err + //~^ ERROR overflow let _e = [5u8][1]; - //~^ ERROR const_err + //~^ ERROR panic black_box(b); black_box(c); black_box(d); From 0663f253757ab0d360f540e9d7bc7882db1dc8bd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 3 Feb 2020 20:12:42 +0000 Subject: [PATCH 0199/1250] Always qualify literals by type --- .../transform/check_consts/qualifs.rs | 25 ++++++------------- .../min-global-align/min_global_align.rs | 10 +++++--- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index e509e8267cc..215496e4d03 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -94,32 +94,23 @@ pub trait Qualif { } Operand::Constant(ref constant) => { - if constant.check_static_ptr(cx.tcx).is_some() { - // `mir_const_qualif` does return the qualifs in the final value of a `static`, - // so we could use value-based qualification here, but we shouldn't do this - // without a good reason. - // - // Note: this uses `constant.literal.ty` which is a reference or pointer to the - // type of the actual `static` item. - Self::in_any_value_of_ty(cx, constant.literal.ty) - } else if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val - { + // Check the qualifs of the value of `const` items. + if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val { assert!(promoted.is_none()); // 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.literal.ty) - } else { + if cx.tcx.trait_of_item(def_id).is_none() { let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id); - let qualif = Self::in_qualifs(&qualifs); + if !Self::in_qualifs(&qualifs) { + return false; + } // 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::in_any_value_of_ty(cx, constant.literal.ty) } - } else { - false } + // Otherwise use the qualifs of the type. + Self::in_any_value_of_ty(cx, constant.literal.ty) } } } diff --git a/src/test/run-make-fulldeps/min-global-align/min_global_align.rs b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs index ce86d202c62..d9851a2f794 100644 --- a/src/test/run-make-fulldeps/min-global-align/min_global_align.rs +++ b/src/test/run-make-fulldeps/min-global-align/min_global_align.rs @@ -1,5 +1,5 @@ #![feature(no_core, lang_items)] -#![crate_type="rlib"] +#![crate_type = "rlib"] #![no_core] pub static STATIC_BOOL: bool = true; @@ -9,7 +9,6 @@ pub static mut STATIC_MUT_BOOL: bool = true; const CONST_BOOL: bool = true; pub static CONST_BOOL_REF: &'static bool = &CONST_BOOL; - #[lang = "sized"] trait Sized {} @@ -19,10 +18,13 @@ trait Copy {} #[lang = "freeze"] trait Freeze {} +// No `UnsafeCell`, so everything is `Freeze`. +impl Freeze for T {} + #[lang = "sync"] trait Sync {} impl Sync for bool {} impl Sync for &'static bool {} -#[lang="drop_in_place"] -pub unsafe fn drop_in_place(_: *mut T) { } +#[lang = "drop_in_place"] +pub unsafe fn drop_in_place(_: *mut T) {} From f2980e71d936be7a39b9a472664363d93f2c7fd8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Feb 2020 14:21:50 +0000 Subject: [PATCH 0200/1250] Add fast path for is_freeze --- src/librustc/ty/util.rs | 40 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index db7b8d8cfd9..f27b66314f9 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -697,7 +697,7 @@ impl<'tcx> ty::TyS<'tcx> { /// strange rules like `>::Bar: Sized` that /// actually carry lifetime requirements. pub fn is_sized(&'tcx self, tcx_at: TyCtxtAt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool { - tcx_at.is_sized_raw(param_env.and(self)) + self.is_trivially_sized(tcx_at.tcx) || tcx_at.is_sized_raw(param_env.and(self)) } /// Checks whether values of this type `T` implement the `Freeze` @@ -713,7 +713,43 @@ impl<'tcx> ty::TyS<'tcx> { param_env: ty::ParamEnv<'tcx>, span: Span, ) -> bool { - tcx.at(span).is_freeze_raw(param_env.and(self)) + self.is_trivially_freeze() || tcx.at(span).is_freeze_raw(param_env.and(self)) + } + + /// Fast path helper for testing if a type is `Freeze`. + /// + /// Returning true means the type is known to be `Freeze`. Returning + /// `false` means nothing -- could be `Freeze`, might not be. + fn is_trivially_freeze(&self) -> bool { + match self.kind { + ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Bool + | ty::Char + | ty::Str + | ty::Never + | ty::Ref(..) + | ty::RawPtr(_) + | ty::FnDef(..) + | ty::Error + | ty::FnPtr(_) => true, + ty::Tuple(_) => self.tuple_fields().all(Self::is_trivially_freeze), + ty::Slice(elem_ty) | ty::Array(elem_ty, _) => elem_ty.is_trivially_freeze(), + ty::Adt(..) + | ty::Bound(..) + | ty::Closure(..) + | ty::Dynamic(..) + | ty::Foreign(_) + | ty::Generator(..) + | ty::GeneratorWitness(_) + | ty::Infer(_) + | ty::Opaque(..) + | ty::Param(_) + | ty::Placeholder(_) + | ty::Projection(_) + | ty::UnnormalizedProjection(_) => false, + } } /// If `ty.needs_drop(...)` returns `true`, then `ty` is definitely From 0c8c800f21e00c7db39084e6b8087706a816fba7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 15:42:13 +0100 Subject: [PATCH 0201/1250] Tighter type bounds for messages Co-Authored-By: Mazdak Farrokhzad --- src/librustc_mir/transform/const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 05e70ed217a..eec4bbc720d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -504,7 +504,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { &self, lint: &'static lint::Lint, source_info: SourceInfo, - message: &str, + message: &'static str, panic: AssertKind, ) -> Option<()> { let lint_root = self.lint_root(source_info)?; From cadf9efad123a62472cad45f22569747cc599256 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 15 Feb 2020 16:41:21 +0100 Subject: [PATCH 0202/1250] Clean up E0309 explanation --- src/librustc_error_codes/error_codes/E0309.md | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0309.md b/src/librustc_error_codes/error_codes/E0309.md index 73ce7407476..e719ee590ab 100644 --- a/src/librustc_error_codes/error_codes/E0309.md +++ b/src/librustc_error_codes/error_codes/E0309.md @@ -1,9 +1,7 @@ -The type definition contains some field whose type -requires an outlives annotation. Outlives annotations -(e.g., `T: 'a`) are used to guarantee that all the data in T is valid -for at least the lifetime `'a`. This scenario most commonly -arises when the type contains an associated type reference -like `>::Output`, as shown in this example: +A parameter type is missing an explicit lifetime bound and may not live long +enough. + +Erroneous code example: ```compile_fail,E0309 // This won't compile because the applicable impl of @@ -25,9 +23,15 @@ where } ``` -Here, the where clause `T: 'a` that appears on the impl is not known to be -satisfied on the struct. To make this example compile, you have to add -a where-clause like `T: 'a` to the struct definition: +The type definition contains some field whose type requires an outlives +annotation. Outlives annotations (e.g., `T: 'a`) are used to guarantee that all +the data in T is valid for at least the lifetime `'a`. This scenario most +commonly arises when the type contains an associated type reference like +`>::Output`, as shown in the previous code. + +There, the where clause `T: 'a` that appears on the impl is not known to be +satisfied on the struct. To make this example compile, you have to add a +where-clause like `T: 'a` to the struct definition: ``` struct Foo<'a, T> From a7db5051d14994474c641328333884aeba70ca25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 9 Feb 2020 15:08:31 +0100 Subject: [PATCH 0203/1250] Treat NodeIs as pure values for incremental compilation --- src/librustc/ich/hcx.rs | 22 +++------------------- src/librustc/ty/query/on_disk_cache.rs | 25 +------------------------ src/libsyntax/node_id.rs | 2 ++ 3 files changed, 6 insertions(+), 43 deletions(-) diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 76e4b5f01b7..e0e8470fe47 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -219,28 +219,12 @@ impl<'a> ToStableHashKey> for hir::HirId { } } -impl<'a> HashStable> for ast::NodeId { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - match hcx.node_id_hashing_mode { - NodeIdHashingMode::Ignore => { - // Don't do anything. - } - NodeIdHashingMode::HashDefPath => { - hcx.definitions.node_to_hir_id(*self).hash_stable(hcx, hasher); - } - } - } -} - impl<'a> ToStableHashKey> for ast::NodeId { - type KeyType = (DefPathHash, hir::ItemLocalId); + type KeyType = Self; #[inline] - fn to_stable_hash_key( - &self, - hcx: &StableHashingContext<'a>, - ) -> (DefPathHash, hir::ItemLocalId) { - hcx.definitions.node_to_hir_id(*self).to_stable_hash_key(hcx) + fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> Self { + *self } } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 01f684dc65c..45d95e97a9c 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -22,7 +22,7 @@ use rustc_span::hygiene::{ExpnId, SyntaxContext}; use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::{BytePos, SourceFile, Span, DUMMY_SP}; use std::mem; -use syntax::ast::{Ident, NodeId}; +use syntax::ast::Ident; const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE; @@ -680,16 +680,6 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } -// `NodeId`s are not stable across compilation sessions, so we store them in their -// `HirId` representation. This allows use to map them to the current `NodeId`. -impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { - #[inline] - fn specialized_decode(&mut self) -> Result { - let hir_id = hir::HirId::decode(self)?; - Ok(self.tcx().hir().hir_to_node_id(hir_id)) - } -} - impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { Fingerprint::decode_opaque(&mut self.opaque) @@ -928,19 +918,6 @@ where } } -// `NodeId`s are not stable across compilation sessions, so we store them in their -// `HirId` representation. This allows use to map them to the current `NodeId`. -impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> -where - E: 'a + TyEncoder, -{ - #[inline] - fn specialized_encode(&mut self, node_id: &NodeId) -> Result<(), Self::Error> { - let hir_id = self.tcx.hir().node_to_hir_id(*node_id); - hir_id.encode(self) - } -} - impl<'a, 'tcx> SpecializedEncoder for CacheEncoder<'a, 'tcx, opaque::Encoder> { fn specialized_encode(&mut self, f: &Fingerprint) -> Result<(), Self::Error> { f.encode_opaque(&mut self.encoder) diff --git a/src/libsyntax/node_id.rs b/src/libsyntax/node_id.rs index 58d2334a7b1..430d8f30421 100644 --- a/src/libsyntax/node_id.rs +++ b/src/libsyntax/node_id.rs @@ -1,8 +1,10 @@ +use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; use rustc_span::ExpnId; use std::fmt; rustc_index::newtype_index! { + #[derive(HashStable_Generic)] pub struct NodeId { ENCODABLE = custom DEBUG_FORMAT = "NodeId({})" From 2fd15442f2f1c798718242eaa9817531a53c2134 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 13 Feb 2020 18:03:38 +0100 Subject: [PATCH 0204/1250] ast: move Generics into AssocItemKinds --- src/librustc_ast_lowering/item.rs | 45 ++--- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_ast_passes/ast_validation.rs | 6 +- src/librustc_ast_passes/feature_gate.rs | 6 +- src/librustc_ast_pretty/pprust.rs | 8 +- .../deriving/generic/mod.rs | 5 +- src/librustc_expand/placeholders.rs | 3 - src/librustc_interface/util.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_parse/parser/item.rs | 16 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/def_collector.rs | 6 +- src/librustc_resolve/late.rs | 180 +++++++++--------- src/librustc_save_analysis/dump_visitor.rs | 14 +- src/libsyntax/ast.rs | 5 +- src/libsyntax/mut_visit.rs | 9 +- src/libsyntax/visit.rs | 7 +- 17 files changed, 155 insertions(+), 163 deletions(-) diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 426659fd924..073f0c6bc47 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -760,31 +760,25 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match i.kind { AssocItemKind::Const(ref ty, ref default) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); - ( - generics, - hir::TraitItemKind::Const( - ty, - default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))), - ), - ) + let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); + (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) } - AssocItemKind::Fn(ref sig, None) => { + AssocItemKind::Fn(ref sig, ref generics, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = - self.lower_method_sig(&i.generics, sig, trait_item_def_id, false, None); + self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - AssocItemKind::Fn(ref sig, Some(ref body)) => { + AssocItemKind::Fn(ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = - self.lower_method_sig(&i.generics, sig, trait_item_def_id, false, None); + self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - AssocItemKind::TyAlias(ref bounds, ref default) => { + AssocItemKind::TyAlias(ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( self.lower_param_bounds(bounds, ImplTraitContext::disallowed()), ty, @@ -806,10 +800,10 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { - let (kind, has_default) = match i.kind { - AssocItemKind::Const(_, ref default) => (hir::AssocItemKind::Const, default.is_some()), - AssocItemKind::TyAlias(_, ref default) => (hir::AssocItemKind::Type, default.is_some()), - AssocItemKind::Fn(ref sig, ref default) => { + let (kind, has_default) = match &i.kind { + AssocItemKind::Const(_, default) => (hir::AssocItemKind::Const, default.is_some()), + AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()), + AssocItemKind::Fn(sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) } AssocItemKind::Macro(..) => unimplemented!(), @@ -833,21 +827,20 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match i.kind { AssocItemKind::Const(ref ty, ref expr) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); ( - generics, + hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), ) } - AssocItemKind::Fn(ref sig, ref body) => { + AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.current_item = Some(i.span); let asyncness = sig.header.asyncness; let body_id = self.lower_maybe_async_body(i.span, &sig.decl, asyncness, body.as_deref()); let impl_trait_return_allow = !self.is_in_trait_impl; let (generics, sig) = self.lower_method_sig( - &i.generics, + generics, sig, impl_item_def_id, impl_trait_return_allow, @@ -856,8 +849,8 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - AssocItemKind::TyAlias(_, ref ty) => { - let generics = self.lower_generics(&i.generics, ImplTraitContext::disallowed()); + AssocItemKind::TyAlias(ref generics, _, ref ty) => { + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = match ty { None => { let ty = self.arena.alloc(self.ty(i.span, hir::TyKind::Err)); @@ -902,13 +895,13 @@ impl<'hir> LoweringContext<'_, 'hir> { defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { AssocItemKind::Const(..) => hir::AssocItemKind::Const, - AssocItemKind::TyAlias(_, ty) => { + AssocItemKind::TyAlias(_, _, ty) => { match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, } } - AssocItemKind::Fn(sig, _) => { + AssocItemKind::Fn(sig, _, _) => { hir::AssocItemKind::Method { has_self: sig.decl.has_self() } } AssocItemKind::Macro(..) => unimplemented!(), diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 99de4b88fd3..56d789b7a6a 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -490,7 +490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lctx.allocate_hir_id_counter(item.id); let owner = match (&item.kind, ctxt) { // Ignore patterns in trait methods without bodies. - (AssocItemKind::Fn(_, None), AssocCtxt::Trait) => None, + (AssocItemKind::Fn(_, _, None), AssocCtxt::Trait) => None, _ => Some(item.id), }; self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt)); diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 2f0495b8b5a..206cdefecc9 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -1154,10 +1154,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { AssocItemKind::Const(_, body) => { self.check_impl_item_provided(item.span, body, "constant", " = ;"); } - AssocItemKind::Fn(_, body) => { + AssocItemKind::Fn(_, _, body) => { self.check_impl_item_provided(item.span, body, "function", " { }"); } - AssocItemKind::TyAlias(bounds, body) => { + AssocItemKind::TyAlias(_, bounds, body) => { self.check_impl_item_provided(item.span, body, "type", " = ;"); self.check_impl_assoc_type_no_bounds(bounds); } @@ -1167,7 +1167,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Trait || self.in_trait_impl { self.invalid_visibility(&item.vis, None); - if let AssocItemKind::Fn(sig, _) = &item.kind { + if let AssocItemKind::Fn(sig, _, _) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(item.span, sig.header.asyncness); } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 0b21de4d78b..32c91f4a634 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -548,12 +548,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } match i.kind { - ast::AssocItemKind::Fn(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _, _) => { if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); } } - ast::AssocItemKind::TyAlias(_, ref ty) => { + ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( &self, @@ -565,7 +565,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { if let Some(ty) = ty { self.check_impl_trait(ty); } - self.check_gat(&i.generics, i.span); + self.check_gat(generics, i.span); } _ => {} } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 75938470b6f..0fcda7f763e 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1473,12 +1473,12 @@ impl<'a> State<'a> { ast::AssocItemKind::Const(ty, expr) => { self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); } - ast::AssocItemKind::Fn(sig, body) => { + ast::AssocItemKind::Fn(sig, generics, body) => { let body = body.as_deref(); - self.print_fn_full(sig, item.ident, &item.generics, &item.vis, body, &item.attrs); + self.print_fn_full(sig, item.ident, generics, &item.vis, body, &item.attrs); } - ast::AssocItemKind::TyAlias(bounds, ty) => { - self.print_associated_type(item.ident, &item.generics, bounds, ty.as_deref()); + ast::AssocItemKind::TyAlias(generics, bounds, ty) => { + self.print_associated_type(item.ident, generics, bounds, ty.as_deref()); } ast::AssocItemKind::Macro(mac) => { self.print_mac(mac); diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 5cf233e222e..2e4cbd708a9 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -544,8 +544,8 @@ impl<'a> TraitDef<'a> { vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, attrs: Vec::new(), - generics: Generics::default(), kind: ast::AssocItemKind::TyAlias( + Generics::default(), Vec::new(), Some(type_def.to_ty(cx, self.span, type_ident, generics)), ), @@ -973,12 +973,11 @@ impl<'a> MethodDef<'a> { P(ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), - generics: fn_generics, span: trait_.span, vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::AssocItemKind::Fn(sig, Some(body_block)), + kind: ast::AssocItemKind::Fn(sig, fn_generics, Some(body_block)), tokens: None, }) } diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs index 6bcb8f45f00..c96b394c7b5 100644 --- a/src/librustc_expand/placeholders.rs +++ b/src/librustc_expand/placeholders.rs @@ -25,7 +25,6 @@ pub fn placeholder( let ident = ast::Ident::invalid(); let attrs = Vec::new(); - let generics = ast::Generics::default(); let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited)); let span = DUMMY_SP; let expr_placeholder = || { @@ -57,7 +56,6 @@ pub fn placeholder( ident, vis, attrs, - generics, kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, @@ -68,7 +66,6 @@ pub fn placeholder( ident, vis, attrs, - generics, kind: ast::AssocItemKind::Macro(mac_placeholder()), defaultness: ast::Defaultness::Final, tokens: None, diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 659323d1c25..df50fc5d3ed 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -686,7 +686,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: P) -> SmallVec<[P; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(ref sig, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 93fca43d67c..207defa96a3 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -640,7 +640,7 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::AssocItemKind::Fn(ref sig, _) => { + ast::AssocItemKind::Fn(ref sig, _, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 500aaaf43b9..96b3cf79720 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -665,11 +665,11 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); - let (ident, kind, generics) = if self.eat_keyword(kw::Type) { + let (ident, kind) = if self.eat_keyword(kw::Type) { self.parse_assoc_ty()? } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; - (ident, AssocItemKind::Fn(sig, body), generics) + (ident, AssocItemKind::Fn(sig, generics, body)) } else if self.check_keyword(kw::Const) { self.parse_assoc_const()? } else if self.isnt_macro_invocation() { @@ -677,7 +677,7 @@ impl<'a> Parser<'a> { } else if self.token.is_path_start() { let mac = self.parse_item_macro(&vis)?; *at_end = true; - (Ident::invalid(), AssocItemKind::Macro(mac), Generics::default()) + (Ident::invalid(), AssocItemKind::Macro(mac)) } else { self.recover_attrs_no_item(&attrs)?; self.unexpected()? @@ -685,26 +685,26 @@ impl<'a> Parser<'a> { let span = lo.to(self.prev_span); let id = DUMMY_NODE_ID; - Ok(AssocItem { id, span, ident, attrs, vis, defaultness, generics, kind, tokens: None }) + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) } /// This parses the grammar: /// /// AssocConst = "const" Ident ":" Ty "=" Expr ";" - fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { self.expect_keyword(kw::Const)?; let ident = self.parse_ident()?; self.expect(&token::Colon)?; let ty = self.parse_ty()?; let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - Ok((ident, AssocItemKind::Const(ty, expr), Generics::default())) + Ok((ident, AssocItemKind::Const(ty, expr))) } /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind, Generics)> { + fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -716,7 +716,7 @@ impl<'a> Parser<'a> { let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; - Ok((ident, AssocItemKind::TyAlias(bounds, default), generics)) + Ok((ident, AssocItemKind::TyAlias(generics, bounds, default))) } /// Parses a `UseTree`. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index d6ea737385c..280a7a8fdba 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1252,7 +1252,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - AssocItemKind::Fn(ref sig, _) => { + AssocItemKind::Fn(ref sig, _, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index fe80dec513c..256b5ff4b9a 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -215,13 +215,15 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_data = match &i.kind { - AssocItemKind::Fn(FnSig { header, decl }, body) if header.asyncness.is_async() => { + AssocItemKind::Fn(FnSig { header, decl }, generics, body) + if header.asyncness.is_async() => + { return self.visit_async_fn( i.id, i.ident.name, i.span, header, - &i.generics, + generics, decl, body.as_deref(), ); diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bcf558d1563..0e4e9c15286 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -826,41 +826,33 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds); - for trait_item in trait_items { + let walk_assoc_item = |this: &mut Self, generics, item| { + this.with_generic_param_rib(generics, AssocItemRibKind, |this| { + visit::walk_assoc_item(this, item, AssocCtxt::Trait) + }); + }; + + for item in trait_items { this.with_trait_items(trait_items, |this| { - this.with_generic_param_rib( - &trait_item.generics, - AssocItemRibKind, - |this| { - match trait_item.kind { - AssocItemKind::Const(ref ty, ref default) => { - this.visit_ty(ty); - - // Only impose the restrictions of - // ConstRibKind for an actual constant - // expression in a provided default. - if let Some(ref expr) = *default { - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); - } - } - AssocItemKind::Fn(_, _) => visit::walk_assoc_item( - this, - trait_item, - AssocCtxt::Trait, - ), - AssocItemKind::TyAlias(..) => visit::walk_assoc_item( - this, - trait_item, - AssocCtxt::Trait, - ), - AssocItemKind::Macro(_) => { - panic!("unexpanded macro in resolve!") - } - }; - }, - ); + match &item.kind { + AssocItemKind::Const(ty, default) => { + this.visit_ty(ty); + // Only impose the restrictions of `ConstRibKind` for an + // actual constant expression in a provided default. + if let Some(expr) = default { + this.with_constant_rib(|this| this.visit_expr(expr)); + } + } + AssocItemKind::Fn(_, generics, _) => { + walk_assoc_item(this, generics, item); + } + AssocItemKind::TyAlias(generics, _, _) => { + walk_assoc_item(this, generics, item); + } + AssocItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") + } + }; }); } }); @@ -1021,7 +1013,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_items .iter() .filter_map(|item| match &item.kind { - AssocItemKind::TyAlias(bounds, _) if bounds.len() == 0 => Some(item.ident), + AssocItemKind::TyAlias(_, bounds, _) if bounds.len() == 0 => Some(item.ident), _ => None, }) .collect(), @@ -1113,66 +1105,74 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_current_self_type(self_type, |this| { this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| { debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); - for impl_item in impl_items { - // We also need a new scope for the impl item type parameters. - this.with_generic_param_rib(&impl_item.generics, - AssocItemRibKind, - |this| { - use crate::ResolutionError::*; - match impl_item.kind { - AssocItemKind::Const(..) => { - debug!( - "resolve_implementation AssocItemKind::Const", - ); - // If this is a trait impl, ensure the const - // exists in trait - this.check_trait_item( - impl_item.ident, - ValueNS, - impl_item.span, - |n, s| ConstNotMemberOfTrait(n, s), - ); - - this.with_constant_rib(|this| { + for item in impl_items { + use crate::ResolutionError::*; + match &item.kind { + AssocItemKind::Const(..) => { + debug!("resolve_implementation AssocItemKind::Const",); + // If this is a trait impl, ensure the const + // exists in trait + this.check_trait_item( + item.ident, + ValueNS, + item.span, + |n, s| ConstNotMemberOfTrait(n, s), + ); + + this.with_constant_rib(|this| { + visit::walk_assoc_item(this, item, AssocCtxt::Impl) + }); + } + AssocItemKind::Fn(_, generics, _) => { + // We also need a new scope for the impl item type parameters. + this.with_generic_param_rib( + generics, + AssocItemRibKind, + |this| { + // If this is a trait impl, ensure the method + // exists in trait + this.check_trait_item( + item.ident, + ValueNS, + item.span, + |n, s| MethodNotMemberOfTrait(n, s), + ); + visit::walk_assoc_item( this, - impl_item, + item, AssocCtxt::Impl, ) - }); - } - AssocItemKind::Fn(..) => { - // If this is a trait impl, ensure the method - // exists in trait - this.check_trait_item(impl_item.ident, - ValueNS, - impl_item.span, - |n, s| MethodNotMemberOfTrait(n, s)); - - visit::walk_assoc_item( - this, - impl_item, - AssocCtxt::Impl, - ) - } - AssocItemKind::TyAlias(_, _) => { - // If this is a trait impl, ensure the type - // exists in trait - this.check_trait_item(impl_item.ident, - TypeNS, - impl_item.span, - |n, s| TypeNotMemberOfTrait(n, s)); - - visit::walk_assoc_item( - this, - impl_item, - AssocCtxt::Impl, - ) - } - AssocItemKind::Macro(_) => - panic!("unexpanded macro in resolve!"), + }, + ); + } + AssocItemKind::TyAlias(generics, _, _) => { + // We also need a new scope for the impl item type parameters. + this.with_generic_param_rib( + generics, + AssocItemRibKind, + |this| { + // If this is a trait impl, ensure the type + // exists in trait + this.check_trait_item( + item.ident, + TypeNS, + item.span, + |n, s| TypeNotMemberOfTrait(n, s), + ); + + visit::walk_assoc_item( + this, + item, + AssocCtxt::Impl, + ) + }, + ); + } + AssocItemKind::Macro(_) => { + panic!("unexpanded macro in resolve!") } - }); + } } }); }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 01e3e3f3685..561a4a83d28 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1015,18 +1015,18 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), trait_item.id, trait_item.ident, - &trait_item.generics, + generics, respan(vis_span, ast::VisibilityKind::Public), trait_item.span, ); } - ast::AssocItemKind::TyAlias(ref bounds, ref default_ty) => { + ast::AssocItemKind::TyAlias(_, ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!( @@ -1085,19 +1085,19 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref body) => { + ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { self.process_method( sig, body.as_deref(), impl_item.id, impl_item.ident, - &impl_item.generics, + generics, impl_item.vis.clone(), impl_item.span, ); } - ast::AssocItemKind::TyAlias(_, None) => {} - ast::AssocItemKind::TyAlias(_, Some(ref ty)) => { + ast::AssocItemKind::TyAlias(_, _, None) => {} + ast::AssocItemKind::TyAlias(_, _, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 72430fa9c17..7f6e405fec6 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1616,7 +1616,6 @@ pub struct AssocItem { pub ident: Ident, pub defaultness: Defaultness, - pub generics: Generics, pub kind: AssocItemKind, /// See `Item::tokens` for what this is. pub tokens: Option, @@ -1636,10 +1635,10 @@ pub enum AssocItemKind { Const(P, Option>), /// An associated function. - Fn(FnSig, Option>), + Fn(FnSig, Generics, Option>), /// An associated type. - TyAlias(GenericBounds, Option>), + TyAlias(Generics, GenericBounds, Option>), /// A macro expanding to an associated item. Macro(Mac), diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index e0180d45193..f3857b3a414 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -951,23 +951,24 @@ pub fn noop_flat_map_assoc_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let AssocItem { id, ident, vis, defaultness: _, attrs, generics, kind, span, tokens: _ } = + let AssocItem { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut(); visitor.visit_id(id); visitor.visit_ident(ident); visitor.visit_vis(vis); visit_attrs(attrs, visitor); - visitor.visit_generics(generics); match kind { AssocItemKind::Const(ty, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Fn(sig, body) => { + AssocItemKind::Fn(sig, generics, body) => { + visitor.visit_generics(generics); visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - AssocItemKind::TyAlias(bounds, ty) => { + AssocItemKind::TyAlias(generics, bounds, ty) => { + visitor.visit_generics(generics); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 73e731397c3..edcfd7f4e78 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -625,17 +625,18 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_vis(&item.vis); visitor.visit_ident(item.ident); walk_list!(visitor, visit_attribute, &item.attrs); - visitor.visit_generics(&item.generics); match item.kind { AssocItemKind::Const(ref ty, ref expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(ref sig, ref body) => { + AssocItemKind::Fn(ref sig, ref generics, ref body) => { + visitor.visit_generics(generics); let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id); } - AssocItemKind::TyAlias(ref bounds, ref ty) => { + AssocItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } From f06df1629e1144be6a217754303a6585699e0728 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 13 Feb 2020 18:05:40 +0100 Subject: [PATCH 0205/1250] ast: colocate AssocItem with ForeignItem --- src/libsyntax/ast.rs | 78 ++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 7f6e405fec6..2eab688fd9d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -1605,45 +1605,6 @@ pub struct FnSig { pub decl: P, } -/// Represents associated items. -/// These include items in `impl` and `trait` definitions. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AssocItem { - pub attrs: Vec, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, - pub ident: Ident, - - pub defaultness: Defaultness, - pub kind: AssocItemKind, - /// See `Item::tokens` for what this is. - pub tokens: Option, -} - -/// Represents various kinds of content within an `impl`. -/// -/// The term "provided" in the variants below refers to the item having a default -/// definition / body. Meanwhile, a "required" item lacks a definition / body. -/// In an implementation, all items must be provided. -/// The `Option`s below denote the bodies, where `Some(_)` -/// means "provided" and conversely `None` means "required". -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum AssocItemKind { - /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. - /// If `def` is parsed, then the associated constant is provided, and otherwise required. - Const(P, Option>), - - /// An associated function. - Fn(FnSig, Generics, Option>), - - /// An associated type. - TyAlias(Generics, GenericBounds, Option>), - - /// A macro expanding to an associated item. - Macro(Mac), -} - #[derive( Clone, Copy, @@ -2664,3 +2625,42 @@ impl ForeignItemKind { } } } + +/// Represents associated items. +/// These include items in `impl` and `trait` definitions. +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub struct AssocItem { + pub attrs: Vec, + pub id: NodeId, + pub span: Span, + pub vis: Visibility, + pub ident: Ident, + + pub defaultness: Defaultness, + pub kind: AssocItemKind, + /// See `Item::tokens` for what this is. + pub tokens: Option, +} + +/// Represents various kinds of content within an `impl`. +/// +/// The term "provided" in the variants below refers to the item having a default +/// definition / body. Meanwhile, a "required" item lacks a definition / body. +/// In an implementation, all items must be provided. +/// The `Option`s below denote the bodies, where `Some(_)` +/// means "provided" and conversely `None` means "required". +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum AssocItemKind { + /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the associated constant is provided, and otherwise required. + Const(P, Option>), + + /// An associated function. + Fn(FnSig, Generics, Option>), + + /// An associated type. + TyAlias(Generics, GenericBounds, Option>), + + /// A macro expanding to an associated item. + Macro(Mac), +} From e2ae717265c4597d605cf5981a6e557516ccb0c8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 13 Feb 2020 18:15:58 +0100 Subject: [PATCH 0206/1250] ast: tweak comments of Foreign/AssocItemKind --- src/libsyntax/ast.rs | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 2eab688fd9d..af0195ffc61 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2605,13 +2605,13 @@ pub type ForeignItem = Item; /// An item within an `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { - /// A foreign function. - Fn(FnSig, Generics, Option>), - /// A foreign static item (`static ext: u8`). + /// A static item (`static FOO: u8`). Static(P, Mutability), - /// A foreign type. + /// A function. + Fn(FnSig, Generics, Option>), + /// A type. Ty, - /// A macro invocation. + /// A macro expanding to an item. Macro(Mac), } @@ -2651,16 +2651,13 @@ pub struct AssocItem { /// means "provided" and conversely `None` means "required". #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum AssocItemKind { - /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. - /// If `def` is parsed, then the associated constant is provided, and otherwise required. + /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the constant is provided, and otherwise required. Const(P, Option>), - - /// An associated function. + /// A function. Fn(FnSig, Generics, Option>), - - /// An associated type. + /// A type. TyAlias(Generics, GenericBounds, Option>), - - /// A macro expanding to an associated item. + /// A macro expanding to an item. Macro(Mac), } From 95dc9b9a73353a786e3c934c5074fb793ff7a735 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 14 Feb 2020 12:55:42 +0100 Subject: [PATCH 0207/1250] ast: normalize `ForeignItemKind::Ty` & `AssocItemKind::TyAlias`. --- src/librustc_ast_lowering/item.rs | 2 +- src/librustc_ast_passes/ast_validation.rs | 63 ++++++++++++++++-- src/librustc_ast_passes/feature_gate.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 18 ++--- src/librustc_parse/parser/item.rs | 12 ++-- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/late.rs | 5 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/mut_visit.rs | 6 +- src/libsyntax/visit.rs | 6 +- .../ui/parser/foreign-ty-semantic-fail.rs | 18 +++++ .../ui/parser/foreign-ty-semantic-fail.stderr | 65 +++++++++++++++++++ .../ui/parser/foreign-ty-syntactic-pass.rs | 12 ++++ .../impl-item-type-no-body-semantic-fail.rs | 4 +- ...mpl-item-type-no-body-semantic-fail.stderr | 4 +- 18 files changed, 192 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/parser/foreign-ty-semantic-fail.rs create mode 100644 src/test/ui/parser/foreign-ty-semantic-fail.stderr create mode 100644 src/test/ui/parser/foreign-ty-syntactic-pass.rs diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 073f0c6bc47..6c4026408ed 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -682,7 +682,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } - ForeignItemKind::Ty => hir::ForeignItemKind::Type, + ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, vis: self.lower_visibility(&i.vis, None), diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 206cdefecc9..c539f98aecf 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -22,6 +22,9 @@ use syntax::expand::is_proc_macro_attr; use syntax::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use syntax::walk_list; +const MORE_EXTERN: &str = + "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html"; + /// Is `self` allowed semantically as the first parameter in an `FnDecl`? enum SelfSemantic { Yes, @@ -423,14 +426,59 @@ impl<'a> AstValidator<'a> { } } - fn check_impl_assoc_type_no_bounds(&self, bounds: &[GenericBound]) { + fn check_type_no_bounds(&self, bounds: &[GenericBound], ctx: &str) { let span = match bounds { [] => return, [b0] => b0.span(), [b0, .., bl] => b0.span().to(bl.span()), }; self.err_handler() - .struct_span_err(span, "bounds on associated `type`s in `impl`s have no effect") + .struct_span_err(span, &format!("bounds on `type`s in {} have no effect", ctx)) + .emit(); + } + + fn check_foreign_ty_genericless(&self, generics: &Generics) { + let cannot_have = |span, descr, remove_descr| { + self.err_handler() + .struct_span_err( + span, + &format!("`type`s inside `extern` blocks cannot have {}", descr), + ) + .span_suggestion( + span, + &format!("remove the {}", remove_descr), + String::new(), + Applicability::MaybeIncorrect, + ) + .span_label(self.current_extern_span(), "`extern` block begins here") + .note(MORE_EXTERN) + .emit(); + }; + + if !generics.params.is_empty() { + cannot_have(generics.span, "generic parameters", "generic parameters"); + } + + if !generics.where_clause.predicates.is_empty() { + cannot_have(generics.where_clause.span, "`where` clauses", "`where` clause"); + } + } + + fn check_foreign_ty_bodyless(&self, ident: Ident, body: Option<&Ty>) { + let body = match body { + None => return, + Some(body) => body, + }; + self.err_handler() + .struct_span_err(ident.span, "incorrect `type` inside `extern` block") + .span_label(ident.span, "cannot have a body") + .span_label(body.span, "the invalid body") + .span_label( + self.current_extern_span(), + "`extern` blocks define existing foreign types and types \ + inside of them cannot have a body", + ) + .note(MORE_EXTERN) .emit(); } @@ -458,7 +506,7 @@ impl<'a> AstValidator<'a> { "`extern` blocks define existing foreign functions and functions \ inside of them cannot have a body", ) - .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html") + .note(MORE_EXTERN) .emit(); } @@ -912,7 +960,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); } - ForeignItemKind::Static(..) | ForeignItemKind::Ty | ForeignItemKind::Macro(..) => {} + ForeignItemKind::TyAlias(generics, bounds, body) => { + self.check_foreign_ty_bodyless(fi.ident, body.as_deref()); + self.check_type_no_bounds(bounds, "`extern` blocks"); + self.check_foreign_ty_genericless(generics); + } + ForeignItemKind::Static(..) | ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, fi) @@ -1159,7 +1212,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } AssocItemKind::TyAlias(_, bounds, body) => { self.check_impl_item_provided(item.span, body, "type", " = ;"); - self.check_impl_assoc_type_no_bounds(bounds); + self.check_type_no_bounds(bounds, "`impl`s"); } _ => {} } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 32c91f4a634..c543f7095b9 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -397,7 +397,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } ast::ForeignItemKind::Macro(..) => {} diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 0fcda7f763e..b0e1b5d4f42 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1019,13 +1019,13 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(item.span.lo()); self.print_outer_attributes(&item.attrs); - match item.kind { - ast::ForeignItemKind::Fn(ref sig, ref gen, ref body) => { + match &item.kind { + ast::ForeignItemKind::Fn(sig, gen, body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); } - ast::ForeignItemKind::Static(ref t, m) => { + ast::ForeignItemKind::Static(t, m) => { self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mut { + if *m == ast::Mutability::Mut { self.word_space("mut"); } self.print_ident(item.ident); @@ -1035,14 +1035,10 @@ impl<'a> State<'a> { self.end(); // end the head-ibox self.end(); // end the outer cbox } - ast::ForeignItemKind::Ty => { - self.head(visibility_qualified(&item.vis, "type")); - self.print_ident(item.ident); - self.s.word(";"); - self.end(); // end the head-ibox - self.end(); // end the outer cbox + ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { + self.print_associated_type(item.ident, generics, bounds, ty.as_deref()); } - ast::ForeignItemKind::Macro(ref m) => { + ast::ForeignItemKind::Macro(m) => { self.print_mac(m); if m.args.need_semicolon() { self.s.word(";"); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 96b3cf79720..4a5b4ff8e04 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -876,7 +876,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - let (ident, kind) = if self.check_keyword(kw::Type) { + let (ident, kind) = if self.eat_keyword(kw::Type) { // FOREIGN TYPE ITEM self.parse_item_foreign_type()? } else if self.check_fn_front_matter() { @@ -925,10 +925,12 @@ impl<'a> Parser<'a> { /// Parses a type from a foreign module. fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { - self.expect_keyword(kw::Type)?; - let ident = self.parse_ident()?; - self.expect_semi()?; - Ok((ident, ForeignItemKind::Ty)) + let (ident, kind) = self.parse_assoc_ty()?; + let kind = match kind { + AssocItemKind::TyAlias(g, b, d) => ForeignItemKind::TyAlias(g, b, d), + _ => unreachable!(), + }; + Ok((ident, kind)) } fn is_static_global(&mut self) -> bool { diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 280a7a8fdba..f5e64443dda 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -829,7 +829,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Static(..) => { (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Ty => { + ForeignItemKind::TyAlias(..) => { (Res::Def(DefKind::ForeignTy, self.r.definitions.local_def_id(item.id)), TypeNS) } ForeignItemKind::Macro(_) => unreachable!(), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 0e4e9c15286..1a1a9b1076e 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -437,7 +437,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { match foreign_item.kind { - ForeignItemKind::Fn(_, ref generics, _) => { + ForeignItemKind::Fn(_, ref generics, _) + | ForeignItemKind::TyAlias(ref generics, ..) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_foreign_item(this, foreign_item); }); @@ -447,7 +448,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Ty | ForeignItemKind::Macro(..) => { + ForeignItemKind::Macro(..) => { visit::walk_foreign_item(self, foreign_item); } } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 561a4a83d28..5668be40eef 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1540,7 +1540,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(ty); } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 401e1722751..e983802ee11 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -173,7 +173,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { })) } // FIXME(plietar): needs a new DefKind in rls-data - ast::ForeignItemKind::Ty => None, + ast::ForeignItemKind::TyAlias(..) => None, ast::ForeignItemKind::Macro(..) => None, } } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index d3c4d6d5723..bd7bd9bc616 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -773,7 +773,7 @@ impl Sig for ast::ForeignItem { Ok(extend_sig(ty_sig, text, defs, vec![])) } - ast::ForeignItemKind::Ty => { + ast::ForeignItemKind::TyAlias(..) => { let mut text = "type ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index af0195ffc61..fe353bc994a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2610,7 +2610,7 @@ pub enum ForeignItemKind { /// A function. Fn(FnSig, Generics, Option>), /// A type. - Ty, + TyAlias(Generics, GenericBounds, Option>), /// A macro expanding to an item. Macro(Mac), } @@ -2620,7 +2620,7 @@ impl ForeignItemKind { match *self { ForeignItemKind::Fn(..) => "foreign function", ForeignItemKind::Static(..) => "foreign static item", - ForeignItemKind::Ty => "foreign type", + ForeignItemKind::TyAlias(..) => "foreign type", ForeignItemKind::Macro(..) => "macro in foreign module", } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f3857b3a414..d36b0a28a8c 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1051,7 +1051,11 @@ pub fn noop_flat_map_foreign_item( visit_opt(body, |body| visitor.visit_block(body)); } ForeignItemKind::Static(t, _m) => visitor.visit_ty(t), - ForeignItemKind::Ty => {} + ForeignItemKind::TyAlias(generics, bounds, ty) => { + visitor.visit_generics(generics); + visit_bounds(bounds, visitor); + visit_opt(ty, |ty| visitor.visit_ty(ty)); + } ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_id(id); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index edcfd7f4e78..ed57fc8abf3 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -535,7 +535,11 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI visitor.visit_fn(kind, item.span, item.id); } ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), - ForeignItemKind::Ty => (), + ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + visitor.visit_generics(generics); + walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_ty, ty); + } ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac), } diff --git a/src/test/ui/parser/foreign-ty-semantic-fail.rs b/src/test/ui/parser/foreign-ty-semantic-fail.rs new file mode 100644 index 00000000000..96b15232b10 --- /dev/null +++ b/src/test/ui/parser/foreign-ty-semantic-fail.rs @@ -0,0 +1,18 @@ +#![feature(extern_types)] + +fn main() {} + +extern "C" { + type A: Ord; + //~^ ERROR bounds on `type`s in `extern` blocks have no effect + type B<'a> where 'a: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type C where T: 'static; + //~^ ERROR `type`s inside `extern` blocks cannot have generic parameters + //~| ERROR `type`s inside `extern` blocks cannot have `where` clauses + type D = u8; + //~^ ERROR incorrect `type` inside `extern` block + + type E: where; +} diff --git a/src/test/ui/parser/foreign-ty-semantic-fail.stderr b/src/test/ui/parser/foreign-ty-semantic-fail.stderr new file mode 100644 index 00000000000..588e4966aae --- /dev/null +++ b/src/test/ui/parser/foreign-ty-semantic-fail.stderr @@ -0,0 +1,65 @@ +error: bounds on `type`s in `extern` blocks have no effect + --> $DIR/foreign-ty-semantic-fail.rs:6:13 + | +LL | type A: Ord; + | ^^^ + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:8:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:8:16 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type B<'a> where 'a: 'static; + | ^^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have generic parameters + --> $DIR/foreign-ty-semantic-fail.rs:11:11 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C where T: 'static; + | ^^^^^^^^ help: remove the generic parameters + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:11:20 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type C where T: 'static; + | ^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `type` inside `extern` block + --> $DIR/foreign-ty-semantic-fail.rs:14:10 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign types and types inside of them cannot have a body +... +LL | type D = u8; + | ^ -- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/foreign-ty-syntactic-pass.rs b/src/test/ui/parser/foreign-ty-syntactic-pass.rs new file mode 100644 index 00000000000..a746de1f14f --- /dev/null +++ b/src/test/ui/parser/foreign-ty-syntactic-pass.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern "C" { + type A: Ord; + type A<'a> where 'a: 'static; + type A where T: 'static; + type A = u8; + type A<'a: 'static, T: Ord + 'static>: Eq + PartialEq where T: 'static + Copy = Vec; +} diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs index 9c321c4bd0d..fa9c7ababcf 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -11,11 +11,11 @@ impl X { //~| ERROR associated types are not yet supported in inherent impls type Z: Ord; //~^ ERROR associated type in `impl` without body - //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR bounds on `type`s in `impl`s have no effect //~| ERROR associated types are not yet supported in inherent impls type W: Ord where Self: Eq; //~^ ERROR associated type in `impl` without body - //~| ERROR bounds on associated `type`s in `impl`s have no effect + //~| ERROR bounds on `type`s in `impl`s have no effect //~| ERROR associated types are not yet supported in inherent impls type W where Self: Eq; //~^ ERROR associated type in `impl` without body diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 65e1981e3ac..541d9317c79 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -14,7 +14,7 @@ LL | type Z: Ord; | | | help: provide a definition for the type: `= ;` -error: bounds on associated `type`s in `impl`s have no effect +error: bounds on `type`s in `impl`s have no effect --> $DIR/impl-item-type-no-body-semantic-fail.rs:12:13 | LL | type Z: Ord; @@ -28,7 +28,7 @@ LL | type W: Ord where Self: Eq; | | | help: provide a definition for the type: `= ;` -error: bounds on associated `type`s in `impl`s have no effect +error: bounds on `type`s in `impl`s have no effect --> $DIR/impl-item-type-no-body-semantic-fail.rs:16:13 | LL | type W: Ord where Self: Eq; From 8a37811e2c3b89beb135cf96dcb5d887a6262751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 15 Feb 2020 18:07:17 +0100 Subject: [PATCH 0208/1250] Panic when hashing node IDs --- src/librustc/ich/hcx.rs | 9 +++------ src/libsyntax/node_id.rs | 2 -- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index e0e8470fe47..9e2db35dc6d 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -219,12 +219,9 @@ impl<'a> ToStableHashKey> for hir::HirId { } } -impl<'a> ToStableHashKey> for ast::NodeId { - type KeyType = Self; - - #[inline] - fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> Self { - *self +impl<'a> HashStable> for ast::NodeId { + fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { + panic!("Node IDs should not appear in incremental state"); } } diff --git a/src/libsyntax/node_id.rs b/src/libsyntax/node_id.rs index 430d8f30421..58d2334a7b1 100644 --- a/src/libsyntax/node_id.rs +++ b/src/libsyntax/node_id.rs @@ -1,10 +1,8 @@ -use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; use rustc_span::ExpnId; use std::fmt; rustc_index::newtype_index! { - #[derive(HashStable_Generic)] pub struct NodeId { ENCODABLE = custom DEBUG_FORMAT = "NodeId({})" From 6351bfd182267133409c5174decdff2071f90454 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 02:53:58 +0900 Subject: [PATCH 0209/1250] Add test for issue-39618 --- src/test/ui/specialization/issue-39618.rs | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/ui/specialization/issue-39618.rs diff --git a/src/test/ui/specialization/issue-39618.rs b/src/test/ui/specialization/issue-39618.rs new file mode 100644 index 00000000000..78894a56997 --- /dev/null +++ b/src/test/ui/specialization/issue-39618.rs @@ -0,0 +1,24 @@ +// Regression test for #39618, shouldn't crash. +// check-pass + +#![feature(specialization)] + +trait Foo { + fn foo(&self); +} + +trait Bar { + fn bar(&self); +} + +impl Bar for T where T: Foo { + fn bar(&self) {} +} + +impl Foo for T where T: Bar { + fn foo(&self) {} +} + +impl Foo for u64 {} + +fn main() {} From f32447d54138e9f42ba5a729550603573913397f Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 02:54:16 +0900 Subject: [PATCH 0210/1250] Add test for issue-51798 --- src/test/ui/issues/auxiliary/issue-51798.rs | 3 +++ src/test/ui/issues/issue-51798.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/issue-51798.rs create mode 100644 src/test/ui/issues/issue-51798.rs diff --git a/src/test/ui/issues/auxiliary/issue-51798.rs b/src/test/ui/issues/auxiliary/issue-51798.rs new file mode 100644 index 00000000000..fef5213db9f --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-51798.rs @@ -0,0 +1,3 @@ +#![crate_type = "lib"] + +pub fn vec() -> Vec { vec![] } diff --git a/src/test/ui/issues/issue-51798.rs b/src/test/ui/issues/issue-51798.rs new file mode 100644 index 00000000000..b075809e93a --- /dev/null +++ b/src/test/ui/issues/issue-51798.rs @@ -0,0 +1,14 @@ +// edition:2018 +// aux-build:issue-51798.rs +// check-pass + +extern crate issue_51798; + +mod server { + fn f() { + let mut v = issue_51798::vec(); + v.clear(); + } +} + +fn main() {} From 3134df22143a9d9304e2b835957db6f40f8950da Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 19:02:36 +0100 Subject: [PATCH 0211/1250] adjust run-fail tests --- src/test/run-fail/mir_indexing_oob_1.rs | 2 +- src/test/run-fail/mir_indexing_oob_2.rs | 2 +- src/test/run-fail/mir_indexing_oob_3.rs | 2 +- src/test/run-fail/overflowing-add.rs | 2 +- src/test/run-fail/overflowing-mul.rs | 2 +- src/test/run-fail/overflowing-neg.rs | 2 +- src/test/run-fail/overflowing-sub.rs | 2 +- src/test/run-fail/promoted_div_by_zero.rs | 2 +- src/test/run-fail/promoted_overflow.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/test/run-fail/mir_indexing_oob_1.rs b/src/test/run-fail/mir_indexing_oob_1.rs index 0ae0320b124..6aaf46cfb1b 100644 --- a/src/test/run-fail/mir_indexing_oob_1.rs +++ b/src/test/run-fail/mir_indexing_oob_1.rs @@ -2,7 +2,7 @@ const C: [u32; 5] = [0; 5]; -#[allow(const_err)] +#[allow(panic, const_err)] fn test() -> u32 { C[10] } diff --git a/src/test/run-fail/mir_indexing_oob_2.rs b/src/test/run-fail/mir_indexing_oob_2.rs index a7a1177260c..1bf8459a068 100644 --- a/src/test/run-fail/mir_indexing_oob_2.rs +++ b/src/test/run-fail/mir_indexing_oob_2.rs @@ -2,7 +2,7 @@ const C: &'static [u8; 5] = b"hello"; -#[allow(const_err)] +#[allow(panic, const_err)] fn test() -> u8 { C[10] } diff --git a/src/test/run-fail/mir_indexing_oob_3.rs b/src/test/run-fail/mir_indexing_oob_3.rs index 188460fff78..c13ca721ea8 100644 --- a/src/test/run-fail/mir_indexing_oob_3.rs +++ b/src/test/run-fail/mir_indexing_oob_3.rs @@ -2,7 +2,7 @@ const C: &'static [u8; 5] = b"hello"; -#[allow(const_err)] +#[allow(panic, const_err)] fn mir() -> u8 { C[10] } diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs index 24602aced9e..69d7779e13e 100644 --- a/src/test/run-fail/overflowing-add.rs +++ b/src/test/run-fail/overflowing-add.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to add with overflow' // compile-flags: -C debug-assertions -#![allow(const_err)] +#![allow(overflow)] fn main() { let _x = 200u8 + 200u8 + 200u8; diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs index 48110365a81..ef191c01586 100644 --- a/src/test/run-fail/overflowing-mul.rs +++ b/src/test/run-fail/overflowing-mul.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' // compile-flags: -C debug-assertions -#![allow(const_err)] +#![allow(overflow)] fn main() { let x = 200u8 * 4; diff --git a/src/test/run-fail/overflowing-neg.rs b/src/test/run-fail/overflowing-neg.rs index c4afd74241e..443cddf53fb 100644 --- a/src/test/run-fail/overflowing-neg.rs +++ b/src/test/run-fail/overflowing-neg.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to negate with overflow' // compile-flags: -C debug-assertions -#![allow(const_err)] +#![allow(overflow)] fn main() { let _x = -std::i8::MIN; diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs index e3b111dd2bb..4f4a3eed8cc 100644 --- a/src/test/run-fail/overflowing-sub.rs +++ b/src/test/run-fail/overflowing-sub.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to subtract with overflow' // compile-flags: -C debug-assertions -#![allow(const_err)] +#![allow(overflow)] fn main() { let _x = 42u8 - (42u8 + 1); diff --git a/src/test/run-fail/promoted_div_by_zero.rs b/src/test/run-fail/promoted_div_by_zero.rs index 3fe51a19c20..0ad081f0314 100644 --- a/src/test/run-fail/promoted_div_by_zero.rs +++ b/src/test/run-fail/promoted_div_by_zero.rs @@ -1,4 +1,4 @@ -#![allow(const_err)] +#![allow(panic, const_err)] // error-pattern: attempt to divide by zero diff --git a/src/test/run-fail/promoted_overflow.rs b/src/test/run-fail/promoted_overflow.rs index 139bf540959..a90f832ddd0 100644 --- a/src/test/run-fail/promoted_overflow.rs +++ b/src/test/run-fail/promoted_overflow.rs @@ -1,4 +1,4 @@ -#![allow(const_err)] +#![allow(overflow)] // error-pattern: overflow // compile-flags: -C overflow-checks=yes From ecb8bf069e0a32d8c76884786a5a0b1ea7ccf8d9 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 02:54:33 +0900 Subject: [PATCH 0212/1250] Add test for issue-62894 --- src/test/ui/parser/issue-62894.rs | 7 ++++ src/test/ui/parser/issue-62894.stderr | 47 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 src/test/ui/parser/issue-62894.rs create mode 100644 src/test/ui/parser/issue-62894.stderr diff --git a/src/test/ui/parser/issue-62894.rs b/src/test/ui/parser/issue-62894.rs new file mode 100644 index 00000000000..b9c0bf834dd --- /dev/null +++ b/src/test/ui/parser/issue-62894.rs @@ -0,0 +1,7 @@ +// Regression test for #62894, shouldn't crash. +// error-pattern: this file contains an unclosed delimiter +// error-pattern: expected one of `(`, `[`, or `{`, found keyword `fn` + +fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + +fn main() {} diff --git a/src/test/ui/parser/issue-62894.stderr b/src/test/ui/parser/issue-62894.stderr new file mode 100644 index 00000000000..6db380f7a7f --- /dev/null +++ b/src/test/ui/parser/issue-62894.stderr @@ -0,0 +1,47 @@ +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: this file contains an unclosed delimiter + --> $DIR/issue-62894.rs:7:14 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - - - unclosed delimiter + | | | + | | unclosed delimiter + | unclosed delimiter +LL | +LL | fn main() {} + | ^ + +error: expected one of `(`, `[`, or `{`, found keyword `fn` + --> $DIR/issue-62894.rs:7:1 + | +LL | fn f() { assert_eq!(f(), (), assert_eq!(assert_eq! + | - expected one of `(`, `[`, or `{` +LL | +LL | fn main() {} + | ^^ unexpected token + +error: aborting due to 4 previous errors + From 426dcf0da03b4287991e378c50ddb0718960941b Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 02:54:51 +0900 Subject: [PATCH 0213/1250] Add test for issue-63952 --- src/test/ui/consts/issue-63952.rs | 28 +++++++++++++++++++++++++++ src/test/ui/consts/issue-63952.stderr | 17 ++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/test/ui/consts/issue-63952.rs create mode 100644 src/test/ui/consts/issue-63952.stderr diff --git a/src/test/ui/consts/issue-63952.rs b/src/test/ui/consts/issue-63952.rs new file mode 100644 index 00000000000..35cbc7003f0 --- /dev/null +++ b/src/test/ui/consts/issue-63952.rs @@ -0,0 +1,28 @@ +// Regression test for #63952, shouldn't hang. + +use std::usize; + +#[repr(C)] +#[derive(Copy, Clone)] +struct SliceRepr { + ptr: *const u8, + len: usize, +} + +union SliceTransmute { + repr: SliceRepr, + slice: &'static [u8], +} + +// bad slice: length too big to even exist anywhere +const SLICE_WAY_TOO_LONG: &[u8] = unsafe { //~ ERROR: it is undefined behavior to use this value + SliceTransmute { + repr: SliceRepr { + ptr: &42, + len: usize::MAX, + }, + } + .slice +}; + +fn main() {} diff --git a/src/test/ui/consts/issue-63952.stderr b/src/test/ui/consts/issue-63952.stderr new file mode 100644 index 00000000000..d5ed970fc35 --- /dev/null +++ b/src/test/ui/consts/issue-63952.stderr @@ -0,0 +1,17 @@ +error[E0080]: it is undefined behavior to use this value + --> $DIR/issue-63952.rs:18:1 + | +LL | / const SLICE_WAY_TOO_LONG: &[u8] = unsafe { +LL | | SliceTransmute { +LL | | repr: SliceRepr { +LL | | ptr: &42, +... | +LL | | .slice +LL | | }; + | |__^ invalid slice: total size is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. From 9478503315795401ce037fbca87bf1dbf82f8d31 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 02:55:03 +0900 Subject: [PATCH 0214/1250] Add test for issue-68653 --- .../ui/generic-associated-types/issue-68653.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/test/ui/generic-associated-types/issue-68653.rs diff --git a/src/test/ui/generic-associated-types/issue-68653.rs b/src/test/ui/generic-associated-types/issue-68653.rs new file mode 100644 index 00000000000..01f4c95639d --- /dev/null +++ b/src/test/ui/generic-associated-types/issue-68653.rs @@ -0,0 +1,16 @@ +// A regression test for #68653, which was fixed by #68938. + +// check-pass + +#![allow(incomplete_features)] +#![feature(generic_associated_types)] + +trait Fun { + type F<'a: 'a>; +} + +impl Fun for T { + type F<'a> = Self; +} + +fn main() {} From 94047f18c2681be6aca4a0f4de4947fe47b8f8b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 19:40:33 +0100 Subject: [PATCH 0215/1250] remove no-longer-needed test --- src/test/compile-fail/consts/const-err3.rs | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 src/test/compile-fail/consts/const-err3.rs diff --git a/src/test/compile-fail/consts/const-err3.rs b/src/test/compile-fail/consts/const-err3.rs deleted file mode 100644 index efd51f40224..00000000000 --- a/src/test/compile-fail/consts/const-err3.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![feature(rustc_attrs)] -#![deny(const_err)] - -fn black_box(_: T) { - unimplemented!() -} - -fn main() { - let b = 200u8 + 200u8 + 200u8; - //~^ ERROR overflow - let c = 200u8 * 4; - //~^ ERROR overflow - let d = 42u8 - (42u8 + 1); - //~^ ERROR overflow - let _e = [5u8][1]; - //~^ ERROR panic - black_box(b); - black_box(c); - black_box(d); -} From 2f39ec24b20bc1ef09c7810f8210ea48bb5a3d29 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 04:36:44 +0900 Subject: [PATCH 0216/1250] Add FIXME note --- src/test/ui/specialization/issue-39618.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/ui/specialization/issue-39618.rs b/src/test/ui/specialization/issue-39618.rs index 78894a56997..20e81e4359b 100644 --- a/src/test/ui/specialization/issue-39618.rs +++ b/src/test/ui/specialization/issue-39618.rs @@ -1,4 +1,7 @@ // Regression test for #39618, shouldn't crash. +// FIXME(JohnTitor): Centril pointed out this looks suspicions, we should revisit here. +// More context: https://github.com/rust-lang/rust/pull/69192#discussion_r379846796 + // check-pass #![feature(specialization)] From f3e9763543e5828fe9eee7f5e78c88193f5b8ba5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 14 Feb 2020 14:21:02 +0100 Subject: [PATCH 0217/1250] ast: make `= ;` optional in free statics/consts. --- src/librustc_ast_lowering/item.rs | 37 ++--- src/librustc_ast_passes/ast_validation.rs | 8 + src/librustc_ast_pretty/pprust.rs | 14 +- src/librustc_builtin_macros/test.rs | 148 +++++++++--------- src/librustc_expand/build.rs | 4 +- src/librustc_lint/unused.rs | 2 +- src/librustc_parse/parser/item.rs | 19 +-- src/librustc_resolve/late.rs | 6 +- src/librustc_save_analysis/dump_visitor.rs | 8 +- src/librustc_save_analysis/sig.rs | 18 ++- src/libsyntax/ast.rs | 4 +- src/libsyntax/mut_visit.rs | 8 +- src/libsyntax/visit.rs | 2 +- .../item-free-const-no-body-semantic-fail.rs | 7 + ...em-free-const-no-body-semantic-fail.stderr | 24 +++ .../item-free-const-no-body-syntactic-pass.rs | 8 + .../item-free-static-no-body-semantic-fail.rs | 11 ++ ...m-free-static-no-body-semantic-fail.stderr | 46 ++++++ ...item-free-static-no-body-syntactic-pass.rs | 8 + 19 files changed, 250 insertions(+), 132 deletions(-) create mode 100644 src/test/ui/parser/item-free-const-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr create mode 100644 src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs create mode 100644 src/test/ui/parser/item-free-static-no-body-semantic-fail.rs create mode 100644 src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr create mode 100644 src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 6c4026408ed..f19481d890d 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -269,26 +269,12 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs) } ItemKind::Static(ref t, m, ref e) => { - let ty = self.lower_ty( - t, - if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }, - ); - hir::ItemKind::Static(ty, m, self.lower_const_body(span, Some(e))) + let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + hir::ItemKind::Static(ty, m, body_id) } ItemKind::Const(ref t, ref e) => { - let ty = self.lower_ty( - t, - if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) - } else { - ImplTraitContext::Disallowed(ImplTraitPosition::Binding) - }, - ); - hir::ItemKind::Const(ty, self.lower_const_body(span, Some(e))) + let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); + hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); @@ -457,6 +443,21 @@ impl<'hir> LoweringContext<'_, 'hir> { // not cause an assertion failure inside the `lower_defaultness` function. } + fn lower_const_item( + &mut self, + ty: &Ty, + span: Span, + body: Option<&Expr>, + ) -> (&'hir hir::Ty<'hir>, hir::BodyId) { + let itctx = if self.sess.features_untracked().impl_trait_in_bindings { + ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc) + } else { + ImplTraitContext::Disallowed(ImplTraitPosition::Binding) + }; + let ty = self.lower_ty(ty, itctx); + (ty, self.lower_const_body(span, body)) + } + fn lower_use_tree( &mut self, tree: &UseTree, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index c539f98aecf..fdbf866cd9a 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -948,6 +948,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } } + ItemKind::Const(.., None) => { + let msg = "free constant item without body"; + self.error_item_without_body(item.span, "constant", msg, " = ;"); + } + ItemKind::Static(.., None) => { + let msg = "free static item without body"; + self.error_item_without_body(item.span, "static", msg, " = ;"); + } _ => {} } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b0e1b5d4f42..356fdd1e71c 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1124,9 +1124,10 @@ impl<'a> State<'a> { self.print_type(ty); self.s.space(); self.end(); // end the head-ibox - - self.word_space("="); - self.print_expr(expr); + if let Some(expr) = expr { + self.word_space("="); + self.print_expr(expr); + } self.s.word(";"); self.end(); // end the outer cbox } @@ -1137,9 +1138,10 @@ impl<'a> State<'a> { self.print_type(ty); self.s.space(); self.end(); // end the head-ibox - - self.word_space("="); - self.print_expr(expr); + if let Some(expr) = expr { + self.word_space("="); + self.print_expr(expr); + } self.s.word(";"); self.end(); // end the outer cbox } diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 02a0bc00c11..b6837c0703a 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -186,81 +186,85 @@ pub fn expand_test_or_bench( ast::ItemKind::Const( cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), // test::TestDescAndFn { - cx.expr_struct( - sp, - test_path("TestDescAndFn"), - vec![ - // desc: test::TestDesc { - field( - "desc", - cx.expr_struct( - sp, - test_path("TestDesc"), - vec![ - // name: "path::to::test" - field( - "name", - cx.expr_call( - sp, - cx.expr_path(test_path("StaticTestName")), - vec![cx.expr_str( - sp, - Symbol::intern(&item_path( - // skip the name of the root module - &cx.current_expansion.module.mod_path[1..], - &item.ident, - )), - )], - ), - ), - // ignore: true | false - field("ignore", cx.expr_bool(sp, should_ignore(&item))), - // allow_fail: true | false - field("allow_fail", cx.expr_bool(sp, should_fail(&item))), - // should_panic: ... - field( - "should_panic", - match should_panic(cx, &item) { - // test::ShouldPanic::No - ShouldPanic::No => cx.expr_path(should_panic_path("No")), - // test::ShouldPanic::Yes - ShouldPanic::Yes(None) => { - cx.expr_path(should_panic_path("Yes")) - } - // test::ShouldPanic::YesWithMessage("...") - ShouldPanic::Yes(Some(sym)) => cx.expr_call( + Some( + cx.expr_struct( + sp, + test_path("TestDescAndFn"), + vec![ + // desc: test::TestDesc { + field( + "desc", + cx.expr_struct( + sp, + test_path("TestDesc"), + vec![ + // name: "path::to::test" + field( + "name", + cx.expr_call( sp, - cx.expr_path(should_panic_path("YesWithMessage")), - vec![cx.expr_str(sp, sym)], + cx.expr_path(test_path("StaticTestName")), + vec![cx.expr_str( + sp, + Symbol::intern(&item_path( + // skip the name of the root module + &cx.current_expansion.module.mod_path[1..], + &item.ident, + )), + )], ), - }, - ), - // test_type: ... - field( - "test_type", - match test_type(cx) { - // test::TestType::UnitTest - TestType::UnitTest => { - cx.expr_path(test_type_path("UnitTest")) - } - // test::TestType::IntegrationTest - TestType::IntegrationTest => { - cx.expr_path(test_type_path("IntegrationTest")) - } - // test::TestPath::Unknown - TestType::Unknown => { - cx.expr_path(test_type_path("Unknown")) - } - }, - ), - // }, - ], + ), + // ignore: true | false + field("ignore", cx.expr_bool(sp, should_ignore(&item))), + // allow_fail: true | false + field("allow_fail", cx.expr_bool(sp, should_fail(&item))), + // should_panic: ... + field( + "should_panic", + match should_panic(cx, &item) { + // test::ShouldPanic::No + ShouldPanic::No => { + cx.expr_path(should_panic_path("No")) + } + // test::ShouldPanic::Yes + ShouldPanic::Yes(None) => { + cx.expr_path(should_panic_path("Yes")) + } + // test::ShouldPanic::YesWithMessage("...") + ShouldPanic::Yes(Some(sym)) => cx.expr_call( + sp, + cx.expr_path(should_panic_path("YesWithMessage")), + vec![cx.expr_str(sp, sym)], + ), + }, + ), + // test_type: ... + field( + "test_type", + match test_type(cx) { + // test::TestType::UnitTest + TestType::UnitTest => { + cx.expr_path(test_type_path("UnitTest")) + } + // test::TestType::IntegrationTest + TestType::IntegrationTest => { + cx.expr_path(test_type_path("IntegrationTest")) + } + // test::TestPath::Unknown + TestType::Unknown => { + cx.expr_path(test_type_path("Unknown")) + } + }, + ), + // }, + ], + ), ), - ), - // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) - field("testfn", test_fn), // } - ], - ), // } + // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) + field("testfn", test_fn), // } + ], + ), // } + ), ), ); test_const = test_const.map(|mut tc| { diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index af22e46eb6a..08821510630 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -634,7 +634,7 @@ impl<'a> ExtCtxt<'a> { mutbl: ast::Mutability, expr: P, ) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, expr)) + self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr))) } pub fn item_const( @@ -644,7 +644,7 @@ impl<'a> ExtCtxt<'a> { ty: P, expr: P, ) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, expr)) + self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, Some(expr))) } pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 480df99a01e..7870b9da4cb 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -603,7 +603,7 @@ impl EarlyLintPass for UnusedParens { fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { use ast::ItemKind::*; - if let Const(.., ref expr) | Static(.., ref expr) = item.kind { + if let Const(.., Some(expr)) | Static(.., Some(expr)) = &item.kind { self.check_unused_parens_expr(cx, expr, "assigned value", false, None, None); } } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 4a5b4ff8e04..893cbf5adfa 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -966,7 +966,7 @@ impl<'a> Parser<'a> { } } - /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty = $expr` with + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// /// When `m` is `"const"`, `$ident` may also be `"_"`. @@ -975,25 +975,22 @@ impl<'a> Parser<'a> { // Parse the type of a `const` or `static mut?` item. // That is, the `":" $ty` fragment. - let ty = if self.token == token::Eq { - self.recover_missing_const_type(id, m) - } else { - // Not `=` so expect `":"" $ty` as usual. - self.expect(&token::Colon)?; + let ty = if self.eat(&token::Colon) { self.parse_ty()? + } else { + self.recover_missing_const_type(id, m) }; - self.expect(&token::Eq)?; - let e = self.parse_expr()?; + let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; let item = match m { - Some(m) => ItemKind::Static(ty, m, e), - None => ItemKind::Const(ty, e), + Some(m) => ItemKind::Static(ty, m, expr), + None => ItemKind::Const(ty, expr), }; Ok((id, item)) } - /// We were supposed to parse `:` but instead, we're already at `=`. + /// We were supposed to parse `:` but the `:` was missing. /// This means that the type is missing. fn recover_missing_const_type(&mut self, id: Ident, m: Option) -> P { // Construct the error and stash it away with the hope diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 1a1a9b1076e..36667e1d6ff 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -881,9 +881,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("resolve_item ItemKind::Const"); self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); - this.with_constant_rib(|this| { - this.visit_expr(expr); - }); + if let Some(expr) = expr { + this.with_constant_rib(|this| this.visit_expr(expr)); + } }); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 5668be40eef..fc5496eb182 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -400,7 +400,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &mut self, item: &'l ast::Item, typ: &'l ast::Ty, - expr: &'l ast::Expr, + expr: Option<&'l ast::Expr>, ) { let hir_id = self.tcx.hir().node_to_hir_id(item.id); self.nest_tables(item.id, |v| { @@ -409,7 +409,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data); } v.visit_ty(&typ); - v.visit_expr(expr); + walk_list!(v, visit_expr, expr); }); } @@ -1293,8 +1293,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { Fn(ref sig, ref ty_params, ref body) => { self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref()) } - Static(ref typ, _, ref expr) => self.process_static_or_const_item(item, typ, expr), - Const(ref typ, ref expr) => self.process_static_or_const_item(item, &typ, &expr), + Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), + Const(ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => { self.process_struct(item, def, ty_params) } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index bd7bd9bc616..d678a8b067e 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -334,10 +334,13 @@ impl Sig for ast::Item { let ty = ty.make(offset + text.len(), id, scx)?; text.push_str(&ty.text); - text.push_str(" = "); - let expr = pprust::expr_to_string(expr).replace('\n', " "); - text.push_str(&expr); + if let Some(expr) = expr { + text.push_str(" = "); + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + } + text.push(';'); Ok(extend_sig(ty, text, defs, vec![])) @@ -355,10 +358,13 @@ impl Sig for ast::Item { let ty = ty.make(offset + text.len(), id, scx)?; text.push_str(&ty.text); - text.push_str(" = "); - let expr = pprust::expr_to_string(expr).replace('\n', " "); - text.push_str(&expr); + if let Some(expr) = expr { + text.push_str(" = "); + let expr = pprust::expr_to_string(expr).replace('\n', " "); + text.push_str(&expr); + } + text.push(';'); Ok(extend_sig(ty, text, defs, vec![])) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index fe353bc994a..61ae14cae02 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2496,11 +2496,11 @@ pub enum ItemKind { /// A static item (`static`). /// /// E.g., `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`. - Static(P, Mutability, P), + Static(P, Mutability, Option>), /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. - Const(P, P), + Const(P, Option>), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index d36b0a28a8c..cd7a3becca7 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -890,13 +890,9 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(ty, _mut, expr) => { + ItemKind::Static(ty, _, expr) | ItemKind::Const(ty, expr) => { vis.visit_ty(ty); - vis.visit_expr(expr); - } - ItemKind::Const(ty, expr) => { - vis.visit_ty(ty); - vis.visit_expr(expr); + visit_opt(expr, |expr| vis.visit_expr(expr)); } ItemKind::Fn(sig, generics, body) => { visit_fn_sig(sig, vis); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index ed57fc8abf3..4beb94e9f0c 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -300,7 +300,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false), ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(ref typ, ref expr) => { visitor.visit_ty(typ); - visitor.visit_expr(expr); + walk_list!(visitor, visit_expr, expr); } ItemKind::Fn(ref sig, ref generics, ref body) => { visitor.visit_generics(generics); diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs new file mode 100644 index 00000000000..613b3c98561 --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.rs @@ -0,0 +1,7 @@ +// Semantically, a free `const` item cannot omit its body. + +fn main() {} + +const A: u8; //~ ERROR free constant item without body +const B; //~ ERROR free constant item without body +//~^ ERROR missing type for `const` item diff --git a/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr new file mode 100644 index 00000000000..4e97229fa1a --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-semantic-fail.stderr @@ -0,0 +1,24 @@ +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:5:1 + | +LL | const A: u8; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: free constant item without body + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:1 + | +LL | const B; + | ^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: missing type for `const` item + --> $DIR/item-free-const-no-body-semantic-fail.rs:6:7 + | +LL | const B; + | ^ help: provide a type for the item: `B: [type error]` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs b/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs new file mode 100644 index 00000000000..acfdd3c363f --- /dev/null +++ b/src/test/ui/parser/item-free-const-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const X: u8; diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs new file mode 100644 index 00000000000..780479e3d26 --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.rs @@ -0,0 +1,11 @@ +// Semantically, a free `static` item cannot omit its body. + +fn main() {} + +static A: u8; //~ ERROR free static item without body +static B; //~ ERROR free static item without body +//~^ ERROR missing type for `static` item + +static mut C: u8; //~ ERROR free static item without body +static mut D; //~ ERROR free static item without body +//~^ ERROR missing type for `static mut` item diff --git a/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr new file mode 100644 index 00000000000..60b7bb34c69 --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-semantic-fail.stderr @@ -0,0 +1,46 @@ +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:5:1 + | +LL | static A: u8; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:1 + | +LL | static B; + | ^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:9:1 + | +LL | static mut C: u8; + | ^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: free static item without body + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:1 + | +LL | static mut D; + | ^^^^^^^^^^^^- + | | + | help: provide a definition for the static: `= ;` + +error: missing type for `static` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:6:8 + | +LL | static B; + | ^ help: provide a type for the item: `B: [type error]` + +error: missing type for `static mut` item + --> $DIR/item-free-static-no-body-semantic-fail.rs:10:12 + | +LL | static mut D; + | ^ help: provide a type for the item: `D: [type error]` + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs b/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs new file mode 100644 index 00000000000..db0039204d8 --- /dev/null +++ b/src/test/ui/parser/item-free-static-no-body-syntactic-pass.rs @@ -0,0 +1,8 @@ +// Syntactically, a free `const` item can omit its body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +static X: u8; From 1c2906ead3825c013ac022249f1e1ee3a3b97c75 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 14 Feb 2020 15:56:05 +0100 Subject: [PATCH 0218/1250] ast/parser: fuse `static` & `const` grammars in all contexts. --- src/librustc_ast_lowering/item.rs | 2 +- src/librustc_ast_passes/ast_validation.rs | 34 +++++++-- src/librustc_ast_pretty/pprust.rs | 71 ++++++------------- src/librustc_parse/parser/item.rs | 37 +++++----- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 2 +- src/libsyntax/mut_visit.rs | 5 +- src/libsyntax/visit.rs | 5 +- .../assoc-const-underscore-semantic-fail.rs | 17 +++++ ...ssoc-const-underscore-semantic-fail.stderr | 27 +++++++ .../assoc-const-underscore-syntactic-pass.rs | 18 +++++ .../ui/parser/foreign-static-semantic-fail.rs | 8 +++ .../foreign-static-semantic-fail.stderr | 27 +++++++ .../parser/foreign-static-syntactic-pass.rs | 11 +++ .../ui/parser/underscore_item_not_const.rs | 16 +---- .../parser/underscore_item_not_const.stderr | 44 ++++-------- 18 files changed, 205 insertions(+), 125 deletions(-) create mode 100644 src/test/ui/parser/assoc-const-underscore-semantic-fail.rs create mode 100644 src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr create mode 100644 src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs create mode 100644 src/test/ui/parser/foreign-static-semantic-fail.rs create mode 100644 src/test/ui/parser/foreign-static-semantic-fail.stderr create mode 100644 src/test/ui/parser/foreign-static-syntactic-pass.rs diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index f19481d890d..813af18c401 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -679,7 +679,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ForeignItemKind::Fn(fn_dec, fn_args, generics) } - ForeignItemKind::Static(ref t, m) => { + ForeignItemKind::Static(ref t, m, _) => { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index fdbf866cd9a..fd65750367e 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -464,19 +464,22 @@ impl<'a> AstValidator<'a> { } } - fn check_foreign_ty_bodyless(&self, ident: Ident, body: Option<&Ty>) { + fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option) { let body = match body { None => return, Some(body) => body, }; self.err_handler() - .struct_span_err(ident.span, "incorrect `type` inside `extern` block") + .struct_span_err(ident.span, &format!("incorrect `{}` inside `extern` block", kind)) .span_label(ident.span, "cannot have a body") - .span_label(body.span, "the invalid body") + .span_label(body, "the invalid body") .span_label( self.current_extern_span(), - "`extern` blocks define existing foreign types and types \ - inside of them cannot have a body", + format!( + "`extern` blocks define existing foreign {0}s and {0}s \ + inside of them cannot have a body", + kind + ), ) .note(MORE_EXTERN) .emit(); @@ -579,6 +582,16 @@ impl<'a> AstValidator<'a> { } } } + + fn check_item_named(&self, ident: Ident, kind: &str) { + if ident.name != kw::Underscore { + return; + } + self.err_handler() + .struct_span_err(ident.span, &format!("`{}` items in this context need a name", kind)) + .span_label(ident.span, format!("`_` is not a valid name for this `{}` item", kind)) + .emit(); + } } enum GenericPosition { @@ -969,11 +982,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); } ForeignItemKind::TyAlias(generics, bounds, body) => { - self.check_foreign_ty_bodyless(fi.ident, body.as_deref()); + self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics); } - ForeignItemKind::Static(..) | ForeignItemKind::Macro(..) => {} + ForeignItemKind::Static(_, _, body) => { + self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); + } + ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, fi) @@ -1234,6 +1250,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } + if let AssocItemKind::Const(..) = item.kind { + self.check_item_named(item.ident, "const"); + } + self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt)); } } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 356fdd1e71c..e9dacfec23c 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1023,17 +1023,8 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(sig, gen, body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); } - ast::ForeignItemKind::Static(t, m) => { - self.head(visibility_qualified(&item.vis, "static")); - if *m == ast::Mutability::Mut { - self.word_space("mut"); - } - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(t); - self.s.word(";"); - self.end(); // end the head-ibox - self.end(); // end the outer cbox + ast::ForeignItemKind::Static(ty, mutbl, body) => { + self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis); } ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { self.print_associated_type(item.ident, generics, bounds, ty.as_deref()); @@ -1047,24 +1038,31 @@ impl<'a> State<'a> { } } - fn print_associated_const( + fn print_item_const( &mut self, ident: ast::Ident, + mutbl: Option, ty: &ast::Ty, - default: Option<&ast::Expr>, + body: Option<&ast::Expr>, vis: &ast::Visibility, ) { - self.s.word(visibility_qualified(vis, "")); - self.word_space("const"); + let leading = match mutbl { + None => "const ", + Some(ast::Mutability::Not) => "static ", + Some(ast::Mutability::Mut) => "static mut ", + }; + self.head(visibility_qualified(vis, leading)); self.print_ident(ident); self.word_space(":"); self.print_type(ty); - if let Some(expr) = default { - self.s.space(); + self.s.space(); + self.end(); // end the head-ibox + if let Some(body) = body { self.word_space("="); - self.print_expr(expr); + self.print_expr(body); } - self.s.word(";") + self.s.word(";"); + self.end(); // end the outer cbox } fn print_associated_type( @@ -1114,36 +1112,11 @@ impl<'a> State<'a> { self.end(); // end inner head-block self.end(); // end outer head-block } - ast::ItemKind::Static(ref ty, m, ref expr) => { - self.head(visibility_qualified(&item.vis, "static")); - if m == ast::Mutability::Mut { - self.word_space("mut"); - } - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(ty); - self.s.space(); - self.end(); // end the head-ibox - if let Some(expr) = expr { - self.word_space("="); - self.print_expr(expr); - } - self.s.word(";"); - self.end(); // end the outer cbox + ast::ItemKind::Static(ref ty, mutbl, ref body) => { + self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis); } - ast::ItemKind::Const(ref ty, ref expr) => { - self.head(visibility_qualified(&item.vis, "const")); - self.print_ident(item.ident); - self.word_space(":"); - self.print_type(ty); - self.s.space(); - self.end(); // end the head-ibox - if let Some(expr) = expr { - self.word_space("="); - self.print_expr(expr); - } - self.s.word(";"); - self.end(); // end the outer cbox + ast::ItemKind::Const(ref ty, ref body) => { + self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); } ast::ItemKind::Fn(ref sig, ref gen, ref body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); @@ -1469,7 +1442,7 @@ impl<'a> State<'a> { self.print_defaultness(item.defaultness); match &item.kind { ast::AssocItemKind::Const(ty, expr) => { - self.print_associated_const(item.ident, ty, expr.as_deref(), &item.vis); + self.print_item_const(item.ident, None, ty, expr.as_deref(), &item.vis); } ast::AssocItemKind::Fn(sig, generics, body) => { let body = body.as_deref(); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 893cbf5adfa..ab915802395 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -670,7 +670,7 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; (ident, AssocItemKind::Fn(sig, generics, body)) - } else if self.check_keyword(kw::Const) { + } else if self.eat_keyword(kw::Const) { self.parse_assoc_const()? } else if self.isnt_macro_invocation() { return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); @@ -693,11 +693,7 @@ impl<'a> Parser<'a> { /// AssocConst = "const" Ident ":" Ty "=" Expr ";" fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { self.expect_keyword(kw::Const)?; - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; - self.expect_semi()?; + let (ident, ty, expr) = self.parse_item_const_common(None)?; Ok((ident, AssocItemKind::Const(ty, expr))) } @@ -916,11 +912,8 @@ impl<'a> Parser<'a> { /// Assumes that the `static` keyword is already parsed. fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let mutbl = self.parse_mutability(); - let ident = self.parse_ident()?; - self.expect(&token::Colon)?; - let ty = self.parse_ty()?; - self.expect_semi()?; - Ok((ident, ForeignItemKind::Static(ty, mutbl))) + let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; + Ok((ident, ForeignItemKind::Static(ty, mutbl, expr))) } /// Parses a type from a foreign module. @@ -971,6 +964,22 @@ impl<'a> Parser<'a> { /// /// When `m` is `"const"`, `$ident` may also be `"_"`. fn parse_item_const(&mut self, m: Option) -> PResult<'a, ItemInfo> { + let (id, ty, expr) = self.parse_item_const_common(m)?; + let item = match m { + Some(m) => ItemKind::Static(ty, m, expr), + None => ItemKind::Const(ty, expr), + }; + Ok((id, item)) + } + + /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with + /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. + /// + /// When `m` is `"const"`, `$ident` may also be `"_"`. + fn parse_item_const_common( + &mut self, + m: Option, + ) -> PResult<'a, (Ident, P, Option>)> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; // Parse the type of a `const` or `static mut?` item. @@ -983,11 +992,7 @@ impl<'a> Parser<'a> { let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - let item = match m { - Some(m) => ItemKind::Static(ty, m, expr), - None => ItemKind::Const(ty, expr), - }; - Ok((id, item)) + Ok((id, ty, expr)) } /// We were supposed to parse `:` but the `:` was missing. diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index fc5496eb182..574689be491 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1532,7 +1532,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Static(ref ty, _) => { + ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index e983802ee11..6bb2bf4c1e9 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, _) => { + ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index d678a8b067e..8fba3109f21 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -760,7 +760,7 @@ impl Sig for ast::ForeignItem { Ok(sig) } - ast::ForeignItemKind::Static(ref ty, m) => { + ast::ForeignItemKind::Static(ref ty, m, _) => { let mut text = "static ".to_owned(); if m == ast::Mutability::Mut { text.push_str("mut "); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 61ae14cae02..bbb629012a9 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2606,7 +2606,7 @@ pub type ForeignItem = Item; #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { /// A static item (`static FOO: u8`). - Static(P, Mutability), + Static(P, Mutability, Option>), /// A function. Fn(FnSig, Generics, Option>), /// A type. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index cd7a3becca7..62f640f0bfa 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1046,7 +1046,10 @@ pub fn noop_flat_map_foreign_item( visitor.visit_generics(generics); visit_opt(body, |body| visitor.visit_block(body)); } - ForeignItemKind::Static(t, _m) => visitor.visit_ty(t), + ForeignItemKind::Static(ty, _, body) => { + visitor.visit_ty(ty); + visit_opt(body, |body| visitor.visit_expr(body)); + } ForeignItemKind::TyAlias(generics, bounds, ty) => { visitor.visit_generics(generics); visit_bounds(bounds, visitor); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 4beb94e9f0c..0dd21cdf12f 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -534,7 +534,10 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id); } - ForeignItemKind::Static(ref typ, _) => visitor.visit_ty(typ), + ForeignItemKind::Static(ref typ, _, ref body) => { + visitor.visit_ty(typ); + walk_list!(visitor, visit_expr, body); + } ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); diff --git a/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs b/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs new file mode 100644 index 00000000000..d37ce06c555 --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-semantic-fail.rs @@ -0,0 +1,17 @@ +// Semantically, an associated constant cannot use `_` as a name. + +fn main() {} + +const _: () = { + pub trait A { + const _: () = (); //~ ERROR `const` items in this context need a name + } + impl A for () { + const _: () = (); //~ ERROR `const` items in this context need a name + //~^ ERROR const `_` is not a member of trait `A` + } + struct B; + impl B { + const _: () = (); //~ ERROR `const` items in this context need a name + } +}; diff --git a/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr b/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr new file mode 100644 index 00000000000..538bf0ec100 --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:7:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error: `const` items in this context need a name + --> $DIR/assoc-const-underscore-semantic-fail.rs:15:15 + | +LL | const _: () = (); + | ^ `_` is not a valid name for this `const` item + +error[E0438]: const `_` is not a member of trait `A` + --> $DIR/assoc-const-underscore-semantic-fail.rs:10:9 + | +LL | const _: () = (); + | ^^^^^^^^^^^^^^^^^ not a member of trait `A` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0438`. diff --git a/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs b/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs new file mode 100644 index 00000000000..60da408c811 --- /dev/null +++ b/src/test/ui/parser/assoc-const-underscore-syntactic-pass.rs @@ -0,0 +1,18 @@ +// All constant items (associated or otherwise) may syntactically use `_` as a name. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +const _: () = { + pub trait A { + const _: () = (); + } + impl A for () { + const _: () = (); + } + impl dyn A { + const _: () = (); + } +}; diff --git a/src/test/ui/parser/foreign-static-semantic-fail.rs b/src/test/ui/parser/foreign-static-semantic-fail.rs new file mode 100644 index 00000000000..9abdf33df9c --- /dev/null +++ b/src/test/ui/parser/foreign-static-semantic-fail.rs @@ -0,0 +1,8 @@ +// Syntactically, a foreign static may not have a body. + +fn main() {} + +extern { + static X: u8 = 0; //~ ERROR incorrect `static` inside `extern` block + static mut Y: u8 = 0; //~ ERROR incorrect `static` inside `extern` block +} diff --git a/src/test/ui/parser/foreign-static-semantic-fail.stderr b/src/test/ui/parser/foreign-static-semantic-fail.stderr new file mode 100644 index 00000000000..5942e3a9449 --- /dev/null +++ b/src/test/ui/parser/foreign-static-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:6:12 + | +LL | extern { + | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: incorrect `static` inside `extern` block + --> $DIR/foreign-static-semantic-fail.rs:7:16 + | +LL | extern { + | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body +LL | static X: u8 = 0; +LL | static mut Y: u8 = 0; + | ^ - the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-static-syntactic-pass.rs b/src/test/ui/parser/foreign-static-syntactic-pass.rs new file mode 100644 index 00000000000..2c805e8a0b7 --- /dev/null +++ b/src/test/ui/parser/foreign-static-syntactic-pass.rs @@ -0,0 +1,11 @@ +// Syntactically, a foreign static may have a body. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern { + static X: u8 = 0; + static mut Y: u8 = 0; +} diff --git a/src/test/ui/parser/underscore_item_not_const.rs b/src/test/ui/parser/underscore_item_not_const.rs index 7b0d128f06f..c01ac4752e0 100644 --- a/src/test/ui/parser/underscore_item_not_const.rs +++ b/src/test/ui/parser/underscore_item_not_const.rs @@ -1,18 +1,4 @@ -// Test that various non-const items and associated consts do not permit `_` as a name. - -// Associated `const`s: - -pub trait A { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} -impl A for () { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} -impl dyn A { - const _: () = (); //~ ERROR expected identifier, found reserved identifier `_` -} - -// Other kinds of items: +// Test that various non-const items do not syntactically permit `_` as a name. static _: () = (); //~ ERROR expected identifier, found reserved identifier `_` struct _(); //~ ERROR expected identifier, found reserved identifier `_` diff --git a/src/test/ui/parser/underscore_item_not_const.stderr b/src/test/ui/parser/underscore_item_not_const.stderr index ebf1ff9ff1e..0bc7642dd19 100644 --- a/src/test/ui/parser/underscore_item_not_const.stderr +++ b/src/test/ui/parser/underscore_item_not_const.stderr @@ -1,92 +1,74 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:6:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:9:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:12:11 - | -LL | const _: () = (); - | ^ expected identifier, found reserved identifier - -error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:17:8 + --> $DIR/underscore_item_not_const.rs:3:8 | LL | static _: () = (); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:18:8 + --> $DIR/underscore_item_not_const.rs:4:8 | LL | struct _(); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:19:6 + --> $DIR/underscore_item_not_const.rs:5:6 | LL | enum _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:20:4 + --> $DIR/underscore_item_not_const.rs:6:4 | LL | fn _() {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:21:5 + --> $DIR/underscore_item_not_const.rs:7:5 | LL | mod _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:22:6 + --> $DIR/underscore_item_not_const.rs:8:6 | LL | type _ = (); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:23:5 + --> $DIR/underscore_item_not_const.rs:9:5 | LL | use _; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:24:5 + --> $DIR/underscore_item_not_const.rs:10:5 | LL | use _ as g; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:25:7 + --> $DIR/underscore_item_not_const.rs:11:7 | LL | trait _ {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:26:7 + --> $DIR/underscore_item_not_const.rs:12:7 | LL | trait _ = Copy; | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:27:14 + --> $DIR/underscore_item_not_const.rs:13:14 | LL | macro_rules! _ { () => {} } | ^ expected identifier, found reserved identifier error: expected one of `!` or `::`, found reserved identifier `_` - --> $DIR/underscore_item_not_const.rs:28:7 + --> $DIR/underscore_item_not_const.rs:14:7 | LL | union _ { f: u8 } | ^ expected one of `!` or `::` -error: aborting due to 15 previous errors +error: aborting due to 12 previous errors From f8d2264463162291f5cb3391c98d7bc95ec17d87 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 01:50:26 +0100 Subject: [PATCH 0219/1250] parse associated statics. --- src/librustc_ast_lowering/item.rs | 13 ++- src/librustc_ast_passes/ast_validation.rs | 9 +- src/librustc_ast_pretty/pprust.rs | 3 + src/librustc_parse/parser/item.rs | 18 ++-- src/librustc_resolve/build_reduced_graph.rs | 3 +- src/librustc_resolve/def_collector.rs | 4 +- src/librustc_resolve/late.rs | 5 +- src/librustc_save_analysis/dump_visitor.rs | 6 +- src/libsyntax/ast.rs | 2 + src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/visit.rs | 2 +- src/test/ui/issues/issue-58856-2.stderr | 4 +- src/test/ui/issues/issue-60075.stderr | 2 +- .../ui/parser/assoc-static-semantic-fail.rs | 43 ++++++++ .../parser/assoc-static-semantic-fail.stderr | 99 +++++++++++++++++++ .../ui/parser/assoc-static-syntactic-pass.rs | 29 ++++++ src/test/ui/parser/issue-32446.stderr | 4 +- src/test/ui/parser/issue-41155.stderr | 4 +- .../parser/macro/trait-non-item-macros.stderr | 4 +- .../ui/parser/removed-syntax-static-fn.rs | 4 +- .../ui/parser/removed-syntax-static-fn.stderr | 25 +++-- 21 files changed, 243 insertions(+), 42 deletions(-) create mode 100644 src/test/ui/parser/assoc-static-semantic-fail.rs create mode 100644 src/test/ui/parser/assoc-static-semantic-fail.stderr create mode 100644 src/test/ui/parser/assoc-static-syntactic-pass.rs diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 813af18c401..b465fd79c8f 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -760,7 +760,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - AssocItemKind::Const(ref ty, ref default) => { + AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`. + | AssocItemKind::Const(ref ty, ref default) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) @@ -802,7 +803,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { let (kind, has_default) = match &i.kind { - AssocItemKind::Const(_, default) => (hir::AssocItemKind::Const, default.is_some()), + AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery. + | AssocItemKind::Const(_, default) => { + (hir::AssocItemKind::Const, default.is_some()) + } AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()), AssocItemKind::Fn(sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) @@ -827,7 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - AssocItemKind::Const(ref ty, ref expr) => { + AssocItemKind::Static(ref ty, _, ref expr) | AssocItemKind::Const(ref ty, ref expr) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); ( hir::Generics::empty(), @@ -895,7 +899,8 @@ impl<'hir> LoweringContext<'_, 'hir> { vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), kind: match &i.kind { - AssocItemKind::Const(..) => hir::AssocItemKind::Const, + AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery. + | AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::TyAlias(_, _, ty) => { match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index fd65750367e..72cffdd750a 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -1250,8 +1250,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - if let AssocItemKind::Const(..) = item.kind { - self.check_item_named(item.ident, "const"); + match item.kind { + AssocItemKind::Const(..) => self.check_item_named(item.ident, "const"), + AssocItemKind::Static(..) => self + .err_handler() + .struct_span_err(item.span, "associated `static` items are not allowed") + .emit(), + _ => {} } self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt)); diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index e9dacfec23c..ee1a829da1a 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1441,6 +1441,9 @@ impl<'a> State<'a> { self.print_outer_attributes(&item.attrs); self.print_defaultness(item.defaultness); match &item.kind { + ast::AssocItemKind::Static(ty, mutbl, expr) => { + self.print_item_const(item.ident, Some(*mutbl), ty, expr.as_deref(), &item.vis); + } ast::AssocItemKind::Const(ty, expr) => { self.print_item_const(item.ident, None, ty, expr.as_deref(), &item.vis); } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ab915802395..9b7728f27d0 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -546,6 +546,7 @@ impl<'a> Parser<'a> { 1, &[ kw::Impl, + kw::Static, kw::Const, kw::Async, kw::Fn, @@ -670,8 +671,14 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; (ident, AssocItemKind::Fn(sig, generics, body)) + } else if self.is_static_global() { + self.bump(); // `static` + let mutbl = self.parse_mutability(); + let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; + (ident, AssocItemKind::Static(ty, mutbl, expr)) } else if self.eat_keyword(kw::Const) { - self.parse_assoc_const()? + let (ident, ty, expr) = self.parse_item_const_common(None)?; + (ident, AssocItemKind::Const(ty, expr)) } else if self.isnt_macro_invocation() { return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); } else if self.token.is_path_start() { @@ -688,15 +695,6 @@ impl<'a> Parser<'a> { Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) } - /// This parses the grammar: - /// - /// AssocConst = "const" Ident ":" Ty "=" Expr ";" - fn parse_assoc_const(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { - self.expect_keyword(kw::Const)?; - let (ident, ty, expr) = self.parse_item_const_common(None)?; - Ok((ident, AssocItemKind::Const(ty, expr))) - } - /// Parses the following grammar: /// /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f5e64443dda..7c541928e6f 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1251,7 +1251,8 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { // Add the item to the trait info. let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { - AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), + AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery. + | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), AssocItemKind::Fn(ref sig, _, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 256b5ff4b9a..60cba555121 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -228,7 +228,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body.as_deref(), ); } - AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), + AssocItemKind::Fn(..) | AssocItemKind::Const(..) | AssocItemKind::Static(..) => { + DefPathData::ValueNs(i.ident.name) + } AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id), }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 36667e1d6ff..7b445fcc035 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -836,7 +836,8 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for item in trait_items { this.with_trait_items(trait_items, |this| { match &item.kind { - AssocItemKind::Const(ty, default) => { + AssocItemKind::Static(ty, _, default) + | AssocItemKind::Const(ty, default) => { this.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -1109,7 +1110,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for item in impl_items { use crate::ResolutionError::*; match &item.kind { - AssocItemKind::Const(..) => { + AssocItemKind::Static(..) | AssocItemKind::Const(..) => { debug!("resolve_implementation AssocItemKind::Const",); // If this is a trait impl, ensure the const // exists in trait diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 574689be491..001f2f09854 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1004,7 +1004,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.process_macro_use(trait_item.span); let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { - ast::AssocItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Static(ref ty, _, ref expr) + | ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( trait_item.id, trait_item.ident, @@ -1074,7 +1075,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) { self.process_macro_use(impl_item.span); match impl_item.kind { - ast::AssocItemKind::Const(ref ty, ref expr) => { + ast::AssocItemKind::Static(ref ty, _, ref expr) + | ast::AssocItemKind::Const(ref ty, ref expr) => { self.process_assoc_const( impl_item.id, impl_item.ident, diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bbb629012a9..ca39fbd6c5d 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2654,6 +2654,8 @@ pub enum AssocItemKind { /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. Const(P, Option>), + /// A static item (`static FOO: u8`). + Static(P, Mutability, Option>), /// A function. Fn(FnSig, Generics, Option>), /// A type. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 62f640f0bfa..91db6158689 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -954,7 +954,7 @@ pub fn noop_flat_map_assoc_item( visitor.visit_vis(vis); visit_attrs(attrs, visitor); match kind { - AssocItemKind::Const(ty, expr) => { + AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 0dd21cdf12f..f5763ecf573 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -633,7 +633,7 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, visitor.visit_ident(item.ident); walk_list!(visitor, visit_attribute, &item.attrs); match item.kind { - AssocItemKind::Const(ref ty, ref expr) => { + AssocItemKind::Const(ref ty, ref expr) | AssocItemKind::Static(ref ty, _, ref expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index 6221b90b31d..f4ca3c46ea2 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -7,11 +7,11 @@ LL | fn how_are_you(&self -> Empty { | | help: `)` may belong here | unclosed delimiter -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `)` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `)` --> $DIR/issue-58856-2.rs:11:1 | LL | } - | - expected one of 11 possible tokens + | - expected one of 12 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index b2beb73503b..bab50a53b1a 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,7 +4,7 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `;` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `;` --> $DIR/issue-60075.rs:6:11 | LL | fn qux() -> Option { diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs new file mode 100644 index 00000000000..cf3debd77cb --- /dev/null +++ b/src/test/ui/parser/assoc-static-semantic-fail.rs @@ -0,0 +1,43 @@ +// Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item. + +#![feature(specialization)] + +fn main() {} + +struct S; +impl S { + static IA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static IB: u8; + //~^ ERROR associated `static` items are not allowed + default static IC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + pub(crate) default static ID: u8; + //~^ ERROR associated `static` items are not allowed +} + +trait T { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + //~| ERROR `default` is only allowed on items in + pub(crate) default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR `default` is only allowed on items in + //~| ERROR unnecessary visibility qualifier +} + +impl T for S { + static TA: u8 = 0; + //~^ ERROR associated `static` items are not allowed + static TB: u8; + //~^ ERROR associated `static` items are not allowed + default static TC: u8 = 0; + //~^ ERROR associated `static` items are not allowed + pub default static TD: u8; + //~^ ERROR associated `static` items are not allowed + //~| ERROR unnecessary visibility qualifier +} diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr new file mode 100644 index 00000000000..d5a02c9bebc --- /dev/null +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -0,0 +1,99 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:9:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:11:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:13:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:15:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:20:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:22:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:24:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:24:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:34:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:36:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:38:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:40:5 + | +LL | pub default static TD: u8; + | ^^^ `pub` not permitted here because it's implied + +error: associated `static` items are not allowed + --> $DIR/assoc-static-semantic-fail.rs:40:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 16 previous errors + +For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/assoc-static-syntactic-pass.rs b/src/test/ui/parser/assoc-static-syntactic-pass.rs new file mode 100644 index 00000000000..7f5b9f79335 --- /dev/null +++ b/src/test/ui/parser/assoc-static-syntactic-pass.rs @@ -0,0 +1,29 @@ +// Syntactically, we do allow e.g., `static X: u8 = 0;` as an associated item. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +impl S { + static IA: u8 = 0; + static IB: u8; + default static IC: u8 = 0; + pub(crate) default static ID: u8; +} + +#[cfg(FALSE)] +trait T { + static TA: u8 = 0; + static TB: u8; + default static TC: u8 = 0; + pub(crate) default static TD: u8; +} + +#[cfg(FALSE)] +impl T for S { + static TA: u8 = 0; + static TB: u8; + default static TC: u8 = 0; + pub default static TD: u8; +} diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index 25c1efe35ae..d25828da0b9 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, `}`, or identifier, found `...` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `...` --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 11 possible tokens + | ^^^ expected one of 12 possible tokens error: aborting due to previous error diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index 327bc65818f..a91ef6c67e8 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,8 +1,8 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `type`, `unsafe`, or identifier, found `}` +error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `static`, `type`, `unsafe`, or identifier, found `}` --> $DIR/issue-41155.rs:5:1 | LL | pub - | - expected one of 9 possible tokens + | - expected one of 10 possible tokens LL | } | ^ unexpected token diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index 9d05e85bcc0..c76b096a1eb 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,8 +1,8 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `type`, `unsafe`, or identifier, found `2` +error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, or identifier, found `2` --> $DIR/trait-non-item-macros.rs:2:19 | LL | ($a:expr) => ($a) - | ^^ expected one of 10 possible tokens + | ^^ expected one of 11 possible tokens ... LL | bah!(2); | -------- in this macro invocation diff --git a/src/test/ui/parser/removed-syntax-static-fn.rs b/src/test/ui/parser/removed-syntax-static-fn.rs index 9e12222f3fd..cd643b874db 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.rs +++ b/src/test/ui/parser/removed-syntax-static-fn.rs @@ -1,8 +1,10 @@ struct S; impl S { - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration static fn f() {} + //~^ ERROR expected identifier, found keyword `fn` + //~| ERROR expected one of `:`, `;`, or `=` + //~| ERROR missing type for `static` item } fn main() {} diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index 5edf88026fb..dc5625bdade 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -1,11 +1,20 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration - --> $DIR/removed-syntax-static-fn.rs:3:9 +error: expected identifier, found keyword `fn` + --> $DIR/removed-syntax-static-fn.rs:4:12 | -LL | impl S { - | _________^ -LL | | -LL | | static fn f() {} - | |____^ missing `fn`, `type`, or `const` +LL | static fn f() {} + | ^^ expected identifier, found keyword -error: aborting due to previous error +error: expected one of `:`, `;`, or `=`, found `f` + --> $DIR/removed-syntax-static-fn.rs:4:15 + | +LL | static fn f() {} + | ^ expected one of `:`, `;`, or `=` + +error: missing type for `static` item + --> $DIR/removed-syntax-static-fn.rs:4:12 + | +LL | static fn f() {} + | ^^ help: provide a type for the item: `r#fn: ` + +error: aborting due to 3 previous errors From 35884fe16889b39d4be43cf8effc3bdf843c6f12 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 02:23:10 +0100 Subject: [PATCH 0220/1250] parse extern consts --- src/librustc_ast_lowering/item.rs | 5 ++++ src/librustc_ast_passes/ast_validation.rs | 17 ++++++++++++ src/librustc_ast_passes/feature_gate.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 3 +++ src/librustc_parse/parser/item.rs | 27 +++++-------------- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/late.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/sig.rs | 1 + src/libsyntax/ast.rs | 4 +++ src/libsyntax/mut_visit.rs | 2 +- src/libsyntax/visit.rs | 3 ++- src/test/ui/extern/extern-const.stderr | 10 +++++-- .../ui/parser/foreign-const-semantic-fail.rs | 8 ++++++ .../parser/foreign-const-semantic-fail.stderr | 27 +++++++++++++++++++ .../ui/parser/foreign-const-syntactic-pass.rs | 11 ++++++++ .../ui/parser/removed-syntax-extern-const.rs | 6 ----- .../parser/removed-syntax-extern-const.stderr | 8 ------ 19 files changed, 98 insertions(+), 44 deletions(-) create mode 100644 src/test/ui/parser/foreign-const-semantic-fail.rs create mode 100644 src/test/ui/parser/foreign-const-semantic-fail.stderr create mode 100644 src/test/ui/parser/foreign-const-syntactic-pass.rs delete mode 100644 src/test/ui/parser/removed-syntax-extern-const.rs delete mode 100644 src/test/ui/parser/removed-syntax-extern-const.stderr diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index b465fd79c8f..e0db8606bc2 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -683,6 +683,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } + ForeignItemKind::Const(ref t, _) => { + // For recovery purposes. + let ty = self.lower_ty(t, ImplTraitContext::disallowed()); + hir::ForeignItemKind::Static(ty, Mutability::Not) + } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 72cffdd750a..8efd50ad098 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -533,6 +533,20 @@ impl<'a> AstValidator<'a> { } } + fn error_foreign_const(&self, ident: Ident, span: Span) { + self.err_handler() + .struct_span_err(ident.span, "extern items cannot be `const`") + .span_suggestion( + span.with_hi(ident.span.lo()), + "try using a static value", + "static ".to_string(), + Applicability::MachineApplicable, + ) + .span_label(self.current_extern_span(), "in this `extern` block") + .note(MORE_EXTERN) + .emit(); + } + /// Reject C-varadic type unless the function is foreign, /// or free and `unsafe extern "C"` semantically. fn check_c_varadic_type(&self, fk: FnKind<'a>) { @@ -989,6 +1003,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); } + ForeignItemKind::Const(..) => { + self.error_foreign_const(fi.ident, fi.span); + } ForeignItemKind::Macro(..) => {} } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index c543f7095b9..d4de2c93758 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -400,7 +400,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } - ast::ForeignItemKind::Macro(..) => {} + ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {} } visit::walk_foreign_item(self, i) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index ee1a829da1a..410600e4957 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1023,6 +1023,9 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(sig, gen, body) => { self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); } + ast::ForeignItemKind::Const(ty, body) => { + self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); + } ast::ForeignItemKind::Static(ty, mutbl, body) => { self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis); } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 9b7728f27d0..5fcd72090ec 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -880,19 +880,12 @@ impl<'a> Parser<'a> { } else if self.is_static_global() { // FOREIGN STATIC ITEM self.bump(); // `static` - self.parse_item_foreign_static()? - } else if self.token.is_keyword(kw::Const) { - // Treat `const` as `static` for error recovery, but don't add it to expected tokens. - self.bump(); // `const` - self.struct_span_err(self.prev_span, "extern items cannot be `const`") - .span_suggestion( - self.prev_span, - "try using a static value", - "static".to_owned(), - Applicability::MachineApplicable, - ) - .emit(); - self.parse_item_foreign_static()? + let mutbl = self.parse_mutability(); + let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; + (ident, ForeignItemKind::Static(ty, mutbl, expr)) + } else if self.eat_keyword(kw::Const) { + let (ident, ty, expr) = self.parse_item_const_common(None)?; + (ident, ForeignItemKind::Const(ty, expr)) } else if self.isnt_macro_invocation() { return Err(self.missing_assoc_item_kind_err("extern", self.prev_span)); } else if self.token.is_path_start() { @@ -906,14 +899,6 @@ impl<'a> Parser<'a> { Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) } - /// Parses a static item from a foreign module. - /// Assumes that the `static` keyword is already parsed. - fn parse_item_foreign_static(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { - let mutbl = self.parse_mutability(); - let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - Ok((ident, ForeignItemKind::Static(ty, mutbl, expr))) - } - /// Parses a type from a foreign module. fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { let (ident, kind) = self.parse_assoc_ty()?; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 7c541928e6f..1f622b80e8e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -826,7 +826,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Fn(..) => { (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Static(..) => { + ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => { (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS) } ForeignItemKind::TyAlias(..) => { diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 7b445fcc035..68559c0446a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -443,7 +443,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Static(..) => { + ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => { self.with_item_rib(HasGenericParams::No, |this| { visit::walk_foreign_item(this, foreign_item); }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 001f2f09854..6a3abf4fbf5 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1534,7 +1534,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 6bb2bf4c1e9..d244370ae2c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -151,7 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 8fba3109f21..3c68124ad40 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -792,6 +792,7 @@ impl Sig for ast::ForeignItem { Ok(Signature { text: text, defs: defs, refs: vec![] }) } + ast::ForeignItemKind::Const(..) => Err("foreign const"), ast::ForeignItemKind::Macro(..) => Err("macro"), } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ca39fbd6c5d..5041d43b16c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2605,6 +2605,9 @@ pub type ForeignItem = Item; /// An item within an `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { + /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// If `def` is parsed, then the constant is provided, and otherwise required. + Const(P, Option>), /// A static item (`static FOO: u8`). Static(P, Mutability, Option>), /// A function. @@ -2619,6 +2622,7 @@ impl ForeignItemKind { pub fn descriptive_variant(&self) -> &str { match *self { ForeignItemKind::Fn(..) => "foreign function", + ForeignItemKind::Const(..) => "foreign const item", ForeignItemKind::Static(..) => "foreign static item", ForeignItemKind::TyAlias(..) => "foreign type", ForeignItemKind::Macro(..) => "macro in foreign module", diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 91db6158689..ffc42340dba 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -1046,7 +1046,7 @@ pub fn noop_flat_map_foreign_item( visitor.visit_generics(generics); visit_opt(body, |body| visitor.visit_block(body)); } - ForeignItemKind::Static(ty, _, body) => { + ForeignItemKind::Const(ty, body) | ForeignItemKind::Static(ty, _, body) => { visitor.visit_ty(ty); visit_opt(body, |body| visitor.visit_expr(body)); } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index f5763ecf573..5a21eb55528 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -534,7 +534,8 @@ pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignI let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id); } - ForeignItemKind::Static(ref typ, _, ref body) => { + ForeignItemKind::Const(ref typ, ref body) + | ForeignItemKind::Static(ref typ, _, ref body) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, body); } diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 258202b6903..97e11381c6f 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,8 +1,14 @@ error: extern items cannot be `const` - --> $DIR/extern-const.rs:16:5 + --> $DIR/extern-const.rs:16:11 | +LL | extern "C" { + | ---------- in this `extern` block LL | const rust_dbg_static_mut: libc::c_int; - | ^^^^^ help: try using a static value: `static` + | ------^^^^^^^^^^^^^^^^^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html error: aborting due to previous error diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs new file mode 100644 index 00000000000..d28b6414282 --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.rs @@ -0,0 +1,8 @@ +fn main() {} + +extern { + const A: isize; + //~^ ERROR extern items cannot be `const` + const B: isize = 42; + //~^ ERROR extern items cannot be `const` +} diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr new file mode 100644 index 00000000000..799a795c593 --- /dev/null +++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr @@ -0,0 +1,27 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:4:11 + | +LL | extern { + | ------ in this `extern` block +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | extern { + | ------ in this `extern` block +... +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-const-syntactic-pass.rs b/src/test/ui/parser/foreign-const-syntactic-pass.rs new file mode 100644 index 00000000000..bacef8e71d6 --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-pass.rs @@ -0,0 +1,11 @@ +// Syntactically, a `const` item inside an `extern { ... }` block is allowed. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +extern { + const A: isize; + const B: isize = 42; +} diff --git a/src/test/ui/parser/removed-syntax-extern-const.rs b/src/test/ui/parser/removed-syntax-extern-const.rs deleted file mode 100644 index 71c22e62f8e..00000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.rs +++ /dev/null @@ -1,6 +0,0 @@ -extern { - const i: isize; - //~^ ERROR extern items cannot be `const` -} - -fn main() {} diff --git a/src/test/ui/parser/removed-syntax-extern-const.stderr b/src/test/ui/parser/removed-syntax-extern-const.stderr deleted file mode 100644 index 2bccbd91452..00000000000 --- a/src/test/ui/parser/removed-syntax-extern-const.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: extern items cannot be `const` - --> $DIR/removed-syntax-extern-const.rs:2:5 - | -LL | const i: isize; - | ^^^^^ help: try using a static value: `static` - -error: aborting due to previous error - From 91110fda27b2d227a5c5b20e3be01a47f7e39910 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 02:34:19 +0100 Subject: [PATCH 0221/1250] ast: make ForeignItemKind an alias of AssocItemKind --- src/libsyntax/ast.rs | 33 +++------------------------------ 1 file changed, 3 insertions(+), 30 deletions(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 5041d43b16c..a931d8c27ba 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2600,35 +2600,8 @@ impl ItemKind { } } -pub type ForeignItem = Item; - -/// An item within an `extern` block. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum ForeignItemKind { - /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. - /// If `def` is parsed, then the constant is provided, and otherwise required. - Const(P, Option>), - /// A static item (`static FOO: u8`). - Static(P, Mutability, Option>), - /// A function. - Fn(FnSig, Generics, Option>), - /// A type. - TyAlias(Generics, GenericBounds, Option>), - /// A macro expanding to an item. - Macro(Mac), -} - -impl ForeignItemKind { - pub fn descriptive_variant(&self) -> &str { - match *self { - ForeignItemKind::Fn(..) => "foreign function", - ForeignItemKind::Const(..) => "foreign const item", - ForeignItemKind::Static(..) => "foreign static item", - ForeignItemKind::TyAlias(..) => "foreign type", - ForeignItemKind::Macro(..) => "macro in foreign module", - } - } -} +pub type ForeignItem = Item; +pub type ForeignItemKind = AssocItemKind; /// Represents associated items. /// These include items in `impl` and `trait` definitions. @@ -2646,7 +2619,7 @@ pub struct AssocItem { pub tokens: Option, } -/// Represents various kinds of content within an `impl`. +/// Represents non-free item kinds. /// /// The term "provided" in the variants below refers to the item having a default /// definition / body. Meanwhile, a "required" item lacks a definition / body. From 0e0c0286a2dfe62ca3093e68a77931bff8896b01 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 17:35:29 +0100 Subject: [PATCH 0222/1250] fuse extern & associated item parsing up to defaultness --- src/librustc_parse/parser/item.rs | 116 ++++++------------ src/test/ui/did_you_mean/issue-40006.rs | 4 +- src/test/ui/did_you_mean/issue-40006.stderr | 24 ++-- src/test/ui/macros/issue-54441.rs | 2 +- src/test/ui/macros/issue-54441.stderr | 4 +- src/test/ui/parser/default.rs | 2 +- src/test/ui/parser/default.stderr | 4 +- src/test/ui/parser/duplicate-visibility.rs | 2 +- .../ui/parser/duplicate-visibility.stderr | 4 +- src/test/ui/parser/extern-no-fn.rs | 3 +- src/test/ui/parser/extern-no-fn.stderr | 5 +- src/test/ui/parser/issue-19398.rs | 2 +- src/test/ui/parser/issue-19398.stderr | 4 +- src/test/ui/parser/issue-21153.rs | 3 +- src/test/ui/parser/issue-21153.stderr | 5 +- .../missing-close-brace-in-impl-trait.rs | 2 +- .../missing-close-brace-in-impl-trait.stderr | 4 +- .../missing-close-brace-in-trait.rs | 2 +- .../missing-close-brace-in-trait.stderr | 4 +- 19 files changed, 81 insertions(+), 115 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 5fcd72090ec..20d6182ddc1 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -13,7 +13,7 @@ use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use syntax::ast::{FnHeader, ForeignItem, ForeignItemKind, Mutability, Visibility, VisibilityKind}; +use syntax::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; use syntax::ptr::P; use syntax::token; use syntax::tokenstream::{DelimSpan, TokenStream, TokenTree}; @@ -333,29 +333,19 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - fn missing_assoc_item_kind_err( - &self, - item_type: &str, - prev_span: Span, - ) -> DiagnosticBuilder<'a> { - let expected_kinds = if item_type == "extern" { - "missing `fn`, `type`, or `static`" - } else { - "missing `fn`, `type`, or `const`" - }; - - // Given this code `path(`, it seems like this is not - // setting the visibility of a macro invocation, but rather - // a mistyped method declaration. - // Create a diagnostic pointing out that `fn` is missing. - // - // x | pub path(&self) { - // | ^ missing `fn`, `type`, or `const` - // pub path( - // ^^ `sp` below will point to this + /// Given this code `path(`, it seems like this is not + /// setting the visibility of a macro invocation, + /// but rather a mistyped method declaration. + /// Create a diagnostic pointing out that `fn` is missing. + /// + /// ``` + /// x | pub path(&self) { + /// | ^ missing `fn`, `type`, `const`, or `static` + /// ``` + fn missing_nested_item_kind_err(&self, prev_span: Span) -> DiagnosticBuilder<'a> { let sp = prev_span.between(self.token.span); - let mut err = self - .struct_span_err(sp, &format!("{} for {}-item declaration", expected_kinds, item_type)); + let expected_kinds = "missing `fn`, `type`, `const`, or `static`"; + let mut err = self.struct_span_err(sp, &format!("{} for item declaration", expected_kinds)); err.span_label(sp, expected_kinds); err } @@ -639,7 +629,7 @@ impl<'a> Parser<'a> { fn parse_assoc_item( &mut self, at_end: &mut bool, - req_name: fn(&token::Token) -> bool, + req_name: ReqName, ) -> PResult<'a, P> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; @@ -660,39 +650,47 @@ impl<'a> Parser<'a> { &mut self, at_end: &mut bool, mut attrs: Vec, - req_name: fn(&token::Token) -> bool, + req_name: ReqName, ) -> PResult<'a, AssocItem> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let defaultness = self.parse_defaultness(); + let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, req_name, &vis)?; + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) + } - let (ident, kind) = if self.eat_keyword(kw::Type) { - self.parse_assoc_ty()? + fn parse_assoc_item_kind( + &mut self, + at_end: &mut bool, + attrs: &mut Vec, + req_name: ReqName, + vis: &Visibility, + ) -> PResult<'a, (Ident, AssocItemKind)> { + if self.eat_keyword(kw::Type) { + self.parse_assoc_ty() } else if self.check_fn_front_matter() { - let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, req_name)?; - (ident, AssocItemKind::Fn(sig, generics, body)) + let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?; + Ok((ident, AssocItemKind::Fn(sig, generics, body))) } else if self.is_static_global() { self.bump(); // `static` let mutbl = self.parse_mutability(); let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - (ident, AssocItemKind::Static(ty, mutbl, expr)) + Ok((ident, AssocItemKind::Static(ty, mutbl, expr))) } else if self.eat_keyword(kw::Const) { let (ident, ty, expr) = self.parse_item_const_common(None)?; - (ident, AssocItemKind::Const(ty, expr)) + Ok((ident, AssocItemKind::Const(ty, expr))) } else if self.isnt_macro_invocation() { - return Err(self.missing_assoc_item_kind_err("associated", self.prev_span)); + Err(self.missing_nested_item_kind_err(self.prev_span)) } else if self.token.is_path_start() { let mac = self.parse_item_macro(&vis)?; *at_end = true; - (Ident::invalid(), AssocItemKind::Macro(mac)) + Ok((Ident::invalid(), AssocItemKind::Macro(mac))) } else { - self.recover_attrs_no_item(&attrs)?; - self.unexpected()? - }; - - let span = lo.to(self.prev_span); - let id = DUMMY_NODE_ID; - Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) + self.recover_attrs_no_item(attrs)?; + self.unexpected() + } } /// Parses the following grammar: @@ -869,46 +867,10 @@ impl<'a> Parser<'a> { let mut attrs = self.parse_outer_attributes()?; let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - - let (ident, kind) = if self.eat_keyword(kw::Type) { - // FOREIGN TYPE ITEM - self.parse_item_foreign_type()? - } else if self.check_fn_front_matter() { - // FOREIGN FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(at_end, &mut attrs, |_| true)?; - (ident, ForeignItemKind::Fn(sig, generics, body)) - } else if self.is_static_global() { - // FOREIGN STATIC ITEM - self.bump(); // `static` - let mutbl = self.parse_mutability(); - let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - (ident, ForeignItemKind::Static(ty, mutbl, expr)) - } else if self.eat_keyword(kw::Const) { - let (ident, ty, expr) = self.parse_item_const_common(None)?; - (ident, ForeignItemKind::Const(ty, expr)) - } else if self.isnt_macro_invocation() { - return Err(self.missing_assoc_item_kind_err("extern", self.prev_span)); - } else if self.token.is_path_start() { - let mac = self.parse_item_macro(&vis)?; - *at_end = true; - (Ident::invalid(), ForeignItemKind::Macro(mac)) - } else { - self.recover_attrs_no_item(&attrs)?; - self.unexpected()? - }; + let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?; Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) } - /// Parses a type from a foreign module. - fn parse_item_foreign_type(&mut self) -> PResult<'a, (Ident, ForeignItemKind)> { - let (ident, kind) = self.parse_assoc_ty()?; - let kind = match kind { - AssocItemKind::TyAlias(g, b, d) => ForeignItemKind::TyAlias(g, b, d), - _ => unreachable!(), - }; - Ok((ident, kind)) - } - fn is_static_global(&mut self) -> bool { if self.check_keyword(kw::Static) { // Check if this could be a closure. diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index 60633c6930c..2ed682cea95 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -18,10 +18,10 @@ trait A { //~ ERROR missing trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration +trait C { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration L = M; } -trait D { //~ ERROR missing `fn`, `type`, or `const` for associated-item declaration +trait D { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration Z = { 2 + 3 }; } trait E { diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 072e61f6a3c..119e30a3e0f 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,26 +1,26 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:1:13 | LL | impl dyn A { | _____________^ LL | | Y - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:7:10 | LL | trait X { | __________^ LL | | X() {} - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:15:10 | LL | trait A { | __________^ LL | | X() {} - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: expected `[`, found `#` --> $DIR/issue-40006.rs:19:17 @@ -28,21 +28,21 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:21:10 | LL | trait C { | __________^ LL | | L = M; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:24:10 | LL | trait D { | __________^ LL | | Z = { 2 + 3 }; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: expected one of `!` or `::`, found `(` --> $DIR/issue-40006.rs:28:9 @@ -50,11 +50,11 @@ error: expected one of `!` or `::`, found `(` LL | ::Y (); | ^ expected one of `!` or `::` -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-40006.rs:32:8 | LL | pub hello_method(&self) { - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` error[E0599]: no method named `hello_method` found for struct `S` in the current scope --> $DIR/issue-40006.rs:38:7 diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index a70163df1cb..5570f081b15 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,5 +1,5 @@ macro_rules! m { - //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration () => { let }; diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index 761e7aec723..5857aacb431 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,11 +1,11 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-54441.rs:1:1 | LL | / macro_rules! m { LL | | LL | | () => { LL | | let - | |________^ missing `fn`, `type`, or `static` + | |________^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 65ecb1ebbe9..50952eef22f 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -20,7 +20,7 @@ impl Foo for u16 { impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` default pub fn foo() -> T { T::default() } - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index ede9e471518..07b051ece2b 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,8 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/default.rs:22:12 | LL | default pub fn foo() -> T { T::default() } - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 1d271fa64b0..f6e7f7e6abe 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -2,5 +2,5 @@ fn main() {} extern { pub pub fn foo(); - //~^ ERROR missing `fn`, `type`, or `static` for extern-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 36a3a1ed5a0..398ba65c9e1 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/duplicate-visibility.rs:4:8 | LL | pub pub fn foo(); - | ^ missing `fn`, `type`, or `static` + | ^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs index c37ddd69ce5..dc47f741073 100644 --- a/src/test/ui/parser/extern-no-fn.rs +++ b/src/test/ui/parser/extern-no-fn.rs @@ -1,4 +1,5 @@ -extern { //~ ERROR missing `fn`, `type`, or `static` for extern-item declaration +extern { +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration f(); } diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr index d2d5e3c4687..8d55eefc8d0 100644 --- a/src/test/ui/parser/extern-no-fn.stderr +++ b/src/test/ui/parser/extern-no-fn.stderr @@ -1,10 +1,11 @@ -error: missing `fn`, `type`, or `static` for extern-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/extern-no-fn.rs:1:9 | LL | extern { | _________^ +LL | | LL | | f(); - | |____^ missing `fn`, `type`, or `static` + | |____^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 982a6be23ac..014c930ef82 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,5 +1,5 @@ trait T { - //~^ ERROR missing `fn`, `type`, or `const` for associated-item declaration + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration extern "Rust" unsafe fn foo(); } diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index 2bd6ac3a4b3..b38b39f9bd9 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,11 +1,11 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-19398.rs:1:10 | LL | trait T { | __________^ LL | | LL | | extern "Rust" unsafe fn foo(); - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs index 46cd45f28b4..4fe05e6f041 100644 --- a/src/test/ui/parser/issue-21153.rs +++ b/src/test/ui/parser/issue-21153.rs @@ -1,4 +1,5 @@ -trait MyTrait: Iterator { //~ ERROR missing `fn`, `type`, or `const` +trait MyTrait: Iterator { + //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration Item = T; } diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index 6e20a9ce3c4..e9824bd7290 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,10 +1,11 @@ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/issue-21153.rs:1:29 | LL | trait MyTrait: Iterator { | _____________________________^ +LL | | LL | | Item = T; - | |____^ missing `fn`, `type`, or `const` + | |____^ missing `fn`, `type`, `const`, or `static` error: aborting due to previous error diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index 592215030f5..748db8983b5 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -3,7 +3,7 @@ fn main() {} impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} -//~^ ERROR missing `fn`, `type`, or `const` +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration trait T { fn foo(&self); diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index 1ec54525105..240be39eace 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -7,7 +7,7 @@ LL | impl T for () { LL | | ^ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 | LL | fn foo(&self) {} @@ -15,7 +15,7 @@ LL | fn foo(&self) {} LL | | LL | | LL | | trait T { - | |_ missing `fn`, `type`, or `const` + | |_ missing `fn`, `type`, `const`, or `static` error[E0405]: cannot find trait `T` in this scope --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index 077e3347194..4e8cc6489bc 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -3,7 +3,7 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR missing `fn`, `type`, or `const` +//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration impl T for Bar { fn foo(&self) {} diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 1bb153c461d..54afad5755b 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,11 +7,11 @@ LL | trait T { LL | fn main() {} | ^ -error: missing `fn`, `type`, or `const` for associated-item declaration +error: missing `fn`, `type`, `const`, or `static` for item declaration --> $DIR/missing-close-brace-in-trait.rs:5:11 | LL | pub(crate) struct Bar(); - | ^ missing `fn`, `type`, or `const` + | ^ missing `fn`, `type`, `const`, or `static` error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` --> $DIR/missing-close-brace-in-trait.rs:1:1 From cf87edfdc5f2b44c7e379270a2b8b92464cb7cdb Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 18:28:47 +0100 Subject: [PATCH 0223/1250] pprust: unify extern & associated item printing --- src/librustc_ast_pretty/pprust.rs | 62 ++++++++++++++----------------- 1 file changed, 27 insertions(+), 35 deletions(-) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 410600e4957..0eea64dfe73 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -912,7 +912,7 @@ impl<'a> State<'a> { } } - crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[ast::Attribute]) { + crate fn print_foreign_mod(&mut self, nmod: &ast::ForeignMod, attrs: &[Attribute]) { self.print_inner_attributes(attrs); for item in &nmod.items { self.print_foreign_item(item); @@ -1016,21 +1016,37 @@ impl<'a> State<'a> { } crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) { + let ast::ForeignItem { id, span, ident, attrs, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, ast::Defaultness::Final, kind, vis); + } + + fn print_nested_item_kind( + &mut self, + id: ast::NodeId, + span: Span, + ident: ast::Ident, + attrs: &[Attribute], + defaultness: ast::Defaultness, + kind: &ast::AssocItemKind, + vis: &ast::Visibility, + ) { + self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); - self.maybe_print_comment(item.span.lo()); - self.print_outer_attributes(&item.attrs); - match &item.kind { + self.maybe_print_comment(span.lo()); + self.print_outer_attributes(attrs); + self.print_defaultness(defaultness); + match kind { ast::ForeignItemKind::Fn(sig, gen, body) => { - self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); + self.print_fn_full(sig, ident, gen, vis, body.as_deref(), attrs); } ast::ForeignItemKind::Const(ty, body) => { - self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); + self.print_item_const(ident, None, ty, body.as_deref(), vis); } ast::ForeignItemKind::Static(ty, mutbl, body) => { - self.print_item_const(item.ident, Some(*mutbl), ty, body.as_deref(), &item.vis); + self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis); } ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { - self.print_associated_type(item.ident, generics, bounds, ty.as_deref()); + self.print_associated_type(ident, generics, bounds, ty.as_deref()); } ast::ForeignItemKind::Macro(m) => { self.print_mac(m); @@ -1039,6 +1055,7 @@ impl<'a> State<'a> { } } } + self.ann.post(self, AnnNode::SubItem(id)) } fn print_item_const( @@ -1438,33 +1455,8 @@ impl<'a> State<'a> { } crate fn print_assoc_item(&mut self, item: &ast::AssocItem) { - self.ann.pre(self, AnnNode::SubItem(item.id)); - self.hardbreak_if_not_bol(); - self.maybe_print_comment(item.span.lo()); - self.print_outer_attributes(&item.attrs); - self.print_defaultness(item.defaultness); - match &item.kind { - ast::AssocItemKind::Static(ty, mutbl, expr) => { - self.print_item_const(item.ident, Some(*mutbl), ty, expr.as_deref(), &item.vis); - } - ast::AssocItemKind::Const(ty, expr) => { - self.print_item_const(item.ident, None, ty, expr.as_deref(), &item.vis); - } - ast::AssocItemKind::Fn(sig, generics, body) => { - let body = body.as_deref(); - self.print_fn_full(sig, item.ident, generics, &item.vis, body, &item.attrs); - } - ast::AssocItemKind::TyAlias(generics, bounds, ty) => { - self.print_associated_type(item.ident, generics, bounds, ty.as_deref()); - } - ast::AssocItemKind::Macro(mac) => { - self.print_mac(mac); - if mac.args.need_semicolon() { - self.s.word(";"); - } - } - } - self.ann.post(self, AnnNode::SubItem(item.id)) + let ast::AssocItem { id, span, ident, attrs, defaultness, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis); } crate fn print_stmt(&mut self, st: &ast::Stmt) { From 5abedd81e04dc1b76db423ca351ef5d3056a6f97 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 18:42:43 +0100 Subject: [PATCH 0224/1250] visit: unify extern & assoc item visiting --- src/libsyntax/mut_visit.rs | 39 +++++++++---------------- src/libsyntax/visit.rs | 59 +++++++++++++++++--------------------- 2 files changed, 40 insertions(+), 58 deletions(-) diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index ffc42340dba..1fa6cce2c62 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -949,6 +949,19 @@ pub fn noop_flat_map_assoc_item( ) -> SmallVec<[P; 1]> { let AssocItem { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut(); + walk_nested_item(visitor, id, span, ident, vis, attrs, kind); + smallvec![item] +} + +pub fn walk_nested_item( + visitor: &mut impl MutVisitor, + id: &mut NodeId, + span: &mut Span, + ident: &mut Ident, + vis: &mut Visibility, + attrs: &mut Vec, + kind: &mut AssocItemKind, +) { visitor.visit_id(id); visitor.visit_ident(ident); visitor.visit_vis(vis); @@ -971,8 +984,6 @@ pub fn noop_flat_map_assoc_item( AssocItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); - - smallvec![item] } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { @@ -1038,29 +1049,7 @@ pub fn noop_flat_map_foreign_item( visitor: &mut T, ) -> SmallVec<[P; 1]> { let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); - visitor.visit_ident(ident); - visit_attrs(attrs, visitor); - match kind { - ForeignItemKind::Fn(sig, generics, body) => { - visit_fn_sig(sig, visitor); - visitor.visit_generics(generics); - visit_opt(body, |body| visitor.visit_block(body)); - } - ForeignItemKind::Const(ty, body) | ForeignItemKind::Static(ty, _, body) => { - visitor.visit_ty(ty); - visit_opt(body, |body| visitor.visit_expr(body)); - } - ForeignItemKind::TyAlias(generics, bounds, ty) => { - visitor.visit_generics(generics); - visit_bounds(bounds, visitor); - visit_opt(ty, |ty| visitor.visit_ty(ty)); - } - ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), - } - visitor.visit_id(id); - visitor.visit_span(span); - visitor.visit_vis(vis); - + walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 5a21eb55528..448ed0ba3de 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -525,29 +525,8 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); - - match item.kind { - ForeignItemKind::Fn(ref sig, ref generics, ref body) => { - visitor.visit_generics(generics); - let kind = FnKind::Fn(FnCtxt::Foreign, item.ident, sig, &item.vis, body.as_deref()); - visitor.visit_fn(kind, item.span, item.id); - } - ForeignItemKind::Const(ref typ, ref body) - | ForeignItemKind::Static(ref typ, _, ref body) => { - visitor.visit_ty(typ); - walk_list!(visitor, visit_expr, body); - } - ForeignItemKind::TyAlias(ref generics, ref bounds, ref ty) => { - visitor.visit_generics(generics); - walk_list!(visitor, visit_param_bound, bounds); - walk_list!(visitor, visit_ty, ty); - } - ForeignItemKind::Macro(ref mac) => visitor.visit_mac(mac), - } - - walk_list!(visitor, visit_attribute, &item.attrs); + let ForeignItem { id, span, ident, vis, attrs, kind, tokens: _ } = item; + walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign); } pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { @@ -630,25 +609,39 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa } pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { - visitor.visit_vis(&item.vis); - visitor.visit_ident(item.ident); - walk_list!(visitor, visit_attribute, &item.attrs); - match item.kind { - AssocItemKind::Const(ref ty, ref expr) | AssocItemKind::Static(ref ty, _, ref expr) => { + let AssocItem { id, span, ident, vis, attrs, kind, tokens: _, defaultness: _ } = item; + walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt)); +} + +fn walk_nested_item<'a, V: Visitor<'a>>( + visitor: &mut V, + id: NodeId, + span: Span, + ident: Ident, + vis: &'a Visibility, + attrs: &'a [Attribute], + kind: &'a AssocItemKind, + ctxt: FnCtxt, +) { + visitor.visit_vis(vis); + visitor.visit_ident(ident); + walk_list!(visitor, visit_attribute, attrs); + match kind { + AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(ref sig, ref generics, ref body) => { + AssocItemKind::Fn(sig, generics, body) => { visitor.visit_generics(generics); - let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), item.ident, sig, &item.vis, body.as_deref()); - visitor.visit_fn(kind, item.span, item.id); + let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref()); + visitor.visit_fn(kind, span, id); } - AssocItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + AssocItemKind::TyAlias(generics, bounds, ty) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); } - AssocItemKind::Macro(ref mac) => { + AssocItemKind::Macro(mac) => { visitor.visit_mac(mac); } } From b6aaacd9914a98d91f0abb8d727bbba14d82957c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 21:37:53 +0100 Subject: [PATCH 0225/1250] fix codegen tests --- src/test/codegen/issue-56927.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs index 0544ff86aac..5ba17d3499b 100644 --- a/src/test/codegen/issue-56927.rs +++ b/src/test/codegen/issue-56927.rs @@ -23,7 +23,7 @@ pub fn test1(s: &mut S) { // CHECK-LABEL: @test2 // CHECK: store i32 4, i32* %{{.+}}, align 4 -#[allow(const_err)] +#[allow(panic)] #[no_mangle] pub fn test2(s: &mut S) { s.arr[usize::MAX / 4 + 1] = 4; From 51a16e574aa1b20dbaa94436065ce80f3ba725d1 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 3 Feb 2020 18:34:36 -0500 Subject: [PATCH 0226/1250] Record proc macro harness order for use during metadata deserialization Fixes #68690 When we generate the proc macro harness, we now explicitly recorder the order in which we generate entries. We then use this ordering data to deserialize the correct proc-macro-data from the crate metadata. --- src/librustc/hir/map/collector.rs | 1 + src/librustc_ast_lowering/lib.rs | 2 + .../proc_macro_harness.rs | 61 +++++++++++++------ src/librustc_hir/hir.rs | 3 + src/librustc_metadata/rmeta/decoder.rs | 4 -- src/librustc_metadata/rmeta/encoder.rs | 9 +-- src/librustc_parse/parser/module.rs | 2 + src/libsyntax/ast.rs | 1 + src/libsyntax/mut_visit.rs | 6 +- .../inline_cross/auxiliary/proc_macro.rs | 13 ++++ src/test/rustdoc/inline_cross/proc_macro.rs | 8 +++ src/test/ui/ast-json/ast-json-output.stdout | 2 +- 12 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 4c922654e02..bf1fc09649a 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -140,6 +140,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { trait_impls: _, body_ids: _, modules: _, + proc_macros: _, } = *krate; alloc_hir_dep_nodes( diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 99de4b88fd3..30fe7de5df4 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -530,6 +530,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let module = self.lower_mod(&c.module); let attrs = self.lower_attrs(&c.attrs); let body_ids = body_ids(&self.bodies); + let proc_macros = c.proc_macros.iter().map(|id| self.node_id_to_hir_id[*id]).collect(); self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id); @@ -546,6 +547,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { body_ids, trait_impls: self.trait_impls, modules: self.modules, + proc_macros, } } diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index 222456d8fe0..b925cad9fdc 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -8,13 +8,15 @@ use rustc_span::hygiene::AstPass; use rustc_span::symbol::{kw, sym}; use rustc_span::{Span, DUMMY_SP}; use smallvec::smallvec; -use syntax::ast::{self, Ident}; +use std::cell::RefCell; +use syntax::ast::{self, Ident, NodeId}; use syntax::attr; use syntax::expand::is_proc_macro_attr; use syntax::ptr::P; use syntax::visit::{self, Visitor}; struct ProcMacroDerive { + id: NodeId, trait_name: ast::Name, function_name: Ident, span: Span, @@ -27,6 +29,7 @@ enum ProcMacroDefType { } struct ProcMacroDef { + id: NodeId, function_name: Ident, span: Span, def_type: ProcMacroDefType, @@ -69,9 +72,6 @@ pub fn inject( if has_proc_macro_decls || is_proc_macro_crate { visit::walk_crate(&mut collect, &krate); } - // NOTE: If you change the order of macros in this vec - // for any reason, you must also update 'raw_proc_macro' - // in src/librustc_metadata/decoder.rs let macros = collect.macros; if !is_proc_macro_crate { @@ -86,7 +86,8 @@ pub fn inject( return krate; } - krate.module.items.push(mk_decls(&mut cx, ¯os)); + let decls = mk_decls(&mut krate, &mut cx, ¯os); + krate.module.items.push(decls); krate } @@ -181,6 +182,7 @@ impl<'a> CollectProcMacros<'a> { if self.in_root && item.vis.node.is_pub() { self.macros.push(ProcMacro::Derive(ProcMacroDerive { + id: item.id, span: item.span, trait_name: trait_ident.name, function_name: item.ident, @@ -200,6 +202,7 @@ impl<'a> CollectProcMacros<'a> { fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) { if self.in_root && item.vis.node.is_pub() { self.macros.push(ProcMacro::Def(ProcMacroDef { + id: item.id, span: item.span, function_name: item.ident, def_type: ProcMacroDefType::Attr, @@ -218,6 +221,7 @@ impl<'a> CollectProcMacros<'a> { fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) { if self.in_root && item.vis.node.is_pub() { self.macros.push(ProcMacro::Def(ProcMacroDef { + id: item.id, span: item.span, function_name: item.ident, def_type: ProcMacroDefType::Bang, @@ -357,7 +361,15 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { // // ... // ]; // } -fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { +fn mk_decls( + ast_krate: &mut ast::Crate, + cx: &mut ExtCtxt<'_>, + macros: &[ProcMacro], +) -> P { + // We're the ones filling in this Vec, + // so it should be empty to start with + assert!(ast_krate.proc_macros.is_empty()); + let expn_id = cx.resolver.expansion_for_ast_pass( DUMMY_SP, AstPass::ProcMacroHarness, @@ -376,6 +388,12 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { let attr = cx.ident_of("attr", span); let bang = cx.ident_of("bang", span); + let krate_ref = RefCell::new(ast_krate); + + // We add NodeIds to 'krate.proc_macros' in the order + // that we generate expressions. The position of each NodeId + // in the 'proc_macros' Vec corresponds to its position + // in the static array that will be generated let decls = { let local_path = |sp: Span, name| cx.expr_path(cx.path(sp.with_ctxt(span.ctxt()), vec![name])); @@ -385,19 +403,26 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P { macros .iter() .map(|m| match m { - ProcMacro::Derive(cd) => cx.expr_call( - span, - proc_macro_ty_method_path(custom_derive), - vec![ - cx.expr_str(cd.span, cd.trait_name), - cx.expr_vec_slice( - span, - cd.attrs.iter().map(|&s| cx.expr_str(cd.span, s)).collect::>(), - ), - local_path(cd.span, cd.function_name), - ], - ), + ProcMacro::Derive(cd) => { + krate_ref.borrow_mut().proc_macros.push(cd.id); + cx.expr_call( + span, + proc_macro_ty_method_path(custom_derive), + vec![ + cx.expr_str(cd.span, cd.trait_name), + cx.expr_vec_slice( + span, + cd.attrs + .iter() + .map(|&s| cx.expr_str(cd.span, s)) + .collect::>(), + ), + local_path(cd.span, cd.function_name), + ], + ) + } ProcMacro::Def(ca) => { + krate_ref.borrow_mut().proc_macros.push(ca.id); let ident = match ca.def_type { ProcMacroDefType::Attr => attr, ProcMacroDefType::Bang => bang, diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 07a2c482253..f13e2f18604 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -635,6 +635,9 @@ pub struct Crate<'hir> { /// A list of modules written out in the order in which they /// appear in the crate. This includes the main crate module. pub modules: BTreeMap, + /// A list of proc macro HirIds, written out in the order in which + /// they are declared in the static array generated by proc_macro_harness. + pub proc_macros: Vec, } impl Crate<'hir> { diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 58cf142ab3a..01fd637b20e 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -637,10 +637,6 @@ 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'. - // NOTE: If you update the order of macros in 'proc_macro_data' for any reason, - // you must also update src/librustc_builtin_macros/proc_macro_harness.rs - // Failing to do so will result in incorrect data being associated - // with proc macros when deserialized. let pos = self.root.proc_macro_data.unwrap().decode(self).position(|i| i == id).unwrap(); &self.raw_proc_macros.unwrap()[pos] } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 4133047af78..41fc5ed843f 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -34,7 +34,6 @@ use std::path::Path; use std::u32; use syntax::ast; use syntax::attr; -use syntax::expand::is_proc_macro_attr; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; @@ -1328,13 +1327,7 @@ impl EncodeContext<'tcx> { 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 - } - }))) + Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner))) } else { None } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 754923ae55e..9dba813c9a7 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -35,6 +35,8 @@ impl<'a> Parser<'a> { attrs: self.parse_inner_attributes()?, module: self.parse_mod_items(&token::Eof, lo)?, span: lo.to(self.token.span), + // Filled in by proc_macro_harness::inject() + proc_macros: Vec::new(), }); krate } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 72430fa9c17..1973733288b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -429,6 +429,7 @@ pub struct Crate { pub module: Mod, pub attrs: Vec, pub span: Span, + pub proc_macros: Vec, } /// Possible values inside of compile-time attribute lists. diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index e0180d45193..f130b0a2ee4 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -989,7 +989,7 @@ pub fn noop_visit_mod(Mod { inner, items, inline: _ }: &mut Mod, } pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { - visit_clobber(krate, |Crate { module, attrs, span }| { + visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| { let item = P(Item { ident: Ident::invalid(), attrs, @@ -1004,11 +1004,11 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { let len = items.len(); if len == 0 { let module = Mod { inner: span, items: vec![], inline: true }; - Crate { module, attrs: vec![], span } + Crate { module, attrs: vec![], span, proc_macros } } else if len == 1 { let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner(); match kind { - ItemKind::Mod(module) => Crate { module, attrs, span }, + ItemKind::Mod(module) => Crate { module, attrs, span, proc_macros }, _ => panic!("visitor converted a module to not a module"), } } else { diff --git a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs index 37465ccf1c2..d8e5746f3f6 100644 --- a/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/auxiliary/proc_macro.rs @@ -9,6 +9,19 @@ extern crate proc_macro; use proc_macro::TokenStream; +macro_rules! make_attr_macro { + ($name:ident) => { + /// Generated doc comment + #[proc_macro_attribute] + pub fn $name(args: TokenStream, input: TokenStream) -> TokenStream { + panic!() + } + } +} + +make_attr_macro!(first_attr); +make_attr_macro!(second_attr); + /// a proc-macro that swallows its input and does nothing. #[proc_macro] pub fn some_proc_macro(_input: TokenStream) -> TokenStream { diff --git a/src/test/rustdoc/inline_cross/proc_macro.rs b/src/test/rustdoc/inline_cross/proc_macro.rs index 3dc8de3fe57..532a295c0f3 100644 --- a/src/test/rustdoc/inline_cross/proc_macro.rs +++ b/src/test/rustdoc/inline_cross/proc_macro.rs @@ -26,3 +26,11 @@ pub use some_macros::some_proc_attr; // @has proc_macro/derive.SomeDerive.html // @has - 'a derive attribute that adds nothing to its input.' pub use some_macros::SomeDerive; + +// @has proc_macro/attr.first_attr.html +// @has - 'Generated doc comment' +pub use some_macros::first_attr; + +// @has proc_macro/attr.second_attr.html +// @has - 'Generated doc comment' +pub use some_macros::second_attr; diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index b299fc55841..35e418696f1 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0}} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]} From 516459870cf0fe13979aaa568bfc413e2e5bba18 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 15 Feb 2020 15:51:40 -0500 Subject: [PATCH 0227/1250] Add additional comment --- src/libsyntax/ast.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 1973733288b..d101473d76b 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -429,6 +429,12 @@ pub struct Crate { pub module: Mod, pub attrs: Vec, pub span: Span, + /// The order of items in the HIR is unrelated to the order of + /// items in the AST. However, we generate proc macro harnesses + /// based on the AST order, and later refer to these harnesses + /// from the HIR. This field keeps track of the order in which + /// we generated proc macros harnesses, so that we can map + /// HIR proc macros items back to their harness items. pub proc_macros: Vec, } From 774a029e9629a461355c9e9cb423820e9936dc65 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sun, 16 Feb 2020 09:59:01 +1300 Subject: [PATCH 0228/1250] Code review changes. --- src/librustc/mir/interpret/value.rs | 11 ++++++++--- src/librustc/ty/sty.rs | 9 +++++++-- src/librustc_codegen_ssa/mir/constant.rs | 4 ++-- src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/interpret/intrinsics.rs | 2 +- src/librustc_mir_build/hair/constant.rs | 2 +- src/librustc_mir_build/hair/pattern/_match.rs | 11 +++++------ src/librustc_mir_build/hair/pattern/mod.rs | 6 ++---- src/librustc_typeck/check/expr.rs | 10 +++------- src/librustdoc/clean/mod.rs | 4 +--- src/librustdoc/clean/utils.rs | 8 ++++---- 11 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 538d955762e..2c146b5d7b4 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -89,8 +89,8 @@ impl<'tcx> ConstValue<'tcx> { ConstValue::Scalar(Scalar::from_u64(i)) } - pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self { - ConstValue::Scalar(Scalar::from_machine_usize(cx, i)) + pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { + ConstValue::Scalar(Scalar::from_machine_usize(i, cx)) } } @@ -314,7 +314,7 @@ impl<'tcx, Tag> Scalar { } #[inline] - pub fn from_machine_usize(cx: &impl HasDataLayout, i: u64) -> Self { + pub fn from_machine_usize(i: u64, cx: &impl HasDataLayout) -> Self { Self::from_uint(i, cx.data_layout().pointer_size) } @@ -337,6 +337,11 @@ impl<'tcx, Tag> Scalar { .unwrap_or_else(|| bug!("Signed value {:#x} does not fit in {} bits", i, size.bits())) } + #[inline] + pub fn from_machine_isize(i: i64, cx: &impl HasDataLayout) -> Self { + Self::from_int(i, cx.data_layout().pointer_size) + } + #[inline] pub fn from_f32(f: Single) -> Self { // We trust apfloat to give us properly truncated data. diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 57b55c0f897..a23c44d1921 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2415,9 +2415,14 @@ pub struct Const<'tcx> { static_assert_size!(Const<'_>, 48); impl<'tcx> Const<'tcx> { + #[inline] + pub fn from_value(tcx: TyCtxt<'tcx>, val: ConstValue<'tcx>, ty: Ty<'tcx>) -> &'tcx Self { + tcx.mk_const(Self { val: ConstKind::Value(val), ty }) + } + #[inline] pub fn from_scalar(tcx: TyCtxt<'tcx>, val: Scalar, ty: Ty<'tcx>) -> &'tcx Self { - tcx.mk_const(Self { val: ConstKind::Value(ConstValue::Scalar(val)), ty }) + Self::from_value(tcx, ConstValue::Scalar(val), ty) } #[inline] @@ -2473,7 +2478,7 @@ impl<'tcx> Const<'tcx> { // evaluate the const. tcx.const_eval_resolve(param_env, did, substs, promoted, None) .ok() - .map(|val| tcx.mk_const(Const { val: ConstKind::Value(val), ty: self.ty })) + .map(|val| Const::from_value(tcx, val, self.ty)) }; match self.val { diff --git a/src/librustc_codegen_ssa/mir/constant.rs b/src/librustc_codegen_ssa/mir/constant.rs index 3bd1755927b..9ceb75a603b 100644 --- a/src/librustc_codegen_ssa/mir/constant.rs +++ b/src/librustc_codegen_ssa/mir/constant.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if let ty::ConstKind::Value(value) = const_.val { Ok(value) } else { - bug!("encountered bad ConstKind in codegen"); + span_bug!(constant.span, "encountered bad ConstKind in codegen: {:?}", const_); } } } @@ -83,7 +83,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ty::Array(_, n) => n.eval_usize(bx.tcx(), ty::ParamEnv::reveal_all()), _ => bug!("invalid simd shuffle type: {}", ty), }; - let c = bx.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(val), ty }); + let c = ty::Const::from_value(bx.tcx(), val, ty); let values: Vec<_> = (0..fields) .map(|field| { let field = bx.tcx().const_field( diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 5915520535d..04e2558a308 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -79,7 +79,7 @@ pub(crate) fn destructure_const<'tcx>( let fields_iter = (0..field_count).map(|i| { let field_op = ecx.operand_field(down, i).unwrap(); let val = op_to_const(&ecx, field_op); - tcx.mk_const(ty::Const { val: ty::ConstKind::Value(val), ty: field_op.layout.ty }) + ty::Const::from_value(tcx, val, field_op.layout.ty) }); let fields = tcx.arena.alloc_from_iter(fields_iter); diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index b7333ac3aae..42d4996c253 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -65,7 +65,7 @@ crate fn eval_nullary_intrinsic<'tcx>( sym::size_of => layout.size.bytes(), _ => bug!(), }; - ConstValue::from_machine_usize(&tcx, n) + ConstValue::from_machine_usize(n, &tcx) } sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()), other => bug!("`{}` is not a zero arg intrinsic", other), diff --git a/src/librustc_mir_build/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs index 266f4738c50..e594e1eeed0 100644 --- a/src/librustc_mir_build/hair/constant.rs +++ b/src/librustc_mir_build/hair/constant.rs @@ -65,7 +65,7 @@ crate fn lit_to_const<'tcx>( ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), ast::LitKind::Err(_) => return Err(LitToConstError::Reported), }; - Ok(tcx.mk_const(ty::Const { val: ty::ConstKind::Value(lit), ty })) + Ok(ty::Const::from_value(tcx, lit, ty)) } fn parse_float<'tcx>(num: Symbol, fty: ast::FloatTy, neg: bool) -> Result, ()> { diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 7ed6c81eb63..85f03629b64 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -343,12 +343,11 @@ impl<'tcx> PatternFolder<'tcx> for LiteralExpander<'tcx> { ty: rty, span: pat.span, kind: box PatKind::Constant { - value: self.tcx.mk_const(Const { - val: ty::ConstKind::Value( - self.fold_const_value_deref(*val, rty, crty), - ), - ty: rty, - }), + value: Const::from_value( + self.tcx, + self.fold_const_value_deref(*val, rty, crty), + rty, + ), }, }, }, diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index f403b1432c4..91011746469 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -769,10 +769,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { Some(span), ) { Ok(value) => { - let const_ = self.tcx.mk_const(ty::Const { - val: ty::ConstKind::Value(value), - ty: self.tables.node_type(id), - }); + let const_ = + ty::Const::from_value(self.tcx, value, self.tables.node_type(id)); let pattern = self.const_to_pat(&const_, id, span); if !is_associated_const { diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index dc9d5003a41..e694d845a9b 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -25,7 +25,7 @@ use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; use rustc::ty::TypeFoldable; -use rustc::ty::{AdtKind, ConstKind, Visibility}; +use rustc::ty::{AdtKind, Visibility}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir as hir; @@ -1011,12 +1011,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let count = if self.const_param_def_id(count).is_some() { Ok(self.to_const(count, tcx.type_of(count_def_id))) } else { - tcx.const_eval_poly(count_def_id).map(|val| { - tcx.mk_const(ty::Const { - val: ConstKind::Value(val), - ty: tcx.type_of(count_def_id), - }) - }) + tcx.const_eval_poly(count_def_id) + .map(|val| ty::Const::from_value(tcx, val, tcx.type_of(count_def_id))) }; let uty = match expected { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 79019d0b950..67c9b9565db 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1333,9 +1333,7 @@ impl Clean for hir::Ty<'_> { let def_id = cx.tcx.hir().local_def_id(length.hir_id); let length = match cx.tcx.const_eval_poly(def_id) { Ok(length) => { - let const_ = - ty::Const { val: ty::ConstKind::Value(length), ty: cx.tcx.types.usize }; - print_const(cx, &const_) + print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize)) } Err(_) => cx .sess() diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index f8c657477f7..704583467b4 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -457,7 +457,7 @@ pub fn name_from_pat(p: &hir::Pat) -> String { } } -pub fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String { +pub fn print_const(cx: &DocContext<'_>, n: &'tcx ty::Const<'_>) -> String { match n.val { ty::ConstKind::Unevaluated(def_id, _, promoted) => { let mut s = if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) { @@ -493,8 +493,8 @@ pub fn print_evaluated_const(cx: &DocContext<'_>, def_id: DefId) -> Option None, (ConstValue::Scalar(_), &ty::Adt(_, _)) => None, (ConstValue::Scalar(_), _) => { - let const_ = ty::Const { val: ty::ConstKind::Value(val), ty }; - Some(print_const_with_custom_print_scalar(cx, &const_)) + let const_ = ty::Const::from_value(cx.tcx, val, ty); + Some(print_const_with_custom_print_scalar(cx, const_)) } _ => None, } @@ -513,7 +513,7 @@ fn format_integer_with_underscore_sep(num: &str) -> String { .collect() } -fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &ty::Const<'tcx>) -> String { +fn print_const_with_custom_print_scalar(cx: &DocContext<'_>, ct: &'tcx ty::Const<'tcx>) -> String { // Use a slightly different format for integer types which always shows the actual value. // For all other types, fallback to the original `pretty_print_const`. match (ct.val, &ct.ty.kind) { From d6238bd8d4fe283968abbf46357c8e56f283b65b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 22:21:00 +0100 Subject: [PATCH 0229/1250] reject assoc statics & extern consts during parsing --- src/librustc_ast_passes/ast_validation.rs | 28 +------ src/librustc_parse/parser/item.rs | 27 ++++++- src/test/ui/extern/extern-const.stderr | 2 - .../parser/assoc-static-semantic-fail.stderr | 44 +++++------ .../ui/parser/assoc-static-syntactic-fail.rs | 27 +++++++ .../parser/assoc-static-syntactic-fail.stderr | 74 +++++++++++++++++++ .../ui/parser/assoc-static-syntactic-pass.rs | 29 -------- .../parser/foreign-const-semantic-fail.stderr | 5 -- .../ui/parser/foreign-const-syntactic-fail.rs | 9 +++ .../foreign-const-syntactic-fail.stderr | 22 ++++++ .../ui/parser/foreign-const-syntactic-pass.rs | 11 --- 11 files changed, 183 insertions(+), 95 deletions(-) create mode 100644 src/test/ui/parser/assoc-static-syntactic-fail.rs create mode 100644 src/test/ui/parser/assoc-static-syntactic-fail.stderr delete mode 100644 src/test/ui/parser/assoc-static-syntactic-pass.rs create mode 100644 src/test/ui/parser/foreign-const-syntactic-fail.rs create mode 100644 src/test/ui/parser/foreign-const-syntactic-fail.stderr delete mode 100644 src/test/ui/parser/foreign-const-syntactic-pass.rs diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 8efd50ad098..d3fcb589fd0 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -533,20 +533,6 @@ impl<'a> AstValidator<'a> { } } - fn error_foreign_const(&self, ident: Ident, span: Span) { - self.err_handler() - .struct_span_err(ident.span, "extern items cannot be `const`") - .span_suggestion( - span.with_hi(ident.span.lo()), - "try using a static value", - "static ".to_string(), - Applicability::MachineApplicable, - ) - .span_label(self.current_extern_span(), "in this `extern` block") - .note(MORE_EXTERN) - .emit(); - } - /// Reject C-varadic type unless the function is foreign, /// or free and `unsafe extern "C"` semantically. fn check_c_varadic_type(&self, fk: FnKind<'a>) { @@ -1003,10 +989,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); } - ForeignItemKind::Const(..) => { - self.error_foreign_const(fi.ident, fi.span); - } - ForeignItemKind::Macro(..) => {} + ForeignItemKind::Const(..) | ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, fi) @@ -1267,13 +1250,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - match item.kind { - AssocItemKind::Const(..) => self.check_item_named(item.ident, "const"), - AssocItemKind::Static(..) => self - .err_handler() - .struct_span_err(item.span, "associated `static` items are not allowed") - .emit(), - _ => {} + if let AssocItemKind::Const(..) = item.kind { + self.check_item_named(item.ident, "const"); } self.with_in_trait_impl(false, |this| visit::walk_assoc_item(this, item, ctxt)); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 20d6182ddc1..da72da04365 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -643,9 +643,16 @@ impl<'a> Parser<'a> { if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { item.tokens = Some(tokens); } + self.error_on_assoc_static(&item); Ok(P(item)) } + fn error_on_assoc_static(&self, item: &AssocItem) { + if let AssocItemKind::Static(..) = item.kind { + self.struct_span_err(item.span, "associated `static` items are not allowed").emit(); + } + } + fn parse_assoc_item_( &mut self, at_end: &mut bool, @@ -868,7 +875,25 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?; - Ok(P(self.mk_item(lo, ident, kind, vis, attrs))) + let item = self.mk_item(lo, ident, kind, vis, attrs); + self.error_on_foreign_const(&item); + Ok(P(item)) + } + + fn error_on_foreign_const(&self, item: &ForeignItem) { + if let AssocItemKind::Const(..) = item.kind { + self.struct_span_err(item.ident.span, "extern items cannot be `const`") + .span_suggestion( + item.span.with_hi(item.ident.span.lo()), + "try using a static value", + "static ".to_string(), + Applicability::MachineApplicable, + ) + .note( + "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html", + ) + .emit(); + } } fn is_static_global(&mut self) -> bool { diff --git a/src/test/ui/extern/extern-const.stderr b/src/test/ui/extern/extern-const.stderr index 97e11381c6f..7f67adbdb19 100644 --- a/src/test/ui/extern/extern-const.stderr +++ b/src/test/ui/extern/extern-const.stderr @@ -1,8 +1,6 @@ error: extern items cannot be `const` --> $DIR/extern-const.rs:16:11 | -LL | extern "C" { - | ---------- in this `extern` block LL | const rust_dbg_static_mut: libc::c_int; | ------^^^^^^^^^^^^^^^^^^^ | | diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr index d5a02c9bebc..d02e2855c7e 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.stderr +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -34,30 +34,12 @@ error: associated `static` items are not allowed LL | static TB: u8; | ^^^^^^^^^^^^^^ -error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:24:5 - | -LL | default static TC: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - error: associated `static` items are not allowed --> $DIR/assoc-static-semantic-fail.rs:24:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:27:5 - | -LL | pub(crate) default static TD: u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:27:5 - | -LL | pub(crate) default static TD: u8; - | ^^^^^^^^^^ - error: associated `static` items are not allowed --> $DIR/assoc-static-semantic-fail.rs:27:5 | @@ -82,17 +64,35 @@ error: associated `static` items are not allowed LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0449]: unnecessary visibility qualifier +error: associated `static` items are not allowed --> $DIR/assoc-static-semantic-fail.rs:40:5 | LL | pub default static TD: u8; - | ^^^ `pub` not permitted here because it's implied + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: associated `static` items are not allowed +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:24:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `default` is only allowed on items in `impl` definitions + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier + --> $DIR/assoc-static-semantic-fail.rs:27:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^ + +error[E0449]: unnecessary visibility qualifier --> $DIR/assoc-static-semantic-fail.rs:40:5 | LL | pub default static TD: u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^ `pub` not permitted here because it's implied error: aborting due to 16 previous errors diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.rs b/src/test/ui/parser/assoc-static-syntactic-fail.rs new file mode 100644 index 00000000000..8f042767e55 --- /dev/null +++ b/src/test/ui/parser/assoc-static-syntactic-fail.rs @@ -0,0 +1,27 @@ +// Syntactically, we do allow e.g., `static X: u8 = 0;` as an associated item. + +fn main() {} + +#[cfg(FALSE)] +impl S { + static IA: u8 = 0; //~ ERROR associated `static` items are not allowed + static IB: u8; //~ ERROR associated `static` items are not allowed + default static IC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub(crate) default static ID: u8; //~ ERROR associated `static` items are not allowed +} + +#[cfg(FALSE)] +trait T { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub(crate) default static TD: u8; //~ ERROR associated `static` items are not allowed +} + +#[cfg(FALSE)] +impl T for S { + static TA: u8 = 0; //~ ERROR associated `static` items are not allowed + static TB: u8; //~ ERROR associated `static` items are not allowed + default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + pub default static TD: u8; //~ ERROR associated `static` items are not allowed +} diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.stderr b/src/test/ui/parser/assoc-static-syntactic-fail.stderr new file mode 100644 index 00000000000..bb1e5c4be2e --- /dev/null +++ b/src/test/ui/parser/assoc-static-syntactic-fail.stderr @@ -0,0 +1,74 @@ +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:7:5 + | +LL | static IA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:8:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:9:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:10:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:15:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:16:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:17:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:18:5 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:23:5 + | +LL | static TA: u8 = 0; + | ^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:24:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:25:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/assoc-static-syntactic-fail.rs:26:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + diff --git a/src/test/ui/parser/assoc-static-syntactic-pass.rs b/src/test/ui/parser/assoc-static-syntactic-pass.rs deleted file mode 100644 index 7f5b9f79335..00000000000 --- a/src/test/ui/parser/assoc-static-syntactic-pass.rs +++ /dev/null @@ -1,29 +0,0 @@ -// Syntactically, we do allow e.g., `static X: u8 = 0;` as an associated item. - -// check-pass - -fn main() {} - -#[cfg(FALSE)] -impl S { - static IA: u8 = 0; - static IB: u8; - default static IC: u8 = 0; - pub(crate) default static ID: u8; -} - -#[cfg(FALSE)] -trait T { - static TA: u8 = 0; - static TB: u8; - default static TC: u8 = 0; - pub(crate) default static TD: u8; -} - -#[cfg(FALSE)] -impl T for S { - static TA: u8 = 0; - static TB: u8; - default static TC: u8 = 0; - pub default static TD: u8; -} diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr index 799a795c593..f364f11bb03 100644 --- a/src/test/ui/parser/foreign-const-semantic-fail.stderr +++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr @@ -1,8 +1,6 @@ error: extern items cannot be `const` --> $DIR/foreign-const-semantic-fail.rs:4:11 | -LL | extern { - | ------ in this `extern` block LL | const A: isize; | ------^ | | @@ -13,9 +11,6 @@ LL | const A: isize; error: extern items cannot be `const` --> $DIR/foreign-const-semantic-fail.rs:6:11 | -LL | extern { - | ------ in this `extern` block -... LL | const B: isize = 42; | ------^ | | diff --git a/src/test/ui/parser/foreign-const-syntactic-fail.rs b/src/test/ui/parser/foreign-const-syntactic-fail.rs new file mode 100644 index 00000000000..a78f8b1623a --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-fail.rs @@ -0,0 +1,9 @@ +// Syntactically, a `const` item inside an `extern { ... }` block is not allowed. + +fn main() {} + +#[cfg(FALSE)] +extern { + const A: isize; //~ ERROR extern items cannot be `const` + const B: isize = 42; //~ ERROR extern items cannot be `const` +} diff --git a/src/test/ui/parser/foreign-const-syntactic-fail.stderr b/src/test/ui/parser/foreign-const-syntactic-fail.stderr new file mode 100644 index 00000000000..9cf58fa95fb --- /dev/null +++ b/src/test/ui/parser/foreign-const-syntactic-fail.stderr @@ -0,0 +1,22 @@ +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:7:11 + | +LL | const A: isize; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: extern items cannot be `const` + --> $DIR/foreign-const-syntactic-fail.rs:8:11 + | +LL | const B: isize = 42; + | ------^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/foreign-const-syntactic-pass.rs b/src/test/ui/parser/foreign-const-syntactic-pass.rs deleted file mode 100644 index bacef8e71d6..00000000000 --- a/src/test/ui/parser/foreign-const-syntactic-pass.rs +++ /dev/null @@ -1,11 +0,0 @@ -// Syntactically, a `const` item inside an `extern { ... }` block is allowed. - -// check-pass - -fn main() {} - -#[cfg(FALSE)] -extern { - const A: isize; - const B: isize = 42; -} From fe62bed73b0ef9fe63faa2a56653f3c7fa17f7c2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 22:33:21 +0100 Subject: [PATCH 0230/1250] print_item_const: remove extraneous space --- src/librustc_ast_pretty/pprust.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 0eea64dfe73..2f712964a84 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1067,9 +1067,9 @@ impl<'a> State<'a> { vis: &ast::Visibility, ) { let leading = match mutbl { - None => "const ", - Some(ast::Mutability::Not) => "static ", - Some(ast::Mutability::Mut) => "static mut ", + None => "const", + Some(ast::Mutability::Not) => "static", + Some(ast::Mutability::Mut) => "static mut", }; self.head(visibility_qualified(vis, leading)); self.print_ident(ident); From f12ae4ac608362264470eda9b1d67236bae62040 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 15 Feb 2020 22:36:03 +0100 Subject: [PATCH 0231/1250] ast: tweak AssocItemKind::Macro comment --- src/libsyntax/ast.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index a931d8c27ba..8154ae2f307 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2637,6 +2637,6 @@ pub enum AssocItemKind { Fn(FnSig, Generics, Option>), /// A type. TyAlias(Generics, GenericBounds, Option>), - /// A macro expanding to an item. + /// A macro expanding to items. Macro(Mac), } From 97cc3a229bfe44d387a458fc6e25e58ee11acee3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 15 Feb 2020 23:02:58 +0100 Subject: [PATCH 0232/1250] fix incremental tests --- src/test/incremental/warnings-reemitted.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs index 5fc89395827..657bc30c088 100644 --- a/src/test/incremental/warnings-reemitted.rs +++ b/src/test/incremental/warnings-reemitted.rs @@ -2,8 +2,8 @@ // compile-flags: -Coverflow-checks=on // build-pass (FIXME(62277): could be check-pass?) -#![warn(const_err)] +#![warn(overflow)] fn main() { - let _ = 255u8 + 1; //~ WARNING attempt to add with overflow + let _ = 255u8 + 1; //~ WARNING operation will overflow } From 8904bddec5abea92c88e5c991925c08a3df5faf3 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sun, 16 Feb 2020 11:39:04 +1300 Subject: [PATCH 0233/1250] Determine type of intrinsics instead of assuming the destination type is the same. --- src/librustc_mir/interpret/intrinsics.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 42d4996c253..04f0f92d67f 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -110,7 +110,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | sym::type_id | sym::type_name => { let gid = GlobalId { instance, promoted: None }; - let val = self.const_eval(gid, dest.layout.ty)?; + let ty = match intrinsic_name { + sym::min_align_of | sym::pref_align_of | sym::size_of => self.tcx.types.usize, + sym::needs_drop => self.tcx.types.bool, + sym::type_id => self.tcx.types.u64, + sym::type_name => self.tcx.mk_static_str(), + _ => span_bug!(span, "Already checked for nullary intrinsics"), + }; + let val = self.const_eval(gid, ty)?; self.copy_op(val, dest)?; } From 3300725342dba6b191bfcc094485f708695c8a44 Mon Sep 17 00:00:00 2001 From: Oliver Middleton Date: Sat, 15 Feb 2020 23:14:46 +0000 Subject: [PATCH 0234/1250] Fix running rustdoc-js test suite individually Without `Compiletest.path` set running `x.py test src/test/rustdoc-js` would run the `rustdoc-js` test suite with everything filtered out. As this was the only place setting `Compiletest.path` to `None` this removes the `Option` wrapper as well. --- src/bootstrap/test.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 1580091488f..899c44bbdd2 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -662,7 +662,7 @@ impl Step for RustdocJSNotStd { target: self.target, mode: "js-doc-test", suite: "rustdoc-js", - path: None, + path: "src/test/rustdoc-js", compare_mode: None, }); } else { @@ -698,7 +698,7 @@ impl Step for RustdocUi { target: self.target, mode: "ui", suite: "rustdoc-ui", - path: Some("src/test/rustdoc-ui"), + path: "src/test/rustdoc-ui", compare_mode: None, }) } @@ -843,7 +843,7 @@ macro_rules! test_definitions { target: self.target, mode: $mode, suite: $suite, - path: Some($path), + path: $path, compare_mode: $compare_mode, }) } @@ -926,7 +926,7 @@ struct Compiletest { target: Interned, mode: &'static str, suite: &'static str, - path: Option<&'static str>, + path: &'static str, compare_mode: Option<&'static str>, } @@ -949,7 +949,7 @@ impl Step for Compiletest { let suite = self.suite; // Path for test suite - let suite_path = self.path.unwrap_or(""); + let suite_path = self.path; // Skip codegen tests if they aren't enabled in configuration. if !builder.config.codegen_tests && suite == "codegen" { From bd12cd3d2fe2fd69cff05d4b710c8020dea2cdf7 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 15 Feb 2020 18:06:39 -0500 Subject: [PATCH 0235/1250] Formatter::sign is &'static str The contents were always UTF-8 anyway, and &str has an equivalent representation to &[u8], so this should not affect performance while removing unsafety at edges. It may be worth exploring a further adjustment that stores a single byte (instead of 16) as the contents are always "", "-", or "+". --- src/libcore/fmt/mod.rs | 6 +++--- src/libcore/fmt/num.rs | 6 +++--- src/libcore/num/flt2dec/mod.rs | 30 +++++++++++++++--------------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 973c2f2b915..3f2c9654706 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1356,11 +1356,11 @@ impl<'a> Formatter<'a> { let mut align = old_align; if self.sign_aware_zero_pad() { // a sign always goes first - let sign = unsafe { str::from_utf8_unchecked(formatted.sign) }; + let sign = formatted.sign; self.buf.write_str(sign)?; // remove the sign from the formatted parts - formatted.sign = b""; + formatted.sign = ""; width = width.saturating_sub(sign.len()); align = rt::v1::Alignment::Right; self.fill = '0'; @@ -1392,7 +1392,7 @@ impl<'a> Formatter<'a> { } if !formatted.sign.is_empty() { - write_bytes(self.buf, formatted.sign)?; + self.buf.write_str(formatted.sign)?; } for part in formatted.parts { match *part { diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index c187471fb5f..5dfd3a8ecdb 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -369,11 +369,11 @@ macro_rules! impl_Exp { flt2dec::Part::Copy(exp_slice) ]; let sign = if !is_nonnegative { - &b"-"[..] + "-" } else if f.sign_plus() { - &b"+"[..] + "+" } else { - &b""[..] + "" }; let formatted = flt2dec::Formatted{sign, parts}; f.pad_formatted_parts(&formatted) diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 9e760c13c0c..93a2348447e 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -237,7 +237,7 @@ impl<'a> Part<'a> { #[derive(Clone)] pub struct Formatted<'a> { /// A byte slice representing a sign, either `""`, `"-"` or `"+"`. - pub sign: &'static [u8], + pub sign: &'static str, /// Formatted parts to be rendered after a sign and optional zero padding. pub parts: &'a [Part<'a>], } @@ -259,7 +259,7 @@ impl<'a> Formatted<'a> { if out.len() < self.sign.len() { return None; } - out[..self.sign.len()].copy_from_slice(self.sign); + out[..self.sign.len()].copy_from_slice(self.sign.as_bytes()); let mut written = self.sign.len(); for part in self.parts { @@ -402,38 +402,38 @@ pub enum Sign { } /// Returns the static byte string corresponding to the sign to be formatted. -/// It can be either `b""`, `b"+"` or `b"-"`. -fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static [u8] { +/// It can be either `""`, `"+"` or `"-"`. +fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str { match (*decoded, sign) { - (FullDecoded::Nan, _) => b"", - (FullDecoded::Zero, Sign::Minus) => b"", + (FullDecoded::Nan, _) => "", + (FullDecoded::Zero, Sign::Minus) => "", (FullDecoded::Zero, Sign::MinusRaw) => { if negative { - b"-" + "-" } else { - b"" + "" } } - (FullDecoded::Zero, Sign::MinusPlus) => b"+", + (FullDecoded::Zero, Sign::MinusPlus) => "+", (FullDecoded::Zero, Sign::MinusPlusRaw) => { if negative { - b"-" + "-" } else { - b"+" + "+" } } (_, Sign::Minus) | (_, Sign::MinusRaw) => { if negative { - b"-" + "-" } else { - b"" + "" } } (_, Sign::MinusPlus) | (_, Sign::MinusPlusRaw) => { if negative { - b"-" + "-" } else { - b"+" + "+" } } } From 759526e513f28443b845b63176f15424686d0254 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Feb 2020 00:57:48 +0100 Subject: [PATCH 0236/1250] Fix printing of `Yield` terminator --- src/librustc/mir/mod.rs | 18 ++++++++++-------- .../mir-opt/generator-storage-dead-unwind.rs | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 4520d3a3333..a3e3a26db05 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1468,21 +1468,23 @@ impl<'tcx> TerminatorKind<'tcx> { /// successors, which may be rendered differently between the text and the graphviz format. pub fn fmt_head(&self, fmt: &mut W) -> fmt::Result { use self::TerminatorKind::*; - match *self { + match self { Goto { .. } => write!(fmt, "goto"), - SwitchInt { discr: ref place, .. } => write!(fmt, "switchInt({:?})", place), + SwitchInt { discr, .. } => write!(fmt, "switchInt({:?})", discr), Return => write!(fmt, "return"), GeneratorDrop => write!(fmt, "generator_drop"), Resume => write!(fmt, "resume"), Abort => write!(fmt, "abort"), - Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value), + Yield { value, resume_arg, .. } => { + write!(fmt, "{:?} = suspend({:?})", resume_arg, value) + } Unreachable => write!(fmt, "unreachable"), - Drop { ref location, .. } => write!(fmt, "drop({:?})", location), - DropAndReplace { ref location, ref value, .. } => { + Drop { location, .. } => write!(fmt, "drop({:?})", location), + DropAndReplace { location, value, .. } => { write!(fmt, "replace({:?} <- {:?})", location, value) } - Call { ref func, ref args, ref destination, .. } => { - if let Some((ref destination, _)) = *destination { + Call { func, args, destination, .. } => { + if let Some((destination, _)) = destination { write!(fmt, "{:?} = ", destination)?; } write!(fmt, "{:?}(", func)?; @@ -1494,7 +1496,7 @@ impl<'tcx> TerminatorKind<'tcx> { } write!(fmt, ")") } - Assert { ref cond, expected, ref msg, .. } => { + Assert { cond, expected, msg, .. } => { write!(fmt, "assert(")?; if !expected { write!(fmt, "!")?; diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs index 4442fa5f521..98acce83759 100644 --- a/src/test/mir-opt/generator-storage-dead-unwind.rs +++ b/src/test/mir-opt/generator-storage-dead-unwind.rs @@ -49,7 +49,7 @@ fn main() { // StorageLive(_4); // _4 = Bar(const 6i32,); // ... -// _1 = suspend(move _6) -> [resume: bb2, drop: bb4]; +// _5 = suspend(move _6) -> [resume: bb2, drop: bb4]; // } // bb1 (cleanup): { // resume; From 940f65782cc5df7fecad27b38cc25b6d1eeaf2e8 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 8 Feb 2020 21:34:38 -0800 Subject: [PATCH 0237/1250] Parse & reject postfix operators after casts This adds parsing for expressions like 'x as Ty[0]' which will immediately error out, but still give the rest of the parser a valid parse tree to continue. --- src/librustc_parse/parser/expr.rs | 41 +++++++++- .../parser/issue-35813-postfix-after-cast.rs | 63 ++++++++++++++++ .../issue-35813-postfix-after-cast.stderr | 74 +++++++++++++++++++ 3 files changed, 176 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/parser/issue-35813-postfix-after-cast.rs create mode 100644 src/test/ui/parser/issue-35813-postfix-after-cast.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 20b9df0a2d9..d7d3145770c 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -551,7 +551,7 @@ impl<'a> Parser<'a> { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); - match self.parse_ty_no_plus() { + let type_result = match self.parse_ty_no_plus() { Ok(rhs) => Ok(mk_expr(self, rhs)), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover @@ -616,7 +616,44 @@ impl<'a> Parser<'a> { } } } - } + }; + + // Disallow postfix operators such as `.`, `?` or index (`[]`) after casts. + // Parses the postfix operator and emits an error. + let expr = type_result?; + let span = expr.span; + + // The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. + let with_postfix = self.parse_dot_or_call_expr_with_(expr, span)?; + if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { + let expr_str = self.span_to_snippet(span); + + let msg = format!( + "casts followed by {} are not supported", + match with_postfix.kind { + ExprKind::Index(_, _) => "index operators", + ExprKind::Try(_) => "try operators", + ExprKind::Field(_, _) => "field access expressions", + ExprKind::MethodCall(_, _) => "method call expressions", + ExprKind::Await(_) => "awaits", + _ => "expressions", + } + ); + let mut err = self.struct_span_err(with_postfix.span, &msg); + let suggestion = "try surrounding the expression with parentheses"; + if let Ok(expr_str) = expr_str { + err.span_suggestion( + span, + suggestion, + format!("({})", expr_str), + Applicability::MachineApplicable, + ) + } else { + err.span_help(span, suggestion) + } + .emit(); + }; + Ok(with_postfix) } fn parse_assoc_op_ascribe(&mut self, lhs: P, lhs_span: Span) -> PResult<'a, P> { diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs new file mode 100644 index 00000000000..dd608b263ec --- /dev/null +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -0,0 +1,63 @@ +// edition:2018 +#![crate_type = "lib"] +use std::future::Future; +use std::pin::Pin; + +// This tests the parser for "x as Y[z]". It errors, but we want to give useful +// errors and parse such that further code gives useful errors. +pub fn index_after_as_cast() { + vec![1, 2, 3] as Vec[0]; + //~^ ERROR: casts followed by index operators are not supported +} + +pub fn index_after_cast_to_index() { + (&[0]) as &[i32][0]; + //~^ ERROR: casts followed by index operators are not supported +} + +// this tests that the precedence for `!x as Y.Z` is still what we expect +pub fn precedence() { + let x: i32 = &vec![1, 2, 3] as &Vec[0]; + //~^ ERROR: casts followed by index operators are not supported +} + +pub fn complex() { + let _ = format!( + "{}", + if true { 33 } else { 44 } as i32.max(0) + //~^ ERROR: casts followed by method call expressions are not supported + ); +} + +pub fn in_condition() { + if 5u64 as i32.max(0) == 0 { + //~^ ERROR: casts followed by method call expressions are not supported + } +} + +pub fn inside_block() { + let _ = if true { + 5u64 as u32.max(0) == 0 + //~^ ERROR: casts followed by method call expressions are not supported + } else { false }; +} + +static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); +//~^ ERROR: casts followed by index operators are not supported + +pub async fn cast_then_await() { + Box::pin(noop()) as Pin>>.await; + //~^ ERROR: casts followed by awaits are not supported +} + +pub async fn noop() {} + +#[derive(Default)] +pub struct Foo { + pub bar: u32, +} + +pub fn struct_field() { + Foo::default() as Foo.bar; + //~^ ERROR: casts followed by field access expressions are not supported +} diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr new file mode 100644 index 00000000000..9459e076ea0 --- /dev/null +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -0,0 +1,74 @@ +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:9:5 + | +LL | vec![1, 2, 3] as Vec[0]; + | -------------------------^^^ + | | + | help: try surrounding the expression with parentheses: `(vec![1, 2, 3] as Vec)` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:14:5 + | +LL | (&[0]) as &[i32][0]; + | ----------------^^^ + | | + | help: try surrounding the expression with parentheses: `((&[0]) as &[i32])` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:20:18 + | +LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; + | ---------------------------^^^ + | | + | help: try surrounding the expression with parentheses: `(&vec![1, 2, 3] as &Vec)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:33:8 + | +LL | if 5u64 as i32.max(0) == 0 { + | -----------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(5u64 as i32)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:40:9 + | +LL | 5u64 as u32.max(0) == 0 + | -----------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(5u64 as u32)` + +error: casts followed by index operators are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:45:24 + | +LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); + | ------------------^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(&[1,2,3] as &[i32])` + +error: casts followed by awaits are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:49:5 + | +LL | Box::pin(noop()) as Pin>>.await; + | -----------------------------------------------------^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(Box::pin(noop()) as Pin>>)` + +error: casts followed by field access expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:61:5 + | +LL | Foo::default() as Foo.bar; + | ---------------------^^^^ + | | + | help: try surrounding the expression with parentheses: `(Foo::default() as Foo)` + +error: casts followed by method call expressions are not supported + --> $DIR/issue-35813-postfix-after-cast.rs:27:9 + | +LL | if true { 33 } else { 44 } as i32.max(0) + | ---------------------------------^^^^^^^ + | | + | help: try surrounding the expression with parentheses: `(if true { 33 } else { 44 } as i32)` + +error: aborting due to 9 previous errors + From 5ce9b80c0f93e54bc83f6cb15942ecdce31c3e6a Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:12:59 -0800 Subject: [PATCH 0238/1250] Refactor out error case & apply suggestions. This is almost entirely refactoring and message changing, with the single behavioral change of panicking for unexpected output. --- src/librustc_parse/parser/expr.rs | 62 +++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index d7d3145770c..76e4a80878f 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -551,8 +551,8 @@ impl<'a> Parser<'a> { // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); - let type_result = match self.parse_ty_no_plus() { - Ok(rhs) => Ok(mk_expr(self, rhs)), + let cast_expr = match self.parse_ty_no_plus() { + Ok(rhs) => mk_expr(self, rhs), Err(mut type_err) => { // Rewind to before attempting to parse the type with generics, to recover // from situations like `x as usize < y` in which we first tried to parse @@ -606,41 +606,63 @@ impl<'a> Parser<'a> { ) .emit(); - Ok(expr) + expr } Err(mut path_err) => { // Couldn't parse as a path, return original error and parser state. path_err.cancel(); mem::replace(self, parser_snapshot_after_type); - Err(type_err) + return Err(type_err); } } } }; - // Disallow postfix operators such as `.`, `?` or index (`[]`) after casts. - // Parses the postfix operator and emits an error. - let expr = type_result?; - let span = expr.span; + self.parse_and_disallow_postfix_after_cast(cast_expr) + } - // The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. - let with_postfix = self.parse_dot_or_call_expr_with_(expr, span)?; - if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { + /// Parses a postfix operators such as `.`, `?`, or index (`[]`) after a cast, + /// then emits an error and returns the newly parsed tree. + /// The resulting parse tree for `&x as T[0]` has a precedence of `((&x) as T)[0]`. + fn parse_and_disallow_postfix_after_cast( + &mut self, + cast_expr: P, + ) -> PResult<'a, P> { + use std::collections::hash_map::DefaultHasher; + use std::hash::Hasher; + // Hash the memory location of expr before parsing any following postfix operators. + // This will be compared with the hash of the output expression. + // If they different we can assume we parsed another expression because the existing expression is not reallocated. + let mut before_hasher = DefaultHasher::new(); + std::ptr::hash(&*cast_expr, &mut before_hasher); + let before_hash = before_hasher.finish(); + let span = cast_expr.span; + let with_postfix = self.parse_dot_or_call_expr_with_(cast_expr, span)?; + + let mut after_hasher = DefaultHasher::new(); + std::ptr::hash(&*with_postfix, &mut after_hasher); + let after_hash = after_hasher.finish(); + + // Check if an illegal postfix operator has been added after the cast. + // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. + if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) || after_hash != before_hash { let expr_str = self.span_to_snippet(span); let msg = format!( - "casts followed by {} are not supported", + "casts cannot be followed by {}", match with_postfix.kind { - ExprKind::Index(_, _) => "index operators", - ExprKind::Try(_) => "try operators", - ExprKind::Field(_, _) => "field access expressions", - ExprKind::MethodCall(_, _) => "method call expressions", - ExprKind::Await(_) => "awaits", - _ => "expressions", + ExprKind::Index(_, _) => "indexing", + ExprKind::Try(_) => "?", + ExprKind::Field(_, _) => "a field access", + ExprKind::MethodCall(_, _) => "a method call", + ExprKind::Call(_, _) => "a function call", + ExprKind::Await(_) => "`.await`", + ref kind => + unreachable!("parse_dot_or_call_expr_with_ shouldn't produce a {:?}", kind), } ); - let mut err = self.struct_span_err(with_postfix.span, &msg); - let suggestion = "try surrounding the expression with parentheses"; + let mut err = self.struct_span_err(span, &msg); + let suggestion = "try surrounding the expression in parentheses"; if let Ok(expr_str) = expr_str { err.span_suggestion( span, From 4fc0532269f40c2870936faaebcdd14539613411 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:18:20 -0800 Subject: [PATCH 0239/1250] Type ascription outputs a Type, not Cast Previously this just errored out on all usages of type ascription, which isn't helpful. --- src/librustc_parse/parser/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 76e4a80878f..645e680d15f 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -645,7 +645,9 @@ impl<'a> Parser<'a> { // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, or has a different memory location, it is an illegal postfix operator. - if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) || after_hash != before_hash { + if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) + || after_hash != before_hash + { let expr_str = self.span_to_snippet(span); let msg = format!( From 0cf204930a2ecaa5f7416602fca6054d4fd44b6b Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:18:50 -0800 Subject: [PATCH 0240/1250] Keep better fix suggestion if type ascription is likely unintended --- src/librustc_parse/parser/expr.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 645e680d15f..fe5570f26ab 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -665,17 +665,23 @@ impl<'a> Parser<'a> { ); let mut err = self.struct_span_err(span, &msg); let suggestion = "try surrounding the expression in parentheses"; - if let Ok(expr_str) = expr_str { - err.span_suggestion( - span, - suggestion, - format!("({})", expr_str), - Applicability::MachineApplicable, - ) + // if type ascription is "likely an error", the user will already be getting a useful + // help message, and doesn't need a second. + if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { + self.maybe_annotate_with_ascription(&mut err, false); } else { - err.span_help(span, suggestion) + if let Ok(expr_str) = expr_str { + err.span_suggestion( + span, + suggestion, + format!("({})", expr_str), + Applicability::MachineApplicable, + ); + } else { + err.span_help(span, suggestion); + } } - .emit(); + err.emit(); }; Ok(with_postfix) } From f82ca8b0efa64bc33ed811b34c83a21aeb2950d1 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:20:53 -0800 Subject: [PATCH 0241/1250] Add more error cases to issue 35813 tests --- .../parser/issue-35813-postfix-after-cast.rs | 100 ++++++++-- .../issue-35813-postfix-after-cast.stderr | 183 +++++++++++++----- 2 files changed, 225 insertions(+), 58 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index dd608b263ec..0083a475ddf 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -1,5 +1,6 @@ // edition:2018 #![crate_type = "lib"] +#![feature(type_ascription)] use std::future::Future; use std::pin::Pin; @@ -7,47 +8,122 @@ use std::pin::Pin; // errors and parse such that further code gives useful errors. pub fn index_after_as_cast() { vec![1, 2, 3] as Vec[0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing + vec![1, 2, 3]: Vec[0]; + //~^ ERROR: casts cannot be followed by indexing } pub fn index_after_cast_to_index() { (&[0]) as &[i32][0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing + (&[0i32]): &[i32; 1][0]; + //~^ ERROR: casts cannot be followed by indexing +} + +pub fn cast_after_cast() { + if 5u64 as i32 as u16 == 0u16 { + + } + if 5u64: u64: u64 == 0u64 { + + } + let _ = 5u64: u64: u64 as u8 as i8 == 9i8; + let _ = 0i32: i32: i32; + let _ = 0 as i32: i32; + let _ = 0i32: i32 as i32; + let _ = 0 as i32 as i32; + let _ = 0i32: i32: i32 as u32 as i32; } // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; - //~^ ERROR: casts followed by index operators are not supported + //~^ ERROR: casts cannot be followed by indexing +} + +pub fn method_calls() { + 0 as i32.max(0); + //~^ ERROR: casts cannot be followed by a method call + 0: i32.max(0); + //~^ ERROR: casts cannot be followed by a method call } pub fn complex() { let _ = format!( - "{}", - if true { 33 } else { 44 } as i32.max(0) - //~^ ERROR: casts followed by method call expressions are not supported + "{} and {}", + if true { 33 } else { 44 } as i32.max(0), + //~^ ERROR: casts cannot be followed by a method call + if true { 33 } else { 44 }: i32.max(0) + //~^ ERROR: casts cannot be followed by a method call ); } pub fn in_condition() { if 5u64 as i32.max(0) == 0 { - //~^ ERROR: casts followed by method call expressions are not supported + //~^ ERROR: casts cannot be followed by a method call + } + if 5u64: u64.max(0) == 0 { + //~^ ERROR: casts cannot be followed by a method call } } pub fn inside_block() { let _ = if true { 5u64 as u32.max(0) == 0 - //~^ ERROR: casts followed by method call expressions are not supported + //~^ ERROR: casts cannot be followed by a method call + } else { false }; + let _ = if true { + 5u64: u64.max(0) == 0 + //~^ ERROR: casts cannot be followed by a method call } else { false }; } static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); -//~^ ERROR: casts followed by index operators are not supported +//~^ ERROR: casts cannot be followed by indexing + +static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); +//~^ ERROR: casts cannot be followed by indexing + + +pub fn cast_then_try() -> Result { + Err(0u64) as Result?; + //~^ ERROR: casts cannot be followed by ? + Err(0u64): Result?; + //~^ ERROR: casts cannot be followed by ? + Ok(1) +} + + +pub fn cast_then_call() { + type F = fn(u8); + // type ascription won't actually do [unique drop fn type] -> fn(u8) casts. + let drop_ptr = drop as fn(u8); + drop as F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] + drop_ptr: F(); + //~^ ERROR: parenthesized type parameters may only be used with a `Fn` trait [E0214] +} + +pub fn cast_to_fn_should_work() { + let drop_ptr = drop as fn(u8); + drop as fn(u8); + drop_ptr: fn(u8); +} + +pub fn parens_after_cast_error() { + let drop_ptr = drop as fn(u8); + drop as fn(u8)(0); + //~^ ERROR: casts cannot be followed by a function call + drop_ptr: fn(u8)(0); + //~^ ERROR: casts cannot be followed by a function call +} pub async fn cast_then_await() { Box::pin(noop()) as Pin>>.await; - //~^ ERROR: casts followed by awaits are not supported + //~^ ERROR: casts cannot be followed by `.await` + + Box::pin(noop()): Pin>.await; + //~^ ERROR: casts cannot be followed by `.await` } pub async fn noop() {} @@ -59,5 +135,7 @@ pub struct Foo { pub fn struct_field() { Foo::default() as Foo.bar; - //~^ ERROR: casts followed by field access expressions are not supported + //~^ ERROR: cannot be followed by a field access + Foo::default(): Foo.bar; + //~^ ERROR: cannot be followed by a field access } diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index 9459e076ea0..ec6c4eb8107 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -1,74 +1,163 @@ -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:9:5 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:10:5 | LL | vec![1, 2, 3] as Vec[0]; - | -------------------------^^^ - | | - | help: try surrounding the expression with parentheses: `(vec![1, 2, 3] as Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3] as Vec)` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:14:5 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:12:5 + | +LL | vec![1, 2, 3]: Vec[0]; + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3]: Vec)` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:17:5 | LL | (&[0]) as &[i32][0]; - | ----------------^^^ - | | - | help: try surrounding the expression with parentheses: `((&[0]) as &[i32])` + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0]) as &[i32])` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:20:18 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:19:5 + | +LL | (&[0i32]): &[i32; 1][0]; + | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:40:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; - | ---------------------------^^^ - | | - | help: try surrounding the expression with parentheses: `(&vec![1, 2, 3] as &Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:33:8 +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:45:5 + | +LL | 0 as i32.max(0); + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:47:5 + | +LL | 0: i32.max(0); + | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:62:8 | LL | if 5u64 as i32.max(0) == 0 { - | -----------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(5u64 as i32)` + | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:40:9 +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:65:8 + | +LL | if 5u64: u64.max(0) == 0 { + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:72:9 | LL | 5u64 as u32.max(0) == 0 - | -----------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(5u64 as u32)` + | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:76:9 + | +LL | 5u64: u64.max(0) == 0 + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` -error: casts followed by index operators are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:45:24 +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:81:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); - | ------------------^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(&[1,2,3] as &[i32])` + | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` + +error: casts cannot be followed by indexing + --> $DIR/issue-35813-postfix-after-cast.rs:84:25 + | +LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` + +error: casts cannot be followed by ? + --> $DIR/issue-35813-postfix-after-cast.rs:89:5 + | +LL | Err(0u64) as Result?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` + +error: casts cannot be followed by ? + --> $DIR/issue-35813-postfix-after-cast.rs:91:5 + | +LL | Err(0u64): Result?; + | ^^^^^^^^^-^^^^^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 -error: casts followed by awaits are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:49:5 +error: casts cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:115:5 + | +LL | drop as fn(u8)(0); + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` + +error: casts cannot be followed by a function call + --> $DIR/issue-35813-postfix-after-cast.rs:117:5 + | +LL | drop_ptr: fn(u8)(0); + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` + +error: casts cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:122:5 | LL | Box::pin(noop()) as Pin>>.await; - | -----------------------------------------------------^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(Box::pin(noop()) as Pin>>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` + +error: casts cannot be followed by `.await` + --> $DIR/issue-35813-postfix-after-cast.rs:125:5 + | +LL | Box::pin(noop()): Pin>.await; + | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 -error: casts followed by field access expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:61:5 +error: casts cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:137:5 | LL | Foo::default() as Foo.bar; - | ---------------------^^^^ - | | - | help: try surrounding the expression with parentheses: `(Foo::default() as Foo)` + | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` + +error: casts cannot be followed by a field access + --> $DIR/issue-35813-postfix-after-cast.rs:139:5 + | +LL | Foo::default(): Foo.bar; + | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:54:9 + | +LL | if true { 33 } else { 44 } as i32.max(0), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:56:9 + | +LL | if true { 33 } else { 44 }: i32.max(0) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` + +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:101:13 + | +LL | drop as F(); + | ^^^ only `Fn` traits may use parentheses -error: casts followed by method call expressions are not supported - --> $DIR/issue-35813-postfix-after-cast.rs:27:9 +error[E0214]: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-35813-postfix-after-cast.rs:103:15 | -LL | if true { 33 } else { 44 } as i32.max(0) - | ---------------------------------^^^^^^^ - | | - | help: try surrounding the expression with parentheses: `(if true { 33 } else { 44 } as i32)` +LL | drop_ptr: F(); + | ^^^ only `Fn` traits may use parentheses -error: aborting due to 9 previous errors +error: aborting due to 25 previous errors +For more information about this error, try `rustc --explain E0214`. From 5dd646435ba882574e677acf58113880a6570949 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 16:21:59 -0800 Subject: [PATCH 0242/1250] Fix related type ascription tests. --- src/test/ui/type/ascription/issue-54516.rs | 4 ++- .../ui/type/ascription/issue-54516.stderr | 26 ++++++++++++++++--- src/test/ui/type/ascription/issue-60933.rs | 4 ++- .../ui/type/ascription/issue-60933.stderr | 26 ++++++++++++++++--- 4 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs index b53bfe5df03..8d6fd2abb6d 100644 --- a/src/test/ui/type/ascription/issue-54516.rs +++ b/src/test/ui/type/ascription/issue-54516.rs @@ -2,5 +2,7 @@ use std::collections::BTreeMap; fn main() { println!("{}", std::mem:size_of::>()); - //~^ ERROR expected one of + //~^ ERROR casts cannot be followed by a function call + //~| ERROR expected value, found module `std::mem` [E0423] + //~| ERROR cannot find type `size_of` in this scope [E0412] } diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr index 7127f67cd7d..fdf35700ef9 100644 --- a/src/test/ui/type/ascription/issue-54516.stderr +++ b/src/test/ui/type/ascription/issue-54516.stderr @@ -1,13 +1,31 @@ -error: expected one of `!`, `,`, or `::`, found `(` - --> $DIR/issue-54516.rs:4:58 +error: casts cannot be followed by a function call + --> $DIR/issue-54516.rs:4:20 | LL | println!("{}", std::mem:size_of::>()); - | - ^ expected one of `!`, `,`, or `::` + | ^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` = note: see issue #23416 for more information -error: aborting due to previous error +error[E0423]: expected value, found module `std::mem` + --> $DIR/issue-54516.rs:4:20 + | +LL | println!("{}", std::mem:size_of::>()); + | ^^^^^^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error[E0412]: cannot find type `size_of` in this scope + --> $DIR/issue-54516.rs:4:29 + | +LL | println!("{}", std::mem:size_of::>()); + | -^^^^^^^ not found in this scope + | | + | help: maybe you meant to write a path separator here: `::` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. diff --git a/src/test/ui/type/ascription/issue-60933.rs b/src/test/ui/type/ascription/issue-60933.rs index 8fb06c887bd..bcf9f88cb41 100644 --- a/src/test/ui/type/ascription/issue-60933.rs +++ b/src/test/ui/type/ascription/issue-60933.rs @@ -1,4 +1,6 @@ fn main() { let u: usize = std::mem:size_of::(); - //~^ ERROR expected one of + //~^ ERROR casts cannot be followed by a function call + //~| ERROR expected value, found module `std::mem` [E0423] + //~| ERROR cannot find type `size_of` in this scope [E0412] } diff --git a/src/test/ui/type/ascription/issue-60933.stderr b/src/test/ui/type/ascription/issue-60933.stderr index 7130767b6c6..cd9ae8f49f4 100644 --- a/src/test/ui/type/ascription/issue-60933.stderr +++ b/src/test/ui/type/ascription/issue-60933.stderr @@ -1,13 +1,31 @@ -error: expected one of `!`, `::`, or `;`, found `(` - --> $DIR/issue-60933.rs:2:43 +error: casts cannot be followed by a function call + --> $DIR/issue-60933.rs:2:20 | LL | let u: usize = std::mem:size_of::(); - | - ^ expected one of `!`, `::`, or `;` + | ^^^^^^^^-^^^^^^^^^^^^^^ | | | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` = note: see issue #23416 for more information -error: aborting due to previous error +error[E0423]: expected value, found module `std::mem` + --> $DIR/issue-60933.rs:2:20 + | +LL | let u: usize = std::mem:size_of::(); + | ^^^^^^^^- help: maybe you meant to write a path separator here: `::` + | | + | not a value + +error[E0412]: cannot find type `size_of` in this scope + --> $DIR/issue-60933.rs:2:29 + | +LL | let u: usize = std::mem:size_of::(); + | -^^^^^^^ not found in this scope + | | + | help: maybe you meant to write a path separator here: `::` + +error: aborting due to 3 previous errors +Some errors have detailed explanations: E0412, E0423. +For more information about an error, try `rustc --explain E0412`. From e3eefe266756449ebe3b2c1bb177f0130569b3b2 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 17:09:42 -0800 Subject: [PATCH 0243/1250] Remove extra debug print in unreachable! --- src/librustc_parse/parser/expr.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index fe5570f26ab..3d0f746d395 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -659,8 +659,7 @@ impl<'a> Parser<'a> { ExprKind::MethodCall(_, _) => "a method call", ExprKind::Call(_, _) => "a function call", ExprKind::Await(_) => "`.await`", - ref kind => - unreachable!("parse_dot_or_call_expr_with_ shouldn't produce a {:?}", kind), + _ => unreachable!("parse_dot_or_call_expr_with_ shouldn't produce this"), } ); let mut err = self.struct_span_err(span, &msg); From c2d7ffb8a9906f5c7b6a1cf6a739cf4d7d732c2b Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 17:17:09 -0800 Subject: [PATCH 0244/1250] Remove trailing whitespace --- src/test/ui/parser/issue-35813-postfix-after-cast.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index 0083a475ddf..d04a092e93b 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -22,10 +22,10 @@ pub fn index_after_cast_to_index() { pub fn cast_after_cast() { if 5u64 as i32 as u16 == 0u16 { - + } if 5u64: u64: u64 == 0u64 { - + } let _ = 5u64: u64: u64 as u8 as i8 == 9i8; let _ = 0i32: i32: i32; @@ -107,7 +107,7 @@ pub fn cast_then_call() { pub fn cast_to_fn_should_work() { let drop_ptr = drop as fn(u8); drop as fn(u8); - drop_ptr: fn(u8); + drop_ptr: fn(u8); } pub fn parens_after_cast_error() { From 8ef3da0858c5a76fd1756b9efcf82eeb9491fb64 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 15 Feb 2020 22:08:29 -0800 Subject: [PATCH 0245/1250] Fix test stderr after rebasing on master. --- src/test/ui/parser/issue-35813-postfix-after-cast.stderr | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index ec6c4eb8107..f96000ea0aa 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -91,7 +91,7 @@ LL | Err(0u64): Result?; | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + = note: see issue #23416 for more information error: casts cannot be followed by a function call --> $DIR/issue-35813-postfix-after-cast.rs:115:5 @@ -120,7 +120,7 @@ LL | Box::pin(noop()): Pin>.await; | help: maybe write a path separator here: `::` | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` - = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + = note: see issue #23416 for more information error: casts cannot be followed by a field access --> $DIR/issue-35813-postfix-after-cast.rs:137:5 From d5691209b6d5fe5e47560b1db7b822dbeb0880fd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 20:13:24 +0100 Subject: [PATCH 0246/1250] Move librustc/{traits,infer} to librustc_infer. --- src/{librustc => librustc_infer}/infer/at.rs | 0 src/{librustc => librustc_infer}/infer/canonical/canonicalizer.rs | 0 src/{librustc => librustc_infer}/infer/canonical/mod.rs | 0 .../infer/canonical/query_response.rs | 0 src/{librustc => librustc_infer}/infer/canonical/substitute.rs | 0 src/{librustc => librustc_infer}/infer/combine.rs | 0 src/{librustc => librustc_infer}/infer/equate.rs | 0 src/{librustc => librustc_infer}/infer/error_reporting/mod.rs | 0 .../infer/error_reporting/need_type_info.rs | 0 .../error_reporting/nice_region_error/different_lifetimes.rs | 0 .../infer/error_reporting/nice_region_error/find_anon_type.rs | 0 .../infer/error_reporting/nice_region_error/mod.rs | 0 .../error_reporting/nice_region_error/named_anon_conflict.rs | 0 .../infer/error_reporting/nice_region_error/outlives_closure.rs | 0 .../infer/error_reporting/nice_region_error/placeholder_error.rs | 0 .../infer/error_reporting/nice_region_error/static_impl_trait.rs | 0 .../error_reporting/nice_region_error/trait_impl_difference.rs | 0 .../infer/error_reporting/nice_region_error/util.rs | 0 src/{librustc => librustc_infer}/infer/error_reporting/note.rs | 0 src/{librustc => librustc_infer}/infer/freshen.rs | 0 src/{librustc => librustc_infer}/infer/fudge.rs | 0 src/{librustc => librustc_infer}/infer/glb.rs | 0 src/{librustc => librustc_infer}/infer/higher_ranked/README.md | 0 src/{librustc => librustc_infer}/infer/higher_ranked/mod.rs | 0 src/{librustc => librustc_infer}/infer/lattice.rs | 0 .../infer/lexical_region_resolve/README.md | 0 .../infer/lexical_region_resolve/graphviz.rs | 0 .../infer/lexical_region_resolve/mod.rs | 0 src/{librustc => librustc_infer}/infer/lub.rs | 0 src/{librustc => librustc_infer}/infer/mod.rs | 0 src/{librustc => librustc_infer}/infer/nll_relate/mod.rs | 0 src/{librustc => librustc_infer}/infer/opaque_types/mod.rs | 0 src/{librustc => librustc_infer}/infer/outlives/env.rs | 0 src/{librustc => librustc_infer}/infer/outlives/mod.rs | 0 src/{librustc => librustc_infer}/infer/outlives/obligations.rs | 0 src/{librustc => librustc_infer}/infer/outlives/verify.rs | 0 .../infer/region_constraints/README.md | 0 .../infer/region_constraints/leak_check.rs | 0 src/{librustc => librustc_infer}/infer/region_constraints/mod.rs | 0 src/{librustc => librustc_infer}/infer/resolve.rs | 0 src/{librustc => librustc_infer}/infer/sub.rs | 0 src/{librustc => librustc_infer}/infer/type_variable.rs | 0 src/{librustc => librustc_infer}/traits/auto_trait.rs | 0 src/{librustc => librustc_infer}/traits/chalk_fulfill.rs | 0 src/{librustc => librustc_infer}/traits/codegen/mod.rs | 0 src/{librustc => librustc_infer}/traits/coherence.rs | 0 src/{librustc => librustc_infer}/traits/engine.rs | 0 src/{librustc => librustc_infer}/traits/error_reporting/mod.rs | 0 .../traits/error_reporting/on_unimplemented.rs | 0 .../traits/error_reporting/suggestions.rs | 0 src/{librustc => librustc_infer}/traits/fulfill.rs | 0 src/{librustc => librustc_infer}/traits/misc.rs | 0 src/{librustc => librustc_infer}/traits/mod.rs | 0 src/{librustc => librustc_infer}/traits/object_safety.rs | 0 src/{librustc => librustc_infer}/traits/on_unimplemented.rs | 0 src/{librustc => librustc_infer}/traits/project.rs | 0 src/{librustc => librustc_infer}/traits/query/dropck_outlives.rs | 0 .../traits/query/evaluate_obligation.rs | 0 src/{librustc => librustc_infer}/traits/query/method_autoderef.rs | 0 src/{librustc => librustc_infer}/traits/query/mod.rs | 0 src/{librustc => librustc_infer}/traits/query/normalize.rs | 0 src/{librustc => librustc_infer}/traits/query/outlives_bounds.rs | 0 .../traits/query/type_op/ascribe_user_type.rs | 0 src/{librustc => librustc_infer}/traits/query/type_op/custom.rs | 0 src/{librustc => librustc_infer}/traits/query/type_op/eq.rs | 0 .../traits/query/type_op/implied_outlives_bounds.rs | 0 src/{librustc => librustc_infer}/traits/query/type_op/mod.rs | 0 .../traits/query/type_op/normalize.rs | 0 src/{librustc => librustc_infer}/traits/query/type_op/outlives.rs | 0 .../traits/query/type_op/prove_predicate.rs | 0 src/{librustc => librustc_infer}/traits/query/type_op/subtype.rs | 0 src/{librustc => librustc_infer}/traits/select.rs | 0 src/{librustc => librustc_infer}/traits/specialize/mod.rs | 0 .../traits/specialize/specialization_graph.rs | 0 src/{librustc => librustc_infer}/traits/structural_impls.rs | 0 src/{librustc => librustc_infer}/traits/structural_match.rs | 0 src/{librustc => librustc_infer}/traits/util.rs | 0 src/{librustc => librustc_infer}/traits/wf.rs | 0 78 files changed, 0 insertions(+), 0 deletions(-) rename src/{librustc => librustc_infer}/infer/at.rs (100%) rename src/{librustc => librustc_infer}/infer/canonical/canonicalizer.rs (100%) rename src/{librustc => librustc_infer}/infer/canonical/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/canonical/query_response.rs (100%) rename src/{librustc => librustc_infer}/infer/canonical/substitute.rs (100%) rename src/{librustc => librustc_infer}/infer/combine.rs (100%) rename src/{librustc => librustc_infer}/infer/equate.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/need_type_info.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/different_lifetimes.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/find_anon_type.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/named_anon_conflict.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/outlives_closure.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/placeholder_error.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/static_impl_trait.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/trait_impl_difference.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/nice_region_error/util.rs (100%) rename src/{librustc => librustc_infer}/infer/error_reporting/note.rs (100%) rename src/{librustc => librustc_infer}/infer/freshen.rs (100%) rename src/{librustc => librustc_infer}/infer/fudge.rs (100%) rename src/{librustc => librustc_infer}/infer/glb.rs (100%) rename src/{librustc => librustc_infer}/infer/higher_ranked/README.md (100%) rename src/{librustc => librustc_infer}/infer/higher_ranked/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/lattice.rs (100%) rename src/{librustc => librustc_infer}/infer/lexical_region_resolve/README.md (100%) rename src/{librustc => librustc_infer}/infer/lexical_region_resolve/graphviz.rs (100%) rename src/{librustc => librustc_infer}/infer/lexical_region_resolve/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/lub.rs (100%) rename src/{librustc => librustc_infer}/infer/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/nll_relate/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/opaque_types/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/outlives/env.rs (100%) rename src/{librustc => librustc_infer}/infer/outlives/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/outlives/obligations.rs (100%) rename src/{librustc => librustc_infer}/infer/outlives/verify.rs (100%) rename src/{librustc => librustc_infer}/infer/region_constraints/README.md (100%) rename src/{librustc => librustc_infer}/infer/region_constraints/leak_check.rs (100%) rename src/{librustc => librustc_infer}/infer/region_constraints/mod.rs (100%) rename src/{librustc => librustc_infer}/infer/resolve.rs (100%) rename src/{librustc => librustc_infer}/infer/sub.rs (100%) rename src/{librustc => librustc_infer}/infer/type_variable.rs (100%) rename src/{librustc => librustc_infer}/traits/auto_trait.rs (100%) rename src/{librustc => librustc_infer}/traits/chalk_fulfill.rs (100%) rename src/{librustc => librustc_infer}/traits/codegen/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/coherence.rs (100%) rename src/{librustc => librustc_infer}/traits/engine.rs (100%) rename src/{librustc => librustc_infer}/traits/error_reporting/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/error_reporting/on_unimplemented.rs (100%) rename src/{librustc => librustc_infer}/traits/error_reporting/suggestions.rs (100%) rename src/{librustc => librustc_infer}/traits/fulfill.rs (100%) rename src/{librustc => librustc_infer}/traits/misc.rs (100%) rename src/{librustc => librustc_infer}/traits/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/object_safety.rs (100%) rename src/{librustc => librustc_infer}/traits/on_unimplemented.rs (100%) rename src/{librustc => librustc_infer}/traits/project.rs (100%) rename src/{librustc => librustc_infer}/traits/query/dropck_outlives.rs (100%) rename src/{librustc => librustc_infer}/traits/query/evaluate_obligation.rs (100%) rename src/{librustc => librustc_infer}/traits/query/method_autoderef.rs (100%) rename src/{librustc => librustc_infer}/traits/query/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/query/normalize.rs (100%) rename src/{librustc => librustc_infer}/traits/query/outlives_bounds.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/ascribe_user_type.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/custom.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/eq.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/implied_outlives_bounds.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/normalize.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/outlives.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/prove_predicate.rs (100%) rename src/{librustc => librustc_infer}/traits/query/type_op/subtype.rs (100%) rename src/{librustc => librustc_infer}/traits/select.rs (100%) rename src/{librustc => librustc_infer}/traits/specialize/mod.rs (100%) rename src/{librustc => librustc_infer}/traits/specialize/specialization_graph.rs (100%) rename src/{librustc => librustc_infer}/traits/structural_impls.rs (100%) rename src/{librustc => librustc_infer}/traits/structural_match.rs (100%) rename src/{librustc => librustc_infer}/traits/util.rs (100%) rename src/{librustc => librustc_infer}/traits/wf.rs (100%) diff --git a/src/librustc/infer/at.rs b/src/librustc_infer/infer/at.rs similarity index 100% rename from src/librustc/infer/at.rs rename to src/librustc_infer/infer/at.rs diff --git a/src/librustc/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs similarity index 100% rename from src/librustc/infer/canonical/canonicalizer.rs rename to src/librustc_infer/infer/canonical/canonicalizer.rs diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs similarity index 100% rename from src/librustc/infer/canonical/mod.rs rename to src/librustc_infer/infer/canonical/mod.rs diff --git a/src/librustc/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs similarity index 100% rename from src/librustc/infer/canonical/query_response.rs rename to src/librustc_infer/infer/canonical/query_response.rs diff --git a/src/librustc/infer/canonical/substitute.rs b/src/librustc_infer/infer/canonical/substitute.rs similarity index 100% rename from src/librustc/infer/canonical/substitute.rs rename to src/librustc_infer/infer/canonical/substitute.rs diff --git a/src/librustc/infer/combine.rs b/src/librustc_infer/infer/combine.rs similarity index 100% rename from src/librustc/infer/combine.rs rename to src/librustc_infer/infer/combine.rs diff --git a/src/librustc/infer/equate.rs b/src/librustc_infer/infer/equate.rs similarity index 100% rename from src/librustc/infer/equate.rs rename to src/librustc_infer/infer/equate.rs diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs similarity index 100% rename from src/librustc/infer/error_reporting/mod.rs rename to src/librustc_infer/infer/error_reporting/mod.rs diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs similarity index 100% rename from src/librustc/infer/error_reporting/need_type_info.rs rename to src/librustc_infer/infer/error_reporting/need_type_info.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/different_lifetimes.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/find_anon_type.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/mod.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/named_anon_conflict.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/outlives_closure.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/placeholder_error.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/static_impl_trait.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/trait_impl_difference.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs diff --git a/src/librustc/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs similarity index 100% rename from src/librustc/infer/error_reporting/nice_region_error/util.rs rename to src/librustc_infer/infer/error_reporting/nice_region_error/util.rs diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs similarity index 100% rename from src/librustc/infer/error_reporting/note.rs rename to src/librustc_infer/infer/error_reporting/note.rs diff --git a/src/librustc/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs similarity index 100% rename from src/librustc/infer/freshen.rs rename to src/librustc_infer/infer/freshen.rs diff --git a/src/librustc/infer/fudge.rs b/src/librustc_infer/infer/fudge.rs similarity index 100% rename from src/librustc/infer/fudge.rs rename to src/librustc_infer/infer/fudge.rs diff --git a/src/librustc/infer/glb.rs b/src/librustc_infer/infer/glb.rs similarity index 100% rename from src/librustc/infer/glb.rs rename to src/librustc_infer/infer/glb.rs diff --git a/src/librustc/infer/higher_ranked/README.md b/src/librustc_infer/infer/higher_ranked/README.md similarity index 100% rename from src/librustc/infer/higher_ranked/README.md rename to src/librustc_infer/infer/higher_ranked/README.md diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs similarity index 100% rename from src/librustc/infer/higher_ranked/mod.rs rename to src/librustc_infer/infer/higher_ranked/mod.rs diff --git a/src/librustc/infer/lattice.rs b/src/librustc_infer/infer/lattice.rs similarity index 100% rename from src/librustc/infer/lattice.rs rename to src/librustc_infer/infer/lattice.rs diff --git a/src/librustc/infer/lexical_region_resolve/README.md b/src/librustc_infer/infer/lexical_region_resolve/README.md similarity index 100% rename from src/librustc/infer/lexical_region_resolve/README.md rename to src/librustc_infer/infer/lexical_region_resolve/README.md diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs similarity index 100% rename from src/librustc/infer/lexical_region_resolve/graphviz.rs rename to src/librustc_infer/infer/lexical_region_resolve/graphviz.rs diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs similarity index 100% rename from src/librustc/infer/lexical_region_resolve/mod.rs rename to src/librustc_infer/infer/lexical_region_resolve/mod.rs diff --git a/src/librustc/infer/lub.rs b/src/librustc_infer/infer/lub.rs similarity index 100% rename from src/librustc/infer/lub.rs rename to src/librustc_infer/infer/lub.rs diff --git a/src/librustc/infer/mod.rs b/src/librustc_infer/infer/mod.rs similarity index 100% rename from src/librustc/infer/mod.rs rename to src/librustc_infer/infer/mod.rs diff --git a/src/librustc/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs similarity index 100% rename from src/librustc/infer/nll_relate/mod.rs rename to src/librustc_infer/infer/nll_relate/mod.rs diff --git a/src/librustc/infer/opaque_types/mod.rs b/src/librustc_infer/infer/opaque_types/mod.rs similarity index 100% rename from src/librustc/infer/opaque_types/mod.rs rename to src/librustc_infer/infer/opaque_types/mod.rs diff --git a/src/librustc/infer/outlives/env.rs b/src/librustc_infer/infer/outlives/env.rs similarity index 100% rename from src/librustc/infer/outlives/env.rs rename to src/librustc_infer/infer/outlives/env.rs diff --git a/src/librustc/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs similarity index 100% rename from src/librustc/infer/outlives/mod.rs rename to src/librustc_infer/infer/outlives/mod.rs diff --git a/src/librustc/infer/outlives/obligations.rs b/src/librustc_infer/infer/outlives/obligations.rs similarity index 100% rename from src/librustc/infer/outlives/obligations.rs rename to src/librustc_infer/infer/outlives/obligations.rs diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs similarity index 100% rename from src/librustc/infer/outlives/verify.rs rename to src/librustc_infer/infer/outlives/verify.rs diff --git a/src/librustc/infer/region_constraints/README.md b/src/librustc_infer/infer/region_constraints/README.md similarity index 100% rename from src/librustc/infer/region_constraints/README.md rename to src/librustc_infer/infer/region_constraints/README.md diff --git a/src/librustc/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs similarity index 100% rename from src/librustc/infer/region_constraints/leak_check.rs rename to src/librustc_infer/infer/region_constraints/leak_check.rs diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs similarity index 100% rename from src/librustc/infer/region_constraints/mod.rs rename to src/librustc_infer/infer/region_constraints/mod.rs diff --git a/src/librustc/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs similarity index 100% rename from src/librustc/infer/resolve.rs rename to src/librustc_infer/infer/resolve.rs diff --git a/src/librustc/infer/sub.rs b/src/librustc_infer/infer/sub.rs similarity index 100% rename from src/librustc/infer/sub.rs rename to src/librustc_infer/infer/sub.rs diff --git a/src/librustc/infer/type_variable.rs b/src/librustc_infer/infer/type_variable.rs similarity index 100% rename from src/librustc/infer/type_variable.rs rename to src/librustc_infer/infer/type_variable.rs diff --git a/src/librustc/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs similarity index 100% rename from src/librustc/traits/auto_trait.rs rename to src/librustc_infer/traits/auto_trait.rs diff --git a/src/librustc/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs similarity index 100% rename from src/librustc/traits/chalk_fulfill.rs rename to src/librustc_infer/traits/chalk_fulfill.rs diff --git a/src/librustc/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs similarity index 100% rename from src/librustc/traits/codegen/mod.rs rename to src/librustc_infer/traits/codegen/mod.rs diff --git a/src/librustc/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs similarity index 100% rename from src/librustc/traits/coherence.rs rename to src/librustc_infer/traits/coherence.rs diff --git a/src/librustc/traits/engine.rs b/src/librustc_infer/traits/engine.rs similarity index 100% rename from src/librustc/traits/engine.rs rename to src/librustc_infer/traits/engine.rs diff --git a/src/librustc/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs similarity index 100% rename from src/librustc/traits/error_reporting/mod.rs rename to src/librustc_infer/traits/error_reporting/mod.rs diff --git a/src/librustc/traits/error_reporting/on_unimplemented.rs b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs similarity index 100% rename from src/librustc/traits/error_reporting/on_unimplemented.rs rename to src/librustc_infer/traits/error_reporting/on_unimplemented.rs diff --git a/src/librustc/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs similarity index 100% rename from src/librustc/traits/error_reporting/suggestions.rs rename to src/librustc_infer/traits/error_reporting/suggestions.rs diff --git a/src/librustc/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs similarity index 100% rename from src/librustc/traits/fulfill.rs rename to src/librustc_infer/traits/fulfill.rs diff --git a/src/librustc/traits/misc.rs b/src/librustc_infer/traits/misc.rs similarity index 100% rename from src/librustc/traits/misc.rs rename to src/librustc_infer/traits/misc.rs diff --git a/src/librustc/traits/mod.rs b/src/librustc_infer/traits/mod.rs similarity index 100% rename from src/librustc/traits/mod.rs rename to src/librustc_infer/traits/mod.rs diff --git a/src/librustc/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs similarity index 100% rename from src/librustc/traits/object_safety.rs rename to src/librustc_infer/traits/object_safety.rs diff --git a/src/librustc/traits/on_unimplemented.rs b/src/librustc_infer/traits/on_unimplemented.rs similarity index 100% rename from src/librustc/traits/on_unimplemented.rs rename to src/librustc_infer/traits/on_unimplemented.rs diff --git a/src/librustc/traits/project.rs b/src/librustc_infer/traits/project.rs similarity index 100% rename from src/librustc/traits/project.rs rename to src/librustc_infer/traits/project.rs diff --git a/src/librustc/traits/query/dropck_outlives.rs b/src/librustc_infer/traits/query/dropck_outlives.rs similarity index 100% rename from src/librustc/traits/query/dropck_outlives.rs rename to src/librustc_infer/traits/query/dropck_outlives.rs diff --git a/src/librustc/traits/query/evaluate_obligation.rs b/src/librustc_infer/traits/query/evaluate_obligation.rs similarity index 100% rename from src/librustc/traits/query/evaluate_obligation.rs rename to src/librustc_infer/traits/query/evaluate_obligation.rs diff --git a/src/librustc/traits/query/method_autoderef.rs b/src/librustc_infer/traits/query/method_autoderef.rs similarity index 100% rename from src/librustc/traits/query/method_autoderef.rs rename to src/librustc_infer/traits/query/method_autoderef.rs diff --git a/src/librustc/traits/query/mod.rs b/src/librustc_infer/traits/query/mod.rs similarity index 100% rename from src/librustc/traits/query/mod.rs rename to src/librustc_infer/traits/query/mod.rs diff --git a/src/librustc/traits/query/normalize.rs b/src/librustc_infer/traits/query/normalize.rs similarity index 100% rename from src/librustc/traits/query/normalize.rs rename to src/librustc_infer/traits/query/normalize.rs diff --git a/src/librustc/traits/query/outlives_bounds.rs b/src/librustc_infer/traits/query/outlives_bounds.rs similarity index 100% rename from src/librustc/traits/query/outlives_bounds.rs rename to src/librustc_infer/traits/query/outlives_bounds.rs diff --git a/src/librustc/traits/query/type_op/ascribe_user_type.rs b/src/librustc_infer/traits/query/type_op/ascribe_user_type.rs similarity index 100% rename from src/librustc/traits/query/type_op/ascribe_user_type.rs rename to src/librustc_infer/traits/query/type_op/ascribe_user_type.rs diff --git a/src/librustc/traits/query/type_op/custom.rs b/src/librustc_infer/traits/query/type_op/custom.rs similarity index 100% rename from src/librustc/traits/query/type_op/custom.rs rename to src/librustc_infer/traits/query/type_op/custom.rs diff --git a/src/librustc/traits/query/type_op/eq.rs b/src/librustc_infer/traits/query/type_op/eq.rs similarity index 100% rename from src/librustc/traits/query/type_op/eq.rs rename to src/librustc_infer/traits/query/type_op/eq.rs diff --git a/src/librustc/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs similarity index 100% rename from src/librustc/traits/query/type_op/implied_outlives_bounds.rs rename to src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs diff --git a/src/librustc/traits/query/type_op/mod.rs b/src/librustc_infer/traits/query/type_op/mod.rs similarity index 100% rename from src/librustc/traits/query/type_op/mod.rs rename to src/librustc_infer/traits/query/type_op/mod.rs diff --git a/src/librustc/traits/query/type_op/normalize.rs b/src/librustc_infer/traits/query/type_op/normalize.rs similarity index 100% rename from src/librustc/traits/query/type_op/normalize.rs rename to src/librustc_infer/traits/query/type_op/normalize.rs diff --git a/src/librustc/traits/query/type_op/outlives.rs b/src/librustc_infer/traits/query/type_op/outlives.rs similarity index 100% rename from src/librustc/traits/query/type_op/outlives.rs rename to src/librustc_infer/traits/query/type_op/outlives.rs diff --git a/src/librustc/traits/query/type_op/prove_predicate.rs b/src/librustc_infer/traits/query/type_op/prove_predicate.rs similarity index 100% rename from src/librustc/traits/query/type_op/prove_predicate.rs rename to src/librustc_infer/traits/query/type_op/prove_predicate.rs diff --git a/src/librustc/traits/query/type_op/subtype.rs b/src/librustc_infer/traits/query/type_op/subtype.rs similarity index 100% rename from src/librustc/traits/query/type_op/subtype.rs rename to src/librustc_infer/traits/query/type_op/subtype.rs diff --git a/src/librustc/traits/select.rs b/src/librustc_infer/traits/select.rs similarity index 100% rename from src/librustc/traits/select.rs rename to src/librustc_infer/traits/select.rs diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs similarity index 100% rename from src/librustc/traits/specialize/mod.rs rename to src/librustc_infer/traits/specialize/mod.rs diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc_infer/traits/specialize/specialization_graph.rs similarity index 100% rename from src/librustc/traits/specialize/specialization_graph.rs rename to src/librustc_infer/traits/specialize/specialization_graph.rs diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc_infer/traits/structural_impls.rs similarity index 100% rename from src/librustc/traits/structural_impls.rs rename to src/librustc_infer/traits/structural_impls.rs diff --git a/src/librustc/traits/structural_match.rs b/src/librustc_infer/traits/structural_match.rs similarity index 100% rename from src/librustc/traits/structural_match.rs rename to src/librustc_infer/traits/structural_match.rs diff --git a/src/librustc/traits/util.rs b/src/librustc_infer/traits/util.rs similarity index 100% rename from src/librustc/traits/util.rs rename to src/librustc_infer/traits/util.rs diff --git a/src/librustc/traits/wf.rs b/src/librustc_infer/traits/wf.rs similarity index 100% rename from src/librustc/traits/wf.rs rename to src/librustc_infer/traits/wf.rs From 187a9741d3cd63dd78571e2a0e08344aef05f51b Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 20:13:24 +0100 Subject: [PATCH 0247/1250] Make librustc compile. --- src/librustc/arena.rs | 6 +++--- src/librustc/infer/{types => }/canonical.rs | 2 +- src/librustc/infer/{types => }/mod.rs | 1 + src/librustc/lib.rs | 4 ---- src/librustc/traits/{types => }/mod.rs | 3 +++ src/librustc/traits/{types => }/query.rs | 0 src/librustc/traits/{types => }/select.rs | 0 src/librustc/traits/{types => }/specialization_graph.rs | 0 src/librustc/traits/{types => }/structural_impls.rs | 0 src/librustc/ty/query/mod.rs | 8 ++++---- 10 files changed, 12 insertions(+), 12 deletions(-) rename src/librustc/infer/{types => }/canonical.rs (99%) rename src/librustc/infer/{types => }/mod.rs (97%) rename src/librustc/traits/{types => }/mod.rs (99%) rename src/librustc/traits/{types => }/query.rs (100%) rename src/librustc/traits/{types => }/select.rs (100%) rename src/librustc/traits/{types => }/specialization_graph.rs (100%) rename src/librustc/traits/{types => }/structural_impls.rs (100%) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 33cbf6ede0a..f5c83fed1fc 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -51,19 +51,19 @@ macro_rules! arena_types { [] dropck_outlives: rustc::infer::canonical::Canonical<'tcx, rustc::infer::canonical::QueryResponse<'tcx, - rustc::traits::query::dropck_outlives::DropckOutlivesResult<'tcx> + rustc::traits::query::DropckOutlivesResult<'tcx> > >, [] normalize_projection_ty: rustc::infer::canonical::Canonical<'tcx, rustc::infer::canonical::QueryResponse<'tcx, - rustc::traits::query::normalize::NormalizationResult<'tcx> + rustc::traits::query::NormalizationResult<'tcx> > >, [] implied_outlives_bounds: rustc::infer::canonical::Canonical<'tcx, rustc::infer::canonical::QueryResponse<'tcx, - Vec> + Vec> > >, [] type_op_subtype: diff --git a/src/librustc/infer/types/canonical.rs b/src/librustc/infer/canonical.rs similarity index 99% rename from src/librustc/infer/types/canonical.rs rename to src/librustc/infer/canonical.rs index 133cf1b5928..76d0d57e233 100644 --- a/src/librustc/infer/types/canonical.rs +++ b/src/librustc/infer/canonical.rs @@ -21,7 +21,7 @@ //! //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html -use crate::infer::region_constraints::MemberConstraint; +use crate::infer::MemberConstraint; use crate::ty::subst::GenericArg; use crate::ty::{self, BoundVar, List, Region, TyCtxt}; use rustc_index::vec::IndexVec; diff --git a/src/librustc/infer/types/mod.rs b/src/librustc/infer/mod.rs similarity index 97% rename from src/librustc/infer/types/mod.rs rename to src/librustc/infer/mod.rs index 534f4cb179c..497d3811f28 100644 --- a/src/librustc/infer/types/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1,4 +1,5 @@ pub mod canonical; +pub mod unify_key; use crate::ty::Region; use crate::ty::Ty; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ceac68704d2..e1e774b853c 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -13,10 +13,6 @@ //! defined in the `ty` module. This includes the **type context** //! (or `tcx`), which is the central context during most of //! compilation, containing the interners and other things. -//! - **Traits.** Trait resolution is implemented in the `traits` module. -//! - **Type inference.** The type inference code can be found in the `infer` module; -//! this code handles low-level equality and subtyping operations. The -//! type check pass in the compiler is found in the `librustc_typeck` crate. //! //! For more information about how rustc works, see the [rustc guide]. //! diff --git a/src/librustc/traits/types/mod.rs b/src/librustc/traits/mod.rs similarity index 99% rename from src/librustc/traits/types/mod.rs rename to src/librustc/traits/mod.rs index 571fb505779..c000aa7c25e 100644 --- a/src/librustc/traits/types/mod.rs +++ b/src/librustc/traits/mod.rs @@ -7,6 +7,7 @@ pub mod select; pub mod specialization_graph; mod structural_impls; +use crate::infer::canonical::Canonical; use crate::mir::interpret::ErrorHandled; use crate::ty::fold::{TypeFolder, TypeVisitor}; use crate::ty::subst::SubstsRef; @@ -22,6 +23,8 @@ use std::rc::Rc; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; +pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, InEnvironment<'tcx, ty::Predicate<'tcx>>>; + pub use self::ObligationCauseCode::*; pub use self::SelectionError::*; pub use self::Vtable::*; diff --git a/src/librustc/traits/types/query.rs b/src/librustc/traits/query.rs similarity index 100% rename from src/librustc/traits/types/query.rs rename to src/librustc/traits/query.rs diff --git a/src/librustc/traits/types/select.rs b/src/librustc/traits/select.rs similarity index 100% rename from src/librustc/traits/types/select.rs rename to src/librustc/traits/select.rs diff --git a/src/librustc/traits/types/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs similarity index 100% rename from src/librustc/traits/types/specialization_graph.rs rename to src/librustc/traits/specialization_graph.rs diff --git a/src/librustc/traits/types/structural_impls.rs b/src/librustc/traits/structural_impls.rs similarity index 100% rename from src/librustc/traits/types/structural_impls.rs rename to src/librustc/traits/structural_impls.rs diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index ddaaab412a4..125ee316ed8 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -19,15 +19,15 @@ use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use crate::session::CrateDisambiguator; -use crate::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint}; -use crate::traits::query::method_autoderef::MethodAutoderefStepsResult; -use crate::traits::query::normalize::NormalizationResult; -use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, CanonicalTypeOpProvePredicateGoal, CanonicalTypeOpSubtypeGoal, NoSolution, }; +use crate::traits::query::{ + DropckOutlivesResult, DtorckConstraint, MethodAutoderefStepsResult, NormalizationResult, + OutlivesBound, +}; use crate::traits::specialization_graph; use crate::traits::Clauses; use crate::traits::{self, Vtable}; From f07e8891458259bb4373bb6aa59d158304f637b1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 20:13:24 +0100 Subject: [PATCH 0248/1250] Make librustc_infer compile. --- Cargo.lock | 30 +++++++++ src/librustc_infer/Cargo.toml | 28 ++++++++ src/librustc_infer/infer/canonical/mod.rs | 5 +- .../infer/canonical/query_response.rs | 8 +-- .../infer/canonical/substitute.rs | 29 ++++++-- .../infer/error_reporting/mod.rs | 16 +++-- .../infer/error_reporting/note.rs | 8 +-- src/librustc_infer/infer/mod.rs | 39 ++++++----- .../infer/outlives/obligations.rs | 2 + src/librustc_infer/infer/outlives/verify.rs | 2 + .../infer/region_constraints/mod.rs | 10 +-- src/librustc_infer/lib.rs | 67 +++++++++++++++++++ src/librustc_infer/traits/chalk_fulfill.rs | 4 +- src/librustc_infer/traits/codegen/mod.rs | 2 +- src/librustc_infer/traits/coherence.rs | 2 +- .../traits/error_reporting/mod.rs | 17 +++-- src/librustc_infer/traits/misc.rs | 3 +- src/librustc_infer/traits/mod.rs | 13 ++-- src/librustc_infer/traits/object_safety.rs | 1 + src/librustc_infer/traits/query/mod.rs | 2 +- .../traits/query/type_op/mod.rs | 2 +- src/librustc_infer/traits/select.rs | 2 +- src/librustc_infer/traits/specialize/mod.rs | 3 +- .../traits/specialize/specialization_graph.rs | 59 +++++++++++----- src/librustc_infer/traits/structural_match.rs | 9 ++- src/librustc_infer/traits/util.rs | 1 + src/librustc_lint/Cargo.toml | 1 + src/librustc_mir/Cargo.toml | 1 + src/librustc_mir_build/Cargo.toml | 1 + src/librustc_passes/Cargo.toml | 1 + src/librustc_resolve/Cargo.toml | 1 + src/librustc_traits/Cargo.toml | 1 + src/librustc_ty/Cargo.toml | 1 + src/librustc_typeck/Cargo.toml | 1 + 34 files changed, 284 insertions(+), 88 deletions(-) create mode 100644 src/librustc_infer/Cargo.toml create mode 100644 src/librustc_infer/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 2847e3cfb04..f8b4eca99ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3776,6 +3776,28 @@ dependencies = [ "smallvec 1.0.0", ] +[[package]] +name = "rustc_infer" +version = "0.0.0" +dependencies = [ + "fmt_macros", + "graphviz", + "log", + "rustc", + "rustc_attr", + "rustc_data_structures", + "rustc_error_codes", + "rustc_errors", + "rustc_hir", + "rustc_index", + "rustc_macros", + "rustc_session", + "rustc_span", + "rustc_target", + "smallvec 1.0.0", + "syntax", +] + [[package]] name = "rustc_interface" version = "0.0.0" @@ -3838,6 +3860,7 @@ dependencies = [ "rustc_feature", "rustc_hir", "rustc_index", + "rustc_infer", "rustc_session", "rustc_span", "rustc_target", @@ -3907,6 +3930,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_infer", "rustc_lexer", "rustc_macros", "rustc_span", @@ -3929,6 +3953,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_infer", "rustc_macros", "rustc_session", "rustc_span", @@ -3969,6 +3994,7 @@ dependencies = [ "rustc_feature", "rustc_hir", "rustc_index", + "rustc_infer", "rustc_session", "rustc_span", "rustc_target", @@ -4019,6 +4045,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_hir", + "rustc_infer", "rustc_metadata", "rustc_session", "rustc_span", @@ -4108,6 +4135,7 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_hir", + "rustc_infer", "rustc_macros", "rustc_span", "rustc_target", @@ -4123,6 +4151,7 @@ dependencies = [ "rustc", "rustc_data_structures", "rustc_hir", + "rustc_infer", "rustc_span", "rustc_target", ] @@ -4139,6 +4168,7 @@ dependencies = [ "rustc_errors", "rustc_hir", "rustc_index", + "rustc_infer", "rustc_span", "rustc_target", "smallvec 1.0.0", diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml new file mode 100644 index 00000000000..53970a4aaf3 --- /dev/null +++ b/src/librustc_infer/Cargo.toml @@ -0,0 +1,28 @@ +[package] +authors = ["The Rust Project Developers"] +name = "rustc_infer" +version = "0.0.0" +edition = "2018" + +[lib] +name = "rustc_infer" +path = "lib.rs" +doctest = false + +[dependencies] +fmt_macros = { path = "../libfmt_macros" } +graphviz = { path = "../libgraphviz" } +log = { version = "0.4", features = ["release_max_level_info", "std"] } +rustc_attr = { path = "../librustc_attr" } +rustc = { path = "../librustc" } +rustc_data_structures = { path = "../librustc_data_structures" } +rustc_errors = { path = "../librustc_errors" } +rustc_error_codes = { path = "../librustc_error_codes" } +rustc_hir = { path = "../librustc_hir" } +rustc_index = { path = "../librustc_index" } +rustc_macros = { path = "../librustc_macros" } +rustc_session = { path = "../librustc_session" } +rustc_span = { path = "../librustc_span" } +rustc_target = { path = "../librustc_target" } +smallvec = { version = "1.0", features = ["union", "may_dangle"] } +syntax = { path = "../libsyntax" } diff --git a/src/librustc_infer/infer/canonical/mod.rs b/src/librustc_infer/infer/canonical/mod.rs index f157d805bcd..ba019a8cf03 100644 --- a/src/librustc_infer/infer/canonical/mod.rs +++ b/src/librustc_infer/infer/canonical/mod.rs @@ -29,12 +29,11 @@ use rustc::ty::{self, BoundVar, List}; use rustc_index::vec::IndexVec; use rustc_span::source_map::Span; -pub use rustc::infer::types::canonical::*; +pub use rustc::infer::canonical::*; +use substitute::CanonicalExt; mod canonicalizer; - pub mod query_response; - mod substitute; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index 012900f8af5..5dc98cb6feb 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -8,7 +8,7 @@ //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use crate::arena::ArenaAllocatable; -use crate::infer::canonical::substitute::substitute_value; +use crate::infer::canonical::substitute::{substitute_value, CanonicalExt}; use crate::infer::canonical::{ Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty, OriginalQueryValues, QueryOutlivesConstraint, QueryRegionConstraints, QueryResponse, @@ -19,9 +19,9 @@ use crate::infer::{InferCtxt, InferOk, InferResult}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; -use crate::ty::fold::TypeFoldable; -use crate::ty::subst::{GenericArg, GenericArgKind}; -use crate::ty::{self, BoundVar, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::{GenericArg, GenericArgKind}; +use rustc::ty::{self, BoundVar, Ty, TyCtxt}; use rustc_data_structures::captures::Captures; use rustc_index::vec::Idx; use rustc_index::vec::IndexVec; diff --git a/src/librustc_infer/infer/canonical/substitute.rs b/src/librustc_infer/infer/canonical/substitute.rs index 92516345633..92066048261 100644 --- a/src/librustc_infer/infer/canonical/substitute.rs +++ b/src/librustc_infer/infer/canonical/substitute.rs @@ -11,15 +11,12 @@ use crate::ty::fold::TypeFoldable; use crate::ty::subst::GenericArgKind; use crate::ty::{self, TyCtxt}; -impl<'tcx, V> Canonical<'tcx, V> { +pub(super) trait CanonicalExt<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value /// with the value given in `var_values`. - pub fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V + fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V where - V: TypeFoldable<'tcx>, - { - self.substitute_projected(tcx, var_values, |value| value) - } + V: TypeFoldable<'tcx>; /// Allows one to apply a substitute to some subset of /// `self.value`. Invoke `projection_fn` with `self.value` to get @@ -27,7 +24,25 @@ impl<'tcx, V> Canonical<'tcx, V> { /// variables bound in `self` (usually this extracts from subset /// of `self`). Apply the substitution `var_values` to this value /// V, replacing each of the canonical variables. - pub fn substitute_projected( + fn substitute_projected( + &self, + tcx: TyCtxt<'tcx>, + var_values: &CanonicalVarValues<'tcx>, + projection_fn: impl FnOnce(&V) -> &T, + ) -> T + where + T: TypeFoldable<'tcx>; +} + +impl<'tcx, V> CanonicalExt<'tcx, V> for Canonical<'tcx, V> { + fn substitute(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V + where + V: TypeFoldable<'tcx>, + { + self.substitute_projected(tcx, var_values, |value| value) + } + + fn substitute_projected( &self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>, diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 327e1da64c4..77119b8618f 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -49,17 +49,18 @@ use super::lexical_region_resolve::RegionResolutionError; use super::region_constraints::GenericKind; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; -use crate::hir::map; use crate::infer::opaque_types; use crate::infer::{self, SuppressRegionErrors}; -use crate::middle::region; use crate::traits::error_reporting::report_object_safety_error; use crate::traits::object_safety_violations; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; -use crate::ty::error::TypeError; -use crate::ty::{ + +use rustc::hir::map; +use rustc::middle::region; +use rustc::ty::error::TypeError; +use rustc::ty::{ self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable, @@ -2005,7 +2006,12 @@ enum FailureCode { Error0644(&'static str), } -impl<'tcx> ObligationCause<'tcx> { +trait ObligationCauseExt<'tcx> { + fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode; + fn as_requirement_str(&self) -> &'static str; +} + +impl<'tcx> ObligationCauseExt<'tcx> for ObligationCause<'tcx> { fn as_failure_code(&self, terr: &TypeError<'tcx>) -> FailureCode { use self::FailureCode::*; use crate::traits::ObligationCauseCode::*; diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 11dda71b8cb..7a7cfdecbaf 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -1,8 +1,8 @@ -use crate::infer::error_reporting::note_and_explain_region; +use crate::infer::error_reporting::{note_and_explain_region, ObligationCauseExt}; use crate::infer::{self, InferCtxt, SubregionOrigin}; -use crate::middle::region; -use crate::ty::error::TypeError; -use crate::ty::{self, Region}; +use rustc::middle::region; +use rustc::ty::error::TypeError; +use rustc::ty::{self, Region}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; impl<'a, 'tcx> InferCtxt<'a, 'tcx> { diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index be58de996a5..b7f83625757 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -7,19 +7,21 @@ pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; pub use crate::ty::IntVarValue; -use crate::infer::canonical::{Canonical, CanonicalVarValues}; -use crate::infer::unify_key::{ConstVarValue, ConstVariableValue}; -use crate::middle::free_region::RegionRelations; -use crate::middle::lang_items; -use crate::middle::region; -use crate::session::config::BorrowckMode; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; -use crate::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; -use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::relate::RelateResult; -use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; -use crate::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; -use crate::ty::{ConstVid, FloatVid, IntVid, TyVid}; + +use rustc::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc::infer::unify_key::{ConstVarValue, ConstVariableValue}; +use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; +use rustc::middle::free_region::RegionRelations; +use rustc::middle::lang_items; +use rustc::middle::region; +use rustc::session::config::BorrowckMode; +use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::relate::RelateResult; +use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; +use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; +use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -40,7 +42,6 @@ use self::outlives::env::OutlivesEnvironment; use self::region_constraints::{GenericKind, RegionConstraintData, VarInfos, VerifyBound}; use self::region_constraints::{RegionConstraintCollector, RegionSnapshot}; use self::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use self::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType}; pub mod at; pub mod canonical; @@ -61,8 +62,8 @@ pub mod region_constraints; pub mod resolve; mod sub; pub mod type_variable; -mod types; -pub mod unify_key; + +pub use rustc::infer::unify_key; #[must_use] #[derive(Debug)] @@ -524,8 +525,12 @@ pub struct InferCtxtBuilder<'tcx> { fresh_tables: Option>>, } -impl TyCtxt<'tcx> { - pub fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { +pub trait TyCtxtInferExt<'tcx> { + fn infer_ctxt(self) -> InferCtxtBuilder<'tcx>; +} + +impl TyCtxtInferExt<'tcx> for TyCtxt<'tcx> { + fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> { InferCtxtBuilder { global_tcx: self, fresh_tables: None } } } diff --git a/src/librustc_infer/infer/outlives/obligations.rs b/src/librustc_infer/infer/outlives/obligations.rs index 17153ef9724..88733f1901a 100644 --- a/src/librustc_infer/infer/outlives/obligations.rs +++ b/src/librustc_infer/infer/outlives/obligations.rs @@ -66,8 +66,10 @@ use crate::traits::ObligationCause; use crate::ty::outlives::Component; use crate::ty::subst::GenericArgKind; use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; + use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; +use smallvec::smallvec; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// Registers that the given region obligation must be resolved diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index a2c99064caa..4a05bfc64b1 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -6,6 +6,8 @@ use crate::ty::{self, Ty, TyCtxt}; use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; +use smallvec::smallvec; + /// The `TypeOutlives` struct has the job of "lowering" a `T: 'a` /// obligation into a series of `'a: 'b` constraints and "verifys", as /// described on the module comment. The final constraints are emitted diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 8379a73bb9e..af4e199f288 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -6,10 +6,10 @@ use self::UndoLog::*; use super::unify_key; use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin}; -use crate::ty::ReStatic; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::{ReLateBound, ReVar}; -use crate::ty::{Region, RegionVid}; +use rustc::ty::ReStatic; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{ReLateBound, ReVar}; +use rustc::ty::{Region, RegionVid}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; use rustc_data_structures::unify as ut; @@ -23,7 +23,7 @@ use std::{cmp, fmt, mem}; mod leak_check; -pub use rustc::infer::types::MemberConstraint; +pub use rustc::infer::MemberConstraint; #[derive(Default)] pub struct RegionConstraintCollector<'tcx> { diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs new file mode 100644 index 00000000000..d64c9e2f90b --- /dev/null +++ b/src/librustc_infer/lib.rs @@ -0,0 +1,67 @@ +//! This crates defines the trait resolution method and the type inference engine. +//! +//! - **Traits.** Trait resolution is implemented in the `traits` module. +//! - **Type inference.** The type inference code can be found in the `infer` module; +//! this code handles low-level equality and subtyping operations. The +//! type check pass in the compiler is found in the `librustc_typeck` crate. +//! +//! For more information about how rustc works, see the [rustc guide]. +//! +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/ +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(arbitrary_self_types)] +#![feature(bool_to_option)] +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(const_fn)] +#![feature(const_transmute)] +#![feature(core_intrinsics)] +#![feature(drain_filter)] +#![cfg_attr(windows, feature(libc))] +#![feature(never_type)] +#![feature(exhaustive_patterns)] +#![feature(overlapping_marker_traits)] +#![feature(extern_types)] +#![feature(nll)] +#![feature(optin_builtin_traits)] +#![feature(option_expect_none)] +#![feature(range_is_empty)] +#![feature(specialization)] +#![feature(unboxed_closures)] +#![feature(thread_local)] +#![feature(trace_macros)] +#![feature(trusted_len)] +#![feature(stmt_expr_attributes)] +#![feature(integer_atomics)] +#![feature(test)] +#![feature(in_band_lifetimes)] +#![feature(crate_visibility_modifier)] +#![feature(log_syntax)] +#![feature(associated_type_bounds)] +#![feature(rustc_attrs)] +#![feature(hash_raw_entry)] +#![recursion_limit = "512"] + +#[macro_use] +extern crate rustc_macros; +#[macro_use] +extern crate rustc_data_structures; +#[macro_use] +extern crate log; +#[macro_use] +extern crate rustc; + +use rustc::arena; +use rustc::dep_graph; +use rustc::hir; +pub mod infer; +use rustc::middle; +pub use rustc_session as session; +pub mod traits; +use rustc::ty; +use rustc::util; diff --git a/src/librustc_infer/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs index a765e55d99f..b28523d955d 100644 --- a/src/librustc_infer/traits/chalk_fulfill.rs +++ b/src/librustc_infer/traits/chalk_fulfill.rs @@ -1,4 +1,4 @@ -use crate::infer::canonical::{Canonical, OriginalQueryValues}; +use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::query::NoSolution; use crate::traits::{ @@ -8,7 +8,7 @@ use crate::traits::{ use crate::ty::{self, Ty}; use rustc_data_structures::fx::FxHashSet; -pub type CanonicalGoal<'tcx> = Canonical<'tcx, InEnvironment<'tcx, ty::Predicate<'tcx>>>; +pub use rustc::traits::ChalkCanonicalGoal as CanonicalGoal; pub struct FulfillmentContext<'tcx> { obligations: FxHashSet>>, diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs index 8a264a79fb6..4f6c9428fc2 100644 --- a/src/librustc_infer/traits/codegen/mod.rs +++ b/src/librustc_infer/traits/codegen/mod.rs @@ -3,7 +3,7 @@ // seems likely that they should eventually be merged into more // general routines. -use crate::infer::InferCtxt; +use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable, }; diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs index 2a667b53550..cafdb0353d5 100644 --- a/src/librustc_infer/traits/coherence.rs +++ b/src/librustc_infer/traits/coherence.rs @@ -4,7 +4,7 @@ //! [trait-resolution]: https://rust-lang.github.io/rustc-guide/traits/resolution.html //! [trait-specialization]: https://rust-lang.github.io/rustc-guide/traits/specialization.html -use crate::infer::{CombinedSnapshot, InferOk}; +use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::SkipLeakCheck; use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext}; diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index c25b392ec23..4bc8ffc3d2f 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -11,18 +11,17 @@ use super::{ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use crate::infer::{self, InferCtxt}; -use crate::mir::interpret::ErrorHandled; -use crate::session::DiagnosticMessageId; +use crate::infer::{self, InferCtxt, TyCtxtInferExt}; use crate::traits::object_safety_violations; -use crate::ty::error::ExpectedFound; -use crate::ty::fast_reject; -use crate::ty::fold::TypeFolder; -use crate::ty::SubtypePredicate; -use crate::ty::{ +use rustc::mir::interpret::ErrorHandled; +use rustc::session::DiagnosticMessageId; +use rustc::ty::error::ExpectedFound; +use rustc::ty::fast_reject; +use rustc::ty::fold::TypeFolder; +use rustc::ty::SubtypePredicate; +use rustc::ty::{ self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; diff --git a/src/librustc_infer/traits/misc.rs b/src/librustc_infer/traits/misc.rs index 3fd0d12c626..7ab918c159e 100644 --- a/src/librustc_infer/traits/misc.rs +++ b/src/librustc_infer/traits/misc.rs @@ -1,8 +1,9 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. +use crate::infer::TyCtxtInferExt; use crate::traits::{self, ObligationCause}; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; #[derive(Clone)] diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 556e69b04f8..6226d38f88e 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -19,12 +19,11 @@ mod select; mod specialize; mod structural_impls; mod structural_match; -mod types; mod util; pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; -use crate::infer::{InferCtxt, SuppressRegionErrors}; +use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; use crate::middle::region; use crate::ty::error::{ExpectedFound, TypeError}; use crate::ty::fold::TypeFoldable; @@ -38,6 +37,9 @@ use rustc_span::{Span, DUMMY_SP}; use std::fmt::Debug; pub use self::FulfillmentErrorCode::*; +pub use self::ObligationCauseCode::*; +pub use self::SelectionError::*; +pub use self::Vtable::*; pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; pub use self::coherence::{OrphanCheckErr, OverlapResult}; @@ -53,8 +55,9 @@ pub use self::project::MismatchedProjectionTypes; pub use self::project::{ normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type, }; -pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot}; -pub use self::select::{IntercrateAmbiguityCause, SelectionContext}; +pub use self::project::{Normalized, ProjectionCache, ProjectionCacheSnapshot, Reveal}; +pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; +pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::find_associated_item; pub use self::specialize::specialization_graph::FutureCompatOverlapError; pub use self::specialize::specialization_graph::FutureCompatOverlapErrorKind; @@ -76,7 +79,7 @@ pub use self::chalk_fulfill::{ CanonicalGoal as ChalkCanonicalGoal, FulfillmentContext as ChalkFulfillmentContext, }; -pub use self::types::*; +pub use rustc::traits::*; /// Whether to skip the leak check, as part of a future compatibility warning step. #[derive(Copy, Clone, PartialEq, Eq, Debug)] diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index 4c5cd866b4a..e35b03a3431 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -10,6 +10,7 @@ use super::elaborate_predicates; +use crate::infer::TyCtxtInferExt; use crate::traits::{self, Obligation, ObligationCause}; use crate::ty::subst::{InternalSubsts, Subst}; use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; diff --git a/src/librustc_infer/traits/query/mod.rs b/src/librustc_infer/traits/query/mod.rs index 20a873dc4c6..77b5ec669a0 100644 --- a/src/librustc_infer/traits/query/mod.rs +++ b/src/librustc_infer/traits/query/mod.rs @@ -12,4 +12,4 @@ pub mod normalize; pub mod outlives_bounds; pub mod type_op; -pub use rustc::traits::types::query::*; +pub use rustc::traits::query::*; diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_infer/traits/query/type_op/mod.rs index 2d03d77cf66..5f131e97056 100644 --- a/src/librustc_infer/traits/query/type_op/mod.rs +++ b/src/librustc_infer/traits/query/type_op/mod.rs @@ -19,7 +19,7 @@ pub mod prove_predicate; use self::prove_predicate::ProvePredicate; pub mod subtype; -pub use crate::traits::types::query::type_op::*; +pub use rustc::traits::query::type_op::*; /// "Type ops" are used in NLL to perform some particular action and /// extract out the resulting region constraints (or an error if it diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index 1fe8ab58d15..9abf030ca38 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -54,7 +54,7 @@ use std::fmt::{self, Display}; use std::iter; use std::rc::Rc; -pub use rustc::traits::types::select::*; +pub use rustc::traits::select::*; pub struct SelectionContext<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs index 7c93a35158b..d300b6f6dd4 100644 --- a/src/librustc_infer/traits/specialize/mod.rs +++ b/src/librustc_infer/traits/specialize/mod.rs @@ -10,8 +10,9 @@ //! [rustc guide]: https://rust-lang.github.io/rustc-guide/traits/specialization.html pub mod specialization_graph; +use specialization_graph::GraphExt; -use crate::infer::{InferCtxt, InferOk}; +use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; use crate::ty::subst::{InternalSubsts, Subst, SubstsRef}; diff --git a/src/librustc_infer/traits/specialize/specialization_graph.rs b/src/librustc_infer/traits/specialize/specialization_graph.rs index e09bcdcbc62..17d4a22b9dd 100644 --- a/src/librustc_infer/traits/specialize/specialization_graph.rs +++ b/src/librustc_infer/traits/specialize/specialization_graph.rs @@ -5,7 +5,7 @@ use rustc::ty::fast_reject::{self, SimplifiedType}; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_hir::def_id::DefId; -pub use rustc::traits::types::specialization_graph::*; +pub use rustc::traits::specialization_graph::*; #[derive(Copy, Clone, Debug)] pub enum FutureCompatOverlapErrorKind { @@ -31,7 +31,19 @@ enum Inserted { ShouldRecurseOn(DefId), } -impl<'tcx> Children { +trait ChildrenExt { + fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); + fn remove_existing(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId); + + fn insert( + &mut self, + tcx: TyCtxt<'tcx>, + impl_def_id: DefId, + simplified_self: Option, + ) -> Result; +} + +impl ChildrenExt for Children { /// Insert an impl into this set of children without comparing to any existing impls. fn insert_blindly(&mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId) { let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap(); @@ -76,8 +88,8 @@ impl<'tcx> Children { debug!("insert(impl_def_id={:?}, simplified_self={:?})", impl_def_id, simplified_self,); let possible_siblings = match simplified_self { - Some(st) => PotentialSiblings::Filtered(self.filtered(st)), - None => PotentialSiblings::Unfiltered(self.iter()), + Some(st) => PotentialSiblings::Filtered(filtered_children(self, st)), + None => PotentialSiblings::Unfiltered(iter_children(self)), }; for possible_sibling in possible_siblings { @@ -199,16 +211,19 @@ impl<'tcx> Children { self.insert_blindly(tcx, impl_def_id); Ok(Inserted::BecameNewSibling(last_lint)) } +} - fn iter(&mut self) -> impl Iterator + '_ { - let nonblanket = self.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter()); - self.blanket_impls.iter().chain(nonblanket).cloned() - } +fn iter_children(children: &mut Children) -> impl Iterator + '_ { + let nonblanket = children.nonblanket_impls.iter_mut().flat_map(|(_, v)| v.iter()); + children.blanket_impls.iter().chain(nonblanket).cloned() +} - fn filtered(&mut self, st: SimplifiedType) -> impl Iterator + '_ { - let nonblanket = self.nonblanket_impls.entry(st).or_default().iter(); - self.blanket_impls.iter().chain(nonblanket).cloned() - } +fn filtered_children( + children: &mut Children, + st: SimplifiedType, +) -> impl Iterator + '_ { + let nonblanket = children.nonblanket_impls.entry(st).or_default().iter(); + children.blanket_impls.iter().chain(nonblanket).cloned() } // A custom iterator used by Children::insert @@ -236,11 +251,25 @@ where } } -impl<'tcx> Graph { +pub trait GraphExt { /// Insert a local impl into the specialization graph. If an existing impl /// conflicts with it (has overlap, but neither specializes the other), /// information about the area of overlap is returned in the `Err`. - pub fn insert( + fn insert( + &mut self, + tcx: TyCtxt<'tcx>, + impl_def_id: DefId, + ) -> Result, OverlapError>; + + /// Insert cached metadata mapping from a child impl back to its parent. + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId); +} + +impl GraphExt for Graph { + /// Insert a local impl into the specialization graph. If an existing impl + /// conflicts with it (has overlap, but neither specializes the other), + /// information about the area of overlap is returned in the `Err`. + fn insert( &mut self, tcx: TyCtxt<'tcx>, impl_def_id: DefId, @@ -337,7 +366,7 @@ impl<'tcx> Graph { } /// Insert cached metadata mapping from a child impl back to its parent. - pub fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) { + fn record_impl_from_cstore(&mut self, tcx: TyCtxt<'tcx>, parent: DefId, child: DefId) { if self.parent.insert(child, parent).is_some() { bug!( "When recording an impl from the crate store, information about its parent \ diff --git a/src/librustc_infer/traits/structural_match.rs b/src/librustc_infer/traits/structural_match.rs index b2c3c23b4e3..60682f58129 100644 --- a/src/librustc_infer/traits/structural_match.rs +++ b/src/librustc_infer/traits/structural_match.rs @@ -1,9 +1,8 @@ -use crate::ty::fold::{TypeFoldable, TypeVisitor}; -use crate::ty::{self, AdtDef, Ty, TyCtxt}; +use crate::infer::{InferCtxt, TyCtxtInferExt}; +use crate::traits::ObligationCause; +use crate::traits::{self, ConstPatternStructural, TraitEngine}; -use rustc::infer::InferCtxt; -use rustc::traits::ObligationCause; -use rustc::traits::{self, ConstPatternStructural, TraitEngine}; +use rustc::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_span::Span; diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index d4c3518260c..1c0638d4528 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -1,5 +1,6 @@ use rustc_errors::DiagnosticBuilder; use rustc_span::Span; +use smallvec::smallvec; use smallvec::SmallVec; use crate::ty::outlives::Component; diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index 27df0f904e4..1c2c241c000 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -23,3 +23,4 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_feature = { path = "../librustc_feature" } rustc_index = { path = "../librustc_index" } rustc_session = { path = "../librustc_session" } +rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 6b2e2bb919c..3554fe54c45 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -23,6 +23,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } +rustc_infer = { path = "../librustc_infer" } rustc_lexer = { path = "../librustc_lexer" } rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } diff --git a/src/librustc_mir_build/Cargo.toml b/src/librustc_mir_build/Cargo.toml index c109e9c618e..fac30637dd0 100644 --- a/src/librustc_mir_build/Cargo.toml +++ b/src/librustc_mir_build/Cargo.toml @@ -19,6 +19,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_index = { path = "../librustc_index" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } +rustc_infer = { path = "../librustc_infer" } rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_passes/Cargo.toml b/src/librustc_passes/Cargo.toml index 981ef7f8796..41718b21f52 100644 --- a/src/librustc_passes/Cargo.toml +++ b/src/librustc_passes/Cargo.toml @@ -17,6 +17,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } +rustc_infer = { path = "../librustc_infer" } rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index f8c96ecaf93..a40c3ca0f9e 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -24,6 +24,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_expand = { path = "../librustc_expand" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } +rustc_infer = { path = "../librustc_infer" } rustc_metadata = { path = "../librustc_metadata" } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 2cb25e63f83..40ca2ea90f2 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -19,3 +19,4 @@ syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } +rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml index 52606e5fdfe..6e64df3492b 100644 --- a/src/librustc_ty/Cargo.toml +++ b/src/librustc_ty/Cargo.toml @@ -13,5 +13,6 @@ log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_hir = { path = "../librustc_hir" } +rustc_infer = { path = "../librustc_infer" } rustc_span = { path = "../librustc_span" } rustc_target = { path = "../librustc_target" } diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 748bfcc7946..f1890f9f4e6 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -23,3 +23,4 @@ smallvec = { version = "1.0", features = ["union", "may_dangle"] } syntax = { path = "../libsyntax" } rustc_span = { path = "../librustc_span" } rustc_index = { path = "../librustc_index" } +rustc_infer = { path = "../librustc_infer" } From 4b57cb3cbed8674aa480bff450affa62ac6b75bf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 23:12:31 +0100 Subject: [PATCH 0249/1250] Make librustc_typeck compile. --- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/_match.rs | 6 +++--- src/librustc_typeck/check/autoderef.rs | 4 ++-- src/librustc_typeck/check/callee.rs | 4 ++-- src/librustc_typeck/check/cast.rs | 6 +++--- src/librustc_typeck/check/closure.rs | 10 +++++----- src/librustc_typeck/check/coercion.rs | 8 ++++---- src/librustc_typeck/check/compare_method.rs | 4 ++-- src/librustc_typeck/check/demand.rs | 4 ++-- src/librustc_typeck/check/dropck.rs | 7 +++---- src/librustc_typeck/check/expr.rs | 6 +++--- src/librustc_typeck/check/method/confirm.rs | 4 ++-- src/librustc_typeck/check/method/mod.rs | 4 ++-- src/librustc_typeck/check/method/probe.rs | 18 +++++++++--------- src/librustc_typeck/check/method/suggest.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 16 ++++++++-------- src/librustc_typeck/check/op.rs | 2 +- src/librustc_typeck/check/pat.rs | 6 +++--- src/librustc_typeck/check/regionck.rs | 4 ++-- src/librustc_typeck/check/upvar.rs | 2 +- src/librustc_typeck/check/wfcheck.rs | 6 +++--- src/librustc_typeck/check/writeback.rs | 4 ++-- src/librustc_typeck/coherence/builtin.rs | 12 ++++++------ .../coherence/inherent_impls_overlap.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 3 ++- src/librustc_typeck/collect/type_of.rs | 2 +- src/librustc_typeck/expr_use_visitor.rs | 2 +- src/librustc_typeck/lib.rs | 4 ++-- src/librustc_typeck/mem_categorization.rs | 3 ++- 30 files changed, 84 insertions(+), 83 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0e7c10541ca..c0574d6d9fd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -14,10 +14,6 @@ use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc::session::parse::feature_err; -use rustc::traits; -use rustc::traits::astconv_object_safety_violations; -use rustc::traits::error_reporting::report_object_safety_error; -use rustc::traits::wf::object_region_bounds; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -29,6 +25,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::print; use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; +use rustc_infer::traits; +use rustc_infer::traits::astconv_object_safety_violations; +use rustc_infer::traits::error_reporting::report_object_safety_error; +use rustc_infer::traits::wf::object_region_bounds; use rustc_span::symbol::sym; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 686cdfbc089..2c71fec6809 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -1,11 +1,11 @@ use crate::check::coercion::CoerceMany; use crate::check::{Diverges, Expectation, FnCtxt, Needs}; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::traits::ObligationCauseCode; -use rustc::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; use rustc::ty::Ty; use rustc_hir as hir; use rustc_hir::ExprKind; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::ObligationCauseCode; +use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; use rustc_span::Span; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index d436733d19a..00e91decf78 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -1,14 +1,14 @@ use super::method::MethodCallee; use super::{FnCtxt, Needs, PlaceOp}; -use rustc::infer::{InferCtxt, InferOk}; use rustc::session::DiagnosticMessageId; -use rustc::traits::{self, TraitEngine}; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc::ty::{ToPredicate, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_infer::traits::{self, TraitEngine}; use rustc_span::Span; use syntax::ast::Ident; diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index b33cc52b238..d0d07334fa5 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -3,15 +3,15 @@ use super::method::MethodCallee; use super::{Expectation, FnCtxt, Needs, TupleArgumentsFlag}; use crate::type_error_struct; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::{infer, traits}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::{infer, traits}; use rustc_span::Span; use rustc_target::spec::abi; use syntax::ast::Ident; diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 909f40ee984..18f6a78804b 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -36,9 +36,6 @@ use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; use rustc::session::Session; -use rustc::traits; -use rustc::traits::error_reporting::report_object_safety_error; -use rustc::traits::object_safety_violations; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; use rustc::ty::error::TypeError; @@ -46,6 +43,9 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_infer::traits; +use rustc_infer::traits::error_reporting::report_object_safety_error; +use rustc_infer::traits::object_safety_violations; use rustc_span::Span; use syntax::ast; diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 396534b3cae..ae6bed476f3 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -4,16 +4,16 @@ use super::{check_fn, Expectation, FnCtxt, GeneratorTypes}; use crate::astconv::AstConv; use crate::middle::{lang_items, region}; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::infer::LateBoundRegionConversionTime; -use rustc::infer::{InferOk, InferResult}; -use rustc::traits::error_reporting::ArgKind; -use rustc::traits::Obligation; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::InternalSubsts; use rustc::ty::{self, GenericParamDefKind, Ty}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::LateBoundRegionConversionTime; +use rustc_infer::infer::{InferOk, InferResult}; +use rustc_infer::traits::error_reporting::ArgKind; +use rustc_infer::traits::Obligation; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; use std::cmp; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index bedef5042fd..ce44fdab323 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -52,11 +52,7 @@ use crate::astconv::AstConv; use crate::check::{FnCtxt, Needs}; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::infer::{Coercion, InferOk, InferResult}; use rustc::session::parse::feature_err; -use rustc::traits::object_safety_violations; -use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -68,6 +64,10 @@ use rustc::ty::{self, Ty, TypeAndMut}; use rustc_errors::{struct_span_err, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{Coercion, InferOk, InferResult}; +use rustc_infer::traits::object_safety_violations; +use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 414f80d84b6..8b54b534375 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -1,6 +1,4 @@ use rustc::hir::map::Map; -use rustc::infer::{self, InferOk}; -use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::ExplicitSelf; @@ -11,6 +9,8 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; +use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc_span::Span; use super::{potentially_plural_count, FnCtxt, Inherited}; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 4a98095ec89..bf74ab696d6 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,6 +1,6 @@ use crate::check::FnCtxt; -use rustc::infer::InferOk; -use rustc::traits::{self, ObligationCause}; +use rustc_infer::infer::InferOk; +use rustc_infer::traits::{self, ObligationCause}; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::{self, AssocItem, Ty}; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 32773e2ed80..ead7536f8c6 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -2,16 +2,15 @@ use crate::check::regionck::RegionCtxt; use crate::hir; use crate::hir::def_id::DefId; use crate::util::common::ErrorReported; -use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::{InferOk, SuppressRegionErrors}; use rustc::middle::region; -use rustc::traits::{ObligationCause, TraitEngine, TraitEngineExt}; use rustc::ty::error::TypeError; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, Predicate, Ty, TyCtxt}; use rustc_errors::struct_span_err; - +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt}; use rustc_span::Span; /// This function confirms that the `Drop` implementation identified by diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 90b7b300da9..d947544d182 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -17,10 +17,7 @@ use crate::check::TupleArgumentsFlag::DontTupleArguments; use crate::type_error_struct; use crate::util::common::ErrorReported; -use rustc::infer; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::middle::lang_items; -use rustc::traits::{self, ObligationCauseCode}; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; @@ -32,6 +29,9 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, QPath}; +use rustc_infer::infer; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::{self, ObligationCauseCode}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Symbol}; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index eee9dc99d35..17842be9a43 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -4,14 +4,14 @@ use crate::astconv::AstConv; use crate::check::{callee, FnCtxt, Needs, PlaceOp}; use crate::hir::def_id::DefId; use crate::hir::GenericArg; -use rustc::infer::{self, InferOk}; -use rustc::traits; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref, PointerCast}; use rustc::ty::adjustment::{AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Ty}; use rustc_hir as hir; +use rustc_infer::infer::{self, InferOk}; +use rustc_infer::traits; use rustc_span::Span; use std::ops::Deref; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index c3e15c507b3..1856157fffb 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -12,8 +12,6 @@ pub use self::MethodError::*; use crate::check::FnCtxt; use crate::namespace::Namespace; -use rustc::infer::{self, InferOk}; -use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; @@ -23,6 +21,8 @@ use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind}; use rustc_hir::def_id::DefId; +use rustc_infer::infer::{self, InferOk}; +use rustc_infer::traits; use rustc_span::Span; use syntax::ast; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8f0fbc2d60c..346406fff56 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -9,18 +9,9 @@ use crate::hir::def::DefKind; use crate::hir::def_id::DefId; use crate::namespace::Namespace; -use rustc::infer::canonical::OriginalQueryValues; -use rustc::infer::canonical::{Canonical, QueryResponse}; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc::infer::{self, InferOk}; use rustc::lint; use rustc::middle::stability; use rustc::session::config::nightly_options; -use rustc::traits::query::method_autoderef::MethodAutoderefBadTy; -use rustc::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult}; -use rustc::traits::query::CanonicalTyGoal; -use rustc::traits::{self, ObligationCause}; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ @@ -31,6 +22,15 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_infer::infer::canonical::OriginalQueryValues; +use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_infer::traits::query::method_autoderef::MethodAutoderefBadTy; +use rustc_infer::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult}; +use rustc_infer::traits::query::CanonicalTyGoal; +use rustc_infer::traits::{self, ObligationCause}; use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; use std::cmp::max; use std::iter; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 789bac2705b..83f063aceda 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -6,8 +6,6 @@ use crate::middle::lang_items::FnOnceTraitLangItem; use crate::namespace::Namespace; use rustc::hir::map as hir_map; use rustc::hir::map::Map; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::traits::Obligation; use rustc::ty::print::with_crate_prefix; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_data_structures::fx::FxHashSet; @@ -17,6 +15,8 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::Obligation; use rustc_span::{source_map, FileName, Span}; use syntax::ast; use syntax::util::lev_distance; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a825856e38a..748a44a7297 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -92,17 +92,9 @@ use crate::middle::lang_items; use crate::namespace::Namespace; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; -use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; -use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc::infer::opaque_types::OpaqueTypeDecl; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; -use rustc::infer::{self, InferCtxt, InferOk, InferResult}; use rustc::middle::region; use rustc::mir::interpret::ConstValue; use rustc::session::parse::feature_err; -use rustc::traits::error_reporting::recursive_type_with_infinite_size_error; -use rustc::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -126,6 +118,14 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath}; use rustc_index::vec::Idx; +use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; +use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; +use rustc_infer::infer::opaque_types::OpaqueTypeDecl; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; +use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt}; +use rustc_infer::traits::error_reporting::recursive_type_with_infinite_size_error; +use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 0c1557a59c2..86b00c2f0d3 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -2,12 +2,12 @@ use super::method::MethodCallee; use super::{FnCtxt, Needs}; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint}; use rustc::ty::{self, Ty, TypeFoldable}; use rustc_errors::{self, struct_span_err, Applicability}; use rustc_hir as hir; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_span::Span; use syntax::ast::Ident; diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 72a2d56af15..2c7cbed6a2d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1,7 +1,4 @@ use crate::check::FnCtxt; -use rustc::infer; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::traits::Pattern; use rustc::ty::subst::GenericArg; use rustc::ty::{self, BindingMode, Ty, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; @@ -10,6 +7,9 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; +use rustc_infer::infer; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::traits::Pattern; use rustc_span::hygiene::DesugaringKind; use rustc_span::Span; use syntax::ast; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index af2ccb45176..c0e33637fd0 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -77,8 +77,6 @@ use crate::check::FnCtxt; use crate::mem_categorization as mc; use crate::middle::region; use rustc::hir::map::Map; -use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::{self, RegionObligation, SuppressRegionErrors}; use rustc::ty::adjustment; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::ty::{self, Ty}; @@ -86,6 +84,8 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors}; use rustc_span::Span; use std::mem; use std::ops::Deref; diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index e4502bf134d..f42611c6340 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -36,13 +36,13 @@ use crate::expr_use_visitor as euv; use crate::mem_categorization as mc; use crate::mem_categorization::PlaceBase; use rustc::hir::map::Map; -use rustc::infer::UpvarRegion; use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_infer::infer::UpvarRegion; use rustc_span::Span; use syntax::ast; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index fc194e3af97..ef5188c94ff 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -1,10 +1,8 @@ use crate::check::{FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; -use rustc::infer::opaque_types::may_define_opaque_type; use rustc::middle::lang_items; use rustc::session::parse::feature_err; -use rustc::traits::{self, ObligationCause, ObligationCauseCode}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, @@ -13,6 +11,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; +use rustc_infer::infer::opaque_types::may_define_opaque_type; +use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_span::symbol::sym; use rustc_span::Span; use syntax::ast; @@ -223,7 +223,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem _ => {} } if !trait_should_be_self.is_empty() { - if rustc::traits::object_safety_violations(tcx, trait_def_id).is_empty() { + if rustc_infer::traits::object_safety_violations(tcx, trait_def_id).is_empty() { return; } let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect(); diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 3a1622f1649..380e256c9fc 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -5,8 +5,6 @@ use crate::check::FnCtxt; use rustc::hir::map::Map; -use rustc::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc::infer::InferCtxt; use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; @@ -14,6 +12,8 @@ use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdSet, DefIndex}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; +use rustc_infer::infer::InferCtxt; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 1970b1e5c5d..aa39a191b3d 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -1,14 +1,8 @@ //! Check properties that are required by built-in traits and set //! up data structures required by type-checking/codegen. -use rustc::infer; -use rustc::infer::outlives::env::OutlivesEnvironment; -use rustc::infer::SuppressRegionErrors; use rustc::middle::lang_items::UnsizeTraitLangItem; use rustc::middle::region; -use rustc::traits::misc::{can_type_implement_copy, CopyImplementationError}; -use rustc::traits::predicate_for_trait_def; -use rustc::traits::{self, ObligationCause, TraitEngine}; use rustc::ty::adjustment::CoerceUnsizedInfo; use rustc::ty::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; @@ -16,6 +10,12 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; +use rustc_infer::infer; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError}; +use rustc_infer::traits::predicate_for_trait_def; +use rustc_infer::traits::{self, ObligationCause, TraitEngine}; pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { let lang_items = tcx.lang_items(); diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index ffea849c4f2..2a0d19b69fd 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -1,10 +1,10 @@ use crate::namespace::Namespace; -use rustc::traits::{self, SkipLeakCheck}; use rustc::ty::{AssocItem, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_infer::traits::{self, SkipLeakCheck}; pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) { assert_eq!(crate_num, LOCAL_CRATE); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 1526182576c..d24ee5f156b 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -5,11 +5,11 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. -use rustc::traits; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_infer::traits; use rustc_span::Span; mod builtin; diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 80521666476..6ce0da666a7 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -1,11 +1,12 @@ //! Orphan checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. -use rustc::traits; use rustc::ty::{self, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits; pub fn check(tcx: TyCtxt<'_>) { let mut orphan = OrphanChecker { tcx }; diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 8b6dba749a6..2ba97055a68 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -1,6 +1,5 @@ use rustc::hir::map::Map; use rustc::session::parse::feature_err; -use rustc::traits; use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc::ty::util::IntTypeExt; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; @@ -12,6 +11,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; +use rustc_infer::traits; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs index 1d3ace933cc..6666b169994 100644 --- a/src/librustc_typeck/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -7,12 +7,12 @@ pub use self::ConsumeMode::*; // Export these here so that Clippy can use them. pub use mc::{Place, PlaceBase, Projection}; -use rustc::infer::InferCtxt; use rustc::ty::{self, adjustment, TyCtxt}; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; use rustc_hir::PatKind; +use rustc_infer::infer::InferCtxt; use crate::mem_categorization as mc; use rustc_span::Span; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 067b33c1447..0a1c61b8aea 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -88,12 +88,10 @@ mod outlives; mod structured_errors; mod variance; -use rustc::infer::InferOk; use rustc::lint; use rustc::middle; use rustc::session; use rustc::session::config::EntryFnType; -use rustc::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; @@ -103,6 +101,8 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; +use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index d3d0aa2e580..a4569a14756 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -48,15 +48,16 @@ //! result of `*x'`, effectively, where `x'` is a `Categorization::Upvar` reference //! tied to `x`. The type of `x'` will be a borrowed pointer. -use rustc::infer::InferCtxt; use rustc::ty::adjustment; use rustc::ty::fold::TypeFoldable; use rustc::ty::{self, Ty, TyCtxt}; + use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::PatKind; +use rustc_infer::infer::InferCtxt; use rustc_span::Span; #[derive(Clone, Debug)] From 67068f35dd41409c8e79710f1335cc9dc64f1860 Mon Sep 17 00:00:00 2001 From: Hiroki Noda Date: Sun, 2 Feb 2020 21:25:38 +0900 Subject: [PATCH 0250/1250] macOS: avoid calling pthread_self() twice --- src/libstd/sys/unix/thread.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 3ca778354e4..674d4c71138 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -255,8 +255,9 @@ pub mod guard { #[cfg(target_os = "macos")] unsafe fn get_stack_start() -> Option<*mut libc::c_void> { - let stackaddr = libc::pthread_get_stackaddr_np(libc::pthread_self()) as usize - - libc::pthread_get_stacksize_np(libc::pthread_self()); + let th = libc::pthread_self(); + let stackaddr = + libc::pthread_get_stackaddr_np(th) as usize - libc::pthread_get_stacksize_np(th); Some(stackaddr as *mut libc::c_void) } From 1637aab15e175b5e0dc14947ffa946804420d414 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 23:21:41 +0100 Subject: [PATCH 0251/1250] Make librustc_mir compile. --- .../borrow_check/constraint_generation.rs | 2 +- .../diagnostics/conflict_errors.rs | 2 +- .../diagnostics/explain_borrow.rs | 2 +- .../borrow_check/diagnostics/region_errors.rs | 6 +++--- .../borrow_check/member_constraints.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/nll.rs | 2 +- .../borrow_check/region_infer/dump_mir.rs | 2 +- .../borrow_check/region_infer/mod.rs | 6 +++--- .../borrow_check/region_infer/opaque_types.rs | 2 +- src/librustc_mir/borrow_check/renumber.rs | 2 +- .../type_check/constraint_conversion.rs | 12 +++++------ .../type_check/free_region_relations.rs | 10 +++++----- .../borrow_check/type_check/input_output.rs | 2 +- .../borrow_check/type_check/liveness/trace.rs | 8 ++++---- .../borrow_check/type_check/mod.rs | 20 ++++++++++--------- .../borrow_check/type_check/relate_tys.rs | 8 ++++---- .../borrow_check/universal_regions.rs | 2 +- .../transform/check_consts/validation.rs | 3 ++- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir_build/build/mod.rs | 1 + src/librustc_mir_build/hair/cx/mod.rs | 2 +- .../hair/pattern/const_to_pat.rs | 6 +++--- 23 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/librustc_mir/borrow_check/constraint_generation.rs b/src/librustc_mir/borrow_check/constraint_generation.rs index 19b7e0cf59b..46cfe0897a9 100644 --- a/src/librustc_mir/borrow_check/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/constraint_generation.rs @@ -1,4 +1,3 @@ -use rustc::infer::InferCtxt; use rustc::mir::visit::TyContext; use rustc::mir::visit::Visitor; use rustc::mir::{ @@ -8,6 +7,7 @@ use rustc::mir::{ use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, RegionVid, Ty}; +use rustc_infer::infer::InferCtxt; use crate::borrow_check::{ borrow_set::BorrowSet, facts::AllFacts, location::LocationTable, nll::ToRegionVid, diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index c7c7db9ad80..d1a03c41580 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -3,7 +3,6 @@ use rustc::mir::{ FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, TerminatorKind, VarBindingForm, }; -use rustc::traits::error_reporting::suggest_constraining_type_param; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -11,6 +10,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_index::vec::Idx; +use rustc_infer::traits::error_reporting::suggest_constraining_type_param; use rustc_span::source_map::DesugaringKind; use rustc_span::Span; diff --git a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs index 01b7c5645fe..6475677988f 100644 --- a/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs +++ b/src/librustc_mir/borrow_check/diagnostics/explain_borrow.rs @@ -2,7 +2,6 @@ use std::collections::VecDeque; -use rustc::infer::NLLRegionVariableOrigin; use rustc::mir::{ Body, CastKind, ConstraintCategory, FakeReadCause, Local, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, @@ -12,6 +11,7 @@ use rustc::ty::{self, RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_index::vec::IndexVec; +use rustc_infer::infer::NLLRegionVariableOrigin; use rustc_span::symbol::Symbol; use rustc_span::Span; diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index b393d4bc2a5..a3e0e51c5b6 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -1,11 +1,11 @@ //! Error reporting machinery for lifetime errors. -use rustc::infer::{ - error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin, -}; use rustc::mir::ConstraintCategory; use rustc::ty::{self, RegionVid, Ty}; use rustc_errors::{Applicability, DiagnosticBuilder}; +use rustc_infer::infer::{ + error_reporting::nice_region_error::NiceRegionError, opaque_types, NLLRegionVariableOrigin, +}; use rustc_span::symbol::kw; use rustc_span::Span; diff --git a/src/librustc_mir/borrow_check/member_constraints.rs b/src/librustc_mir/borrow_check/member_constraints.rs index c95919685bb..aeb29d2e11e 100644 --- a/src/librustc_mir/borrow_check/member_constraints.rs +++ b/src/librustc_mir/borrow_check/member_constraints.rs @@ -1,5 +1,5 @@ use crate::rustc::ty::{self, Ty}; -use rustc::infer::region_constraints::MemberConstraint; +use rustc::infer::MemberConstraint; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index f9db62e0a3a..a3edfb662c5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1,6 +1,5 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. -use rustc::infer::InferCtxt; use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT; use rustc::lint::builtin::UNUSED_MUT; use rustc::mir::{ @@ -20,6 +19,7 @@ use rustc_hir as hir; use rustc_hir::{def_id::DefId, HirId, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use either::Either; use smallvec::SmallVec; diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 101d1856c38..ba0f2e8a7ad 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -1,6 +1,5 @@ //! The entry point of the NLL borrow checker. -use rustc::infer::InferCtxt; use rustc::mir::{ BasicBlock, Body, BodyAndCache, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, ReadOnlyBodyAndCache, @@ -10,6 +9,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir::def_id::DefId; use rustc_index::vec::IndexVec; +use rustc_infer::infer::InferCtxt; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; diff --git a/src/librustc_mir/borrow_check/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/region_infer/dump_mir.rs index b236ffe8074..369e5402311 100644 --- a/src/librustc_mir/borrow_check/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/region_infer/dump_mir.rs @@ -4,7 +4,7 @@ //! context internal state. use super::{OutlivesConstraint, RegionInferenceContext}; -use rustc::infer::NLLRegionVariableOrigin; +use rustc_infer::infer::NLLRegionVariableOrigin; use std::io::{self, Write}; // Room for "'_#NNNNr" before things get misaligned. diff --git a/src/librustc_mir/borrow_check/region_infer/mod.rs b/src/librustc_mir/borrow_check/region_infer/mod.rs index 192e4700b91..144f655420b 100644 --- a/src/librustc_mir/borrow_check/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/region_infer/mod.rs @@ -1,9 +1,6 @@ use std::collections::VecDeque; use std::rc::Rc; -use rustc::infer::canonical::QueryOutlivesConstraint; -use rustc::infer::region_constraints::{GenericKind, VarInfos, VerifyBound}; -use rustc::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin}; use rustc::mir::{ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory, Local, Location, @@ -15,6 +12,9 @@ use rustc_data_structures::graph::scc::Sccs; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; +use rustc_infer::infer::canonical::QueryOutlivesConstraint; +use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound}; +use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin, RegionVariableOrigin}; use rustc_span::Span; use crate::borrow_check::{ diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index 52d54f7b53c..15bbc5677da 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -1,7 +1,7 @@ -use rustc::infer::InferCtxt; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; +use rustc_infer::infer::InferCtxt; use rustc_span::Span; use super::RegionInferenceContext; diff --git a/src/librustc_mir/borrow_check/renumber.rs b/src/librustc_mir/borrow_check/renumber.rs index ab08cb0a319..a63d18c27f1 100644 --- a/src/librustc_mir/borrow_check/renumber.rs +++ b/src/librustc_mir/borrow_check/renumber.rs @@ -1,9 +1,9 @@ -use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::mir::{BodyAndCache, Location, PlaceElem, Promoted}; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_index::vec::IndexVec; +use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. diff --git a/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs b/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs index a3e38cd7a5f..576759c2a35 100644 --- a/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs +++ b/src/librustc_mir/borrow_check/type_check/constraint_conversion.rs @@ -1,12 +1,12 @@ -use rustc::infer::canonical::QueryOutlivesConstraint; -use rustc::infer::canonical::QueryRegionConstraints; -use rustc::infer::outlives::env::RegionBoundPairs; -use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; -use rustc::infer::region_constraints::{GenericKind, VerifyBound}; -use rustc::infer::{self, InferCtxt, SubregionOrigin}; use rustc::mir::ConstraintCategory; use rustc::ty::subst::GenericArgKind; use rustc::ty::{self, TyCtxt}; +use rustc_infer::infer::canonical::QueryOutlivesConstraint; +use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::infer::outlives::env::RegionBoundPairs; +use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate}; +use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; +use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_span::DUMMY_SP; use crate::borrow_check::{ diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs index cf8c3449d66..137216531a3 100644 --- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs @@ -1,12 +1,12 @@ -use rustc::infer::canonical::QueryRegionConstraints; -use rustc::infer::region_constraints::GenericKind; -use rustc::infer::InferCtxt; use rustc::mir::ConstraintCategory; -use rustc::traits::query::outlives_bounds::{self, OutlivesBound}; -use rustc::traits::query::type_op::{self, TypeOp}; use rustc::ty::free_region_map::FreeRegionRelations; use rustc::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_data_structures::transitive_relation::TransitiveRelation; +use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::infer::region_constraints::GenericKind; +use rustc_infer::infer::InferCtxt; +use rustc_infer::traits::query::outlives_bounds::{self, OutlivesBound}; +use rustc_infer::traits::query::type_op::{self, TypeOp}; use rustc_span::DUMMY_SP; use std::rc::Rc; diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index 3d3b1e5cbf6..37cf77b7095 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -7,9 +7,9 @@ //! `RETURN_PLACE` the MIR arguments) are always fully normalized (and //! contain revealed `impl Trait` values). -use rustc::infer::LateBoundRegionConversionTime; use rustc::mir::*; use rustc::ty::Ty; +use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_index::vec::Idx; use rustc_span::Span; diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index 198f4b4b42e..4c8deb0ecf8 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -1,11 +1,11 @@ -use rustc::infer::canonical::QueryRegionConstraints; use rustc::mir::{BasicBlock, ConstraintCategory, Local, Location, ReadOnlyBodyAndCache}; -use rustc::traits::query::dropck_outlives::DropckOutlivesResult; -use rustc::traits::query::type_op::outlives::DropckOutlives; -use rustc::traits::query::type_op::TypeOp; use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::HybridBitSet; +use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::traits::query::dropck_outlives::DropckOutlivesResult; +use rustc_infer::traits::query::type_op::outlives::DropckOutlives; +use rustc_infer::traits::query::type_op::TypeOp; use std::rc::Rc; use crate::dataflow::generic::ResultsCursor; diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 88fe6d1a3a4..c92486213fd 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -5,19 +5,10 @@ use std::{fmt, iter, mem}; use either::Either; -use rustc::infer::canonical::QueryRegionConstraints; -use rustc::infer::opaque_types::GenerateMemberConstraints; -use rustc::infer::outlives::env::RegionBoundPairs; -use rustc::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin}; use rustc::mir::tcx::PlaceTy; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc::mir::AssertKind; use rustc::mir::*; -use rustc::traits::query::type_op; -use rustc::traits::query::type_op::custom::CustomTypeOp; -use rustc::traits::query::{Fallible, NoSolution}; -use rustc::traits::{self, ObligationCause, PredicateObligations}; use rustc::ty::adjustment::PointerCast; use rustc::ty::cast::CastTy; use rustc::ty::fold::TypeFoldable; @@ -32,6 +23,17 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; +use rustc_infer::infer::canonical::QueryRegionConstraints; +use rustc_infer::infer::opaque_types::GenerateMemberConstraints; +use rustc_infer::infer::outlives::env::RegionBoundPairs; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{ + InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin, +}; +use rustc_infer::traits::query::type_op; +use rustc_infer::traits::query::type_op::custom::CustomTypeOp; +use rustc_infer::traits::query::{Fallible, NoSolution}; +use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; use rustc_span::{Span, DUMMY_SP}; use crate::dataflow::generic::ResultsCursor; diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index edbcd715159..31507a184d8 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -1,10 +1,10 @@ -use rustc::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::mir::ConstraintCategory; -use rustc::traits::query::Fallible; -use rustc::traits::DomainGoal; use rustc::ty::relate::TypeRelation; use rustc::ty::{self, Ty}; +use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; +use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc_infer::traits::query::Fallible; +use rustc_infer::traits::DomainGoal; use crate::borrow_check::constraints::OutlivesConstraint; use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index f6e3ca2f809..0913de63e8e 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -13,7 +13,6 @@ //! just returns them for other code to use. use either::Either; -use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::middle::lang_items; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; @@ -24,6 +23,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{BodyOwnerKind, HirId}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; use std::iter; use crate::borrow_check::nll::ToRegionVid; diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index e9715f682b0..167d8145c03 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -3,12 +3,13 @@ use rustc::middle::lang_items; use rustc::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; -use rustc::traits::{self, TraitEngine}; use rustc::ty::cast::CastTy; use rustc::ty::{self, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir::{def_id::DefId, HirId}; use rustc_index::bit_set::BitSet; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::{self, TraitEngine}; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 5729cda64f7..91d134fbb00 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -14,7 +14,6 @@ use rustc::mir::{ SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; -use rustc::traits; use rustc::ty::layout::{ HasDataLayout, HasTyCtxt, LayoutError, LayoutOf, Size, TargetDataLayout, TyLayout, }; @@ -25,6 +24,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::vec::IndexVec; +use rustc_infer::traits; use rustc_span::Span; use syntax::ast::Mutability; diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 5f8c0b027e9..8b7d0637c03 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -12,6 +12,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{GeneratorKind, HirIdMap, Node}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_infer::infer::TyCtxtInferExt; use rustc_span::symbol::kw; use rustc_span::Span; use rustc_target::spec::abi::Abi; diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs index 497c6610550..ee62af7f851 100644 --- a/src/librustc_mir_build/hair/cx/mod.rs +++ b/src/librustc_mir_build/hair/cx/mod.rs @@ -5,7 +5,6 @@ use crate::hair::util::UserAnnotatedTyHelpers; use crate::hair::*; -use rustc::infer::InferCtxt; use rustc::middle::region; use rustc::mir::interpret::{LitToConstError, LitToConstInput}; use rustc::ty::layout::VariantIdx; @@ -16,6 +15,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::Node; use rustc_index::vec::Idx; +use rustc_infer::infer::InferCtxt; use rustc_span::symbol::{sym, Symbol}; use syntax::ast; use syntax::attr; diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 5fbe764430c..27d1bce76ed 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -1,10 +1,10 @@ -use rustc::infer::InferCtxt; use rustc::lint; use rustc::mir::Field; -use rustc::traits::predicate_for_trait_def; -use rustc::traits::{self, ObligationCause, PredicateObligation}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::predicate_for_trait_def; +use rustc_infer::traits::{self, ObligationCause, PredicateObligation}; use rustc_index::vec::Idx; From 2519f4a0a336993fc2e494a194807c56060256b3 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 23:28:45 +0100 Subject: [PATCH 0252/1250] Make librustc_traits compile. --- src/librustc_traits/chalk_context/mod.rs | 14 ++++++------- .../chalk_context/resolvent_ops.rs | 10 +++++----- src/librustc_traits/chalk_context/unify.rs | 6 +++--- src/librustc_traits/dropck_outlives.rs | 11 +++++----- src/librustc_traits/evaluate_obligation.rs | 9 +++++---- .../implied_outlives_bounds.rs | 14 ++++++------- .../normalize_erasing_regions.rs | 3 ++- .../normalize_projection_ty.rs | 9 ++++++--- src/librustc_traits/type_op.rs | 20 +++++++++---------- 9 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs index 0b18352df33..240a93f0900 100644 --- a/src/librustc_traits/chalk_context/mod.rs +++ b/src/librustc_traits/chalk_context/mod.rs @@ -5,19 +5,19 @@ mod unify; use chalk_engine::fallible::Fallible; use chalk_engine::forest::Forest; use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause, Literal}; -use rustc::infer::canonical::{ +use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use rustc::ty::query::Providers; +use rustc::ty::subst::{GenericArg, GenericArgKind}; +use rustc::ty::{self, TyCtxt}; +use rustc_infer::infer::canonical::{ Canonical, CanonicalVarValues, Certainty, OriginalQueryValues, QueryRegionConstraints, QueryResponse, }; -use rustc::infer::{InferCtxt, LateBoundRegionConversionTime}; -use rustc::traits::{ +use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, TyCtxtInferExt}; +use rustc_infer::traits::{ self, ChalkCanonicalGoal, ChalkContextLift, Clause, DomainGoal, Environment, ExClauseFold, Goal, GoalKind, InEnvironment, QuantifierKind, }; -use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc::ty::query::Providers; -use rustc::ty::subst::{GenericArg, GenericArgKind}; -use rustc::ty::{self, TyCtxt}; use rustc_macros::{Lift, TypeFoldable}; use rustc_span::DUMMY_SP; diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs index dc6018e80ea..796ce6085fd 100644 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ b/src/librustc_traits/chalk_context/resolvent_ops.rs @@ -1,13 +1,13 @@ use chalk_engine::fallible::{Fallible, NoSolution}; use chalk_engine::{context, ExClause, Literal}; -use rustc::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc::infer::{InferCtxt, LateBoundRegionConversionTime}; -use rustc::traits::{ - Clause, DomainGoal, Environment, Goal, GoalKind, InEnvironment, ProgramClause, WhereClause, -}; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; use rustc::ty::subst::GenericArg; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; +use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; +use rustc_infer::traits::{ + Clause, DomainGoal, Environment, Goal, GoalKind, InEnvironment, ProgramClause, WhereClause, +}; use rustc_span::DUMMY_SP; use super::unify::*; diff --git a/src/librustc_traits/chalk_context/unify.rs b/src/librustc_traits/chalk_context/unify.rs index fcb3c3b1773..3274a301bb6 100644 --- a/src/librustc_traits/chalk_context/unify.rs +++ b/src/librustc_traits/chalk_context/unify.rs @@ -1,8 +1,8 @@ -use rustc::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc::infer::{InferCtxt, RegionVariableOrigin}; -use rustc::traits::{DomainGoal, Environment, Goal, InEnvironment}; use rustc::ty; use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; +use rustc_infer::infer::{InferCtxt, RegionVariableOrigin}; +use rustc_infer::traits::{DomainGoal, Environment, Goal, InEnvironment}; use rustc_span::DUMMY_SP; crate struct UnificationResult<'tcx> { diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 346d2a931d1..e14295de061 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -1,13 +1,14 @@ -use rustc::infer::canonical::{Canonical, QueryResponse}; -use rustc::traits::query::dropck_outlives::trivial_dropck_outlives; -use rustc::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint}; -use rustc::traits::query::{CanonicalTyGoal, NoSolution}; -use rustc::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; +use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::query::dropck_outlives::trivial_dropck_outlives; +use rustc_infer::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint}; +use rustc_infer::traits::query::{CanonicalTyGoal, NoSolution}; +use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; use rustc_span::source_map::{Span, DUMMY_SP}; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index 3ad1b223a84..4cf5b66b3cb 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -1,9 +1,10 @@ -use rustc::traits::query::CanonicalPredicateGoal; -use rustc::traits::{ - EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, -}; use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::query::CanonicalPredicateGoal; +use rustc_infer::traits::{ + EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, +}; use rustc_span::source_map::DUMMY_SP; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 40f821c29d3..69424e3fac7 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -1,17 +1,17 @@ //! Provider for the `implied_outlives_bounds` query. //! Do not call this query directory. See [`rustc::traits::query::implied_outlives_bounds`]. -use rustc::infer::canonical::{self, Canonical}; -use rustc::infer::InferCtxt; -use rustc::traits::query::outlives_bounds::OutlivesBound; -use rustc::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; -use rustc::traits::wf; -use rustc::traits::FulfillmentContext; -use rustc::traits::{TraitEngine, TraitEngineExt}; use rustc::ty::outlives::Component; use rustc::ty::query::Providers; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; +use rustc_infer::infer::canonical::{self, Canonical}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::query::outlives_bounds::OutlivesBound; +use rustc_infer::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; +use rustc_infer::traits::wf; +use rustc_infer::traits::FulfillmentContext; +use rustc_infer::traits::{TraitEngine, TraitEngineExt}; use rustc_span::source_map::DUMMY_SP; use smallvec::{smallvec, SmallVec}; diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index e81b0242d61..4e5f20d80b0 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -1,7 +1,8 @@ use rustc::traits::query::NoSolution; -use rustc::traits::{Normalized, ObligationCause}; use rustc::ty::query::Providers; use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index e50ca485e0a..b5678956347 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -1,9 +1,12 @@ -use rustc::infer::canonical::{Canonical, QueryResponse}; -use rustc::traits::query::{normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution}; -use rustc::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_hir as hir; +use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits::query::{ + normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution, +}; +use rustc_infer::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; use rustc_span::DUMMY_SP; use std::sync::atomic::Ordering; diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 149c42e9c5e..41181338061 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -1,13 +1,3 @@ -use rustc::infer::at::ToTrace; -use rustc::infer::canonical::{Canonical, QueryResponse}; -use rustc::infer::InferCtxt; -use rustc::traits::query::type_op::ascribe_user_type::AscribeUserType; -use rustc::traits::query::type_op::eq::Eq; -use rustc::traits::query::type_op::normalize::Normalize; -use rustc::traits::query::type_op::prove_predicate::ProvePredicate; -use rustc::traits::query::type_op::subtype::Subtype; -use rustc::traits::query::{Fallible, NoSolution}; -use rustc::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt}; use rustc::ty::query::Providers; use rustc::ty::subst::{GenericArg, Subst, UserSelfTy, UserSubsts}; use rustc::ty::{ @@ -15,6 +5,16 @@ use rustc::ty::{ }; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_infer::infer::at::ToTrace; +use rustc_infer::infer::canonical::{Canonical, QueryResponse}; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::traits::query::type_op::ascribe_user_type::AscribeUserType; +use rustc_infer::traits::query::type_op::eq::Eq; +use rustc_infer::traits::query::type_op::normalize::Normalize; +use rustc_infer::traits::query::type_op::prove_predicate::ProvePredicate; +use rustc_infer::traits::query::type_op::subtype::Subtype; +use rustc_infer::traits::query::{Fallible, NoSolution}; +use rustc_infer::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt}; use rustc_span::DUMMY_SP; use std::fmt; From bee6a5ac1274201e7da2081a5aff6b3b1f407185 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 6 Jan 2020 23:31:06 +0100 Subject: [PATCH 0253/1250] Other crates. --- Cargo.lock | 1 + src/librustc_interface/Cargo.toml | 1 + src/librustc_interface/passes.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_passes/stability.rs | 2 +- src/librustc_ty/common_traits.rs | 3 ++- src/librustc_ty/instance.rs | 2 +- src/librustc_ty/ty.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 4 ++-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/lib.rs | 1 + 12 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f8b4eca99ee..7ff9d419c5d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3818,6 +3818,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_incremental", + "rustc_infer", "rustc_lint", "rustc_metadata", "rustc_mir", diff --git a/src/librustc_interface/Cargo.toml b/src/librustc_interface/Cargo.toml index de7a9f4f5af..b3ac5b0fc54 100644 --- a/src/librustc_interface/Cargo.toml +++ b/src/librustc_interface/Cargo.toml @@ -31,6 +31,7 @@ rustc_codegen_ssa = { path = "../librustc_codegen_ssa" } rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_codegen_llvm = { path = "../librustc_codegen_llvm", optional = true } rustc_hir = { path = "../librustc_hir" } +rustc_infer = { path = "../librustc_infer" } rustc_metadata = { path = "../librustc_metadata" } rustc_mir = { path = "../librustc_mir" } rustc_mir_build = { path = "../librustc_mir_build" } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 6224c4654d6..0b4a337051f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -13,7 +13,6 @@ use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType use rustc::session::config::{PpMode, PpSourceMode}; use rustc::session::search_paths::PathKind; use rustc::session::Session; -use rustc::traits; use rustc::ty::steal::Steal; use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc::util::common::ErrorReported; @@ -26,6 +25,7 @@ use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::Crate; +use rustc_infer::traits; use rustc_lint::LintStore; use rustc_mir as mir; use rustc_mir_build as mir_build; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 93fca43d67c..6039fef33e6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -24,7 +24,6 @@ use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; use rustc::hir::map::Map; use rustc::lint::LintDiagnosticBuilder; -use rustc::traits::misc::can_type_implement_copy; use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::FxHashSet; @@ -36,6 +35,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{GenericParamKind, PatKind}; use rustc_hir::{HirIdSet, Node}; +use rustc_infer::traits::misc::can_type_implement_copy; use rustc_session::lint::FutureIncompatibleInfo; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 4e2085d07a3..99f005c29e8 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -7,7 +7,6 @@ use rustc::middle::privacy::AccessLevels; use rustc::middle::stability::{DeprecationEntry, Index}; use rustc::session::parse::feature_err; use rustc::session::Session; -use rustc::traits::misc::can_type_implement_copy; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_attr::{self as attr, Stability}; @@ -18,6 +17,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Generics, HirId, Item, StructField, Variant}; +use rustc_infer::traits::misc::can_type_implement_copy; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use syntax::ast::Attribute; diff --git a/src/librustc_ty/common_traits.rs b/src/librustc_ty/common_traits.rs index 9fe8a19311f..e0ce6ad23a6 100644 --- a/src/librustc_ty/common_traits.rs +++ b/src/librustc_ty/common_traits.rs @@ -1,8 +1,9 @@ //! Queries for checking whether a type implements one of a few common traits. use rustc::middle::lang_items; -use rustc::traits; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::traits; use rustc_span::DUMMY_SP; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 66f189a5d97..484b774add4 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -1,7 +1,7 @@ -use rustc::traits; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt, TypeFoldable}; use rustc_hir::def_id::DefId; +use rustc_infer::traits; use rustc_target::spec::abi::Abi; use log::debug; diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index ddb7c8bc791..f9b2ee3cb8e 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -1,11 +1,11 @@ use rustc::hir::map as hir_map; use rustc::session::CrateDisambiguator; -use rustc::traits::{self}; use rustc::ty::subst::Subst; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_infer::traits; use rustc_span::symbol::Symbol; use rustc_span::Span; diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 8edd0591c85..289923b45e6 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1,7 +1,7 @@ -use rustc::traits::auto_trait::{self, AutoTraitResult}; use rustc::ty::{self, Region, RegionVid, TypeFoldable}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_infer::traits::auto_trait::{self, AutoTraitResult}; use std::fmt::Debug; diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 288446b6219..f7968bf7722 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,9 +1,9 @@ -use rustc::infer::InferOk; -use rustc::traits; use rustc::ty::subst::Subst; use rustc::ty::{ToPredicate, WithConstness}; use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_infer::infer::{InferOk, TyCtxtInferExt}; +use rustc_infer::traits; use rustc_span::DUMMY_SP; use super::*; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 87edc88611f..ee432647084 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -9,7 +9,6 @@ mod simplify; pub mod types; pub mod utils; -use rustc::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc::middle::lang_items; use rustc::middle::resolve_lifetime as rl; use rustc::middle::stability; @@ -22,6 +21,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData}; use rustc_mir::const_eval::is_min_const_fn; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4e0a2d94274..eab88b7165d 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_expand; extern crate rustc_feature; extern crate rustc_hir; extern crate rustc_index; +extern crate rustc_infer; extern crate rustc_interface; extern crate rustc_lexer; extern crate rustc_lint; From 795673ae2060198cdb09c6ded8d303c244dac6fd Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 7 Jan 2020 22:07:22 +0100 Subject: [PATCH 0254/1250] Remove librustc_infer crate re-exports. --- src/librustc_infer/infer/at.rs | 4 ++-- src/librustc_infer/infer/canonical/canonicalizer.rs | 8 ++++---- src/librustc_infer/infer/canonical/query_response.rs | 2 +- src/librustc_infer/infer/canonical/substitute.rs | 6 +++--- src/librustc_infer/infer/combine.rs | 10 +++++----- src/librustc_infer/infer/equate.rs | 8 ++++---- .../infer/error_reporting/need_type_info.rs | 6 +++--- .../nice_region_error/different_lifetimes.rs | 2 +- .../nice_region_error/find_anon_type.rs | 6 +++--- .../infer/error_reporting/nice_region_error/mod.rs | 4 ++-- .../nice_region_error/named_anon_conflict.rs | 2 +- .../nice_region_error/outlives_closure.rs | 4 ++-- .../nice_region_error/placeholder_error.rs | 8 ++++---- .../nice_region_error/static_impl_trait.rs | 4 ++-- .../nice_region_error/trait_impl_difference.rs | 4 ++-- .../infer/error_reporting/nice_region_error/util.rs | 2 +- src/librustc_infer/infer/freshen.rs | 4 ++-- src/librustc_infer/infer/fudge.rs | 4 ++-- src/librustc_infer/infer/glb.rs | 4 ++-- src/librustc_infer/infer/higher_ranked/mod.rs | 4 ++-- src/librustc_infer/infer/lattice.rs | 6 +++--- .../infer/lexical_region_resolve/graphviz.rs | 6 +++--- .../infer/lexical_region_resolve/mod.rs | 12 ++++++------ src/librustc_infer/infer/lub.rs | 4 ++-- src/librustc_infer/infer/mod.rs | 6 +++--- src/librustc_infer/infer/nll_relate/mod.rs | 10 +++++----- src/librustc_infer/infer/opaque_types/mod.rs | 10 +++++----- src/librustc_infer/infer/outlives/env.rs | 4 ++-- src/librustc_infer/infer/outlives/obligations.rs | 6 +++--- src/librustc_infer/infer/outlives/verify.rs | 4 ++-- .../infer/region_constraints/leak_check.rs | 4 ++-- src/librustc_infer/infer/resolve.rs | 4 ++-- src/librustc_infer/infer/sub.rs | 8 ++++---- src/librustc_infer/infer/type_variable.rs | 2 +- src/librustc_infer/lib.rs | 7 ------- src/librustc_infer/traits/auto_trait.rs | 4 ++-- src/librustc_infer/traits/chalk_fulfill.rs | 2 +- src/librustc_infer/traits/codegen/mod.rs | 4 ++-- src/librustc_infer/traits/coherence.rs | 6 +++--- src/librustc_infer/traits/engine.rs | 2 +- .../traits/error_reporting/on_unimplemented.rs | 4 ++-- .../traits/error_reporting/suggestions.rs | 5 +++-- src/librustc_infer/traits/fulfill.rs | 4 ++-- src/librustc_infer/traits/mod.rs | 12 ++++++------ src/librustc_infer/traits/object_safety.rs | 6 +++--- src/librustc_infer/traits/on_unimplemented.rs | 4 ++-- src/librustc_infer/traits/project.rs | 6 +++--- src/librustc_infer/traits/query/normalize.rs | 6 +++--- src/librustc_infer/traits/query/outlives_bounds.rs | 2 +- src/librustc_infer/traits/query/type_op/eq.rs | 2 +- .../traits/query/type_op/implied_outlives_bounds.rs | 2 +- src/librustc_infer/traits/query/type_op/mod.rs | 4 ++-- src/librustc_infer/traits/query/type_op/normalize.rs | 4 ++-- src/librustc_infer/traits/query/type_op/outlives.rs | 2 +- .../traits/query/type_op/prove_predicate.rs | 2 +- src/librustc_infer/traits/query/type_op/subtype.rs | 2 +- src/librustc_infer/traits/select.rs | 12 ++++++------ src/librustc_infer/traits/specialize/mod.rs | 4 ++-- src/librustc_infer/traits/structural_impls.rs | 4 ++-- src/librustc_infer/traits/util.rs | 6 +++--- src/librustc_infer/traits/wf.rs | 6 +++--- 61 files changed, 150 insertions(+), 156 deletions(-) diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs index c58f1bd87bd..156b5a8b0b5 100644 --- a/src/librustc_infer/infer/at.rs +++ b/src/librustc_infer/infer/at.rs @@ -27,8 +27,8 @@ use super::*; -use crate::ty::relate::{Relate, TypeRelation}; -use crate::ty::Const; +use rustc::ty::relate::{Relate, TypeRelation}; +use rustc::ty::Const; pub struct At<'a, 'tcx> { pub infcx: &'a InferCtxt<'a, 'tcx>, diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 85fafa34915..ecd7281351d 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -10,10 +10,10 @@ use crate::infer::canonical::{ OriginalQueryValues, }; use crate::infer::InferCtxt; -use crate::ty::flags::FlagComputation; -use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::subst::GenericArg; -use crate::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags}; +use rustc::ty::flags::FlagComputation; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::subst::GenericArg; +use rustc::ty::{self, BoundVar, InferConst, List, Ty, TyCtxt, TypeFlags}; use std::sync::atomic::Ordering; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index 5dc98cb6feb..f4196e57605 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -7,7 +7,6 @@ //! //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html -use crate::arena::ArenaAllocatable; use crate::infer::canonical::substitute::{substitute_value, CanonicalExt}; use crate::infer::canonical::{ Canonical, CanonicalVarValues, CanonicalizedQueryResponse, Certainty, OriginalQueryValues, @@ -19,6 +18,7 @@ use crate::infer::{InferCtxt, InferOk, InferResult}; use crate::traits::query::{Fallible, NoSolution}; use crate::traits::TraitEngine; use crate::traits::{Obligation, ObligationCause, PredicateObligation}; +use rustc::arena::ArenaAllocatable; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{GenericArg, GenericArgKind}; use rustc::ty::{self, BoundVar, Ty, TyCtxt}; diff --git a/src/librustc_infer/infer/canonical/substitute.rs b/src/librustc_infer/infer/canonical/substitute.rs index 92066048261..99ddedfe881 100644 --- a/src/librustc_infer/infer/canonical/substitute.rs +++ b/src/librustc_infer/infer/canonical/substitute.rs @@ -7,9 +7,9 @@ //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html use crate::infer::canonical::{Canonical, CanonicalVarValues}; -use crate::ty::fold::TypeFoldable; -use crate::ty::subst::GenericArgKind; -use crate::ty::{self, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::GenericArgKind; +use rustc::ty::{self, TyCtxt}; pub(super) trait CanonicalExt<'tcx, V> { /// Instantiate the wrapped value, replacing each canonical value diff --git a/src/librustc_infer/infer/combine.rs b/src/librustc_infer/infer/combine.rs index 9eb961255c2..a10af56a0f0 100644 --- a/src/librustc_infer/infer/combine.rs +++ b/src/librustc_infer/infer/combine.rs @@ -33,12 +33,12 @@ use super::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use super::{InferCtxt, MiscVariable, TypeTrace}; use crate::traits::{Obligation, PredicateObligations}; -use crate::ty::error::TypeError; -use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use crate::ty::subst::SubstsRef; -use crate::ty::{self, InferConst, Ty, TyCtxt}; -use crate::ty::{IntType, UintType}; +use rustc::ty::error::TypeError; +use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc::ty::subst::SubstsRef; +use rustc::ty::{self, InferConst, Ty, TyCtxt}; +use rustc::ty::{IntType, UintType}; use rustc_hir::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; use syntax::ast; diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index 018bbe03543..c1eec6832b8 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -1,10 +1,10 @@ use super::combine::{CombineFields, RelationDir}; use super::Subtype; -use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use crate::ty::subst::SubstsRef; -use crate::ty::TyVar; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc::ty::subst::SubstsRef; +use rustc::ty::TyVar; +use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index 0d7fce7eac6..c8a465654b6 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -1,8 +1,8 @@ -use crate::hir::map::Map; use crate::infer::type_variable::TypeVariableOriginKind; use crate::infer::InferCtxt; -use crate::ty::print::Print; -use crate::ty::{self, DefIdTree, Infer, Ty, TyVar}; +use rustc::hir::map::Map; +use rustc::ty::print::Print; +use rustc::ty::{self, DefIdTree, Infer, Ty, TyVar}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index 6a9fe19e1ac..1a09729ef64 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -3,7 +3,7 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::util::common::ErrorReported; +use rustc::util::common::ErrorReported; use rustc_errors::struct_span_err; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index 8e2592b5318..2ae7f4cc04f 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -1,7 +1,7 @@ -use crate::hir::map::Map; use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::middle::resolve_lifetime as rl; -use crate::ty::{self, Region, TyCtxt}; +use rustc::hir::map::Map; +use rustc::middle::resolve_lifetime as rl; +use rustc::ty::{self, Region, TyCtxt}; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::Node; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index b10a60ef6f1..d8c314a0d2f 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -1,8 +1,8 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::lexical_region_resolve::RegionResolutionError::*; use crate::infer::InferCtxt; -use crate::ty::{self, TyCtxt}; -use crate::util::common::ErrorReported; +use rustc::ty::{self, TyCtxt}; +use rustc::util::common::ErrorReported; use rustc_errors::DiagnosticBuilder; use rustc_span::source_map::Span; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index 250dcff372c..b3197556053 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -1,7 +1,7 @@ //! Error Reporting for Anonymous Region Lifetime Errors //! where one region is named and the other is anonymous. use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::ty; +use rustc::ty; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir::{FunctionRetTy, TyKind}; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs index af0e5ef8005..d88e6555af9 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/outlives_closure.rs @@ -4,8 +4,8 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError::SubSupConflict; use crate::infer::SubregionOrigin; -use crate::ty::RegionKind; -use crate::util::common::ErrorReported; +use rustc::ty::RegionKind; +use rustc::util::common::ErrorReported; use rustc_hir::{Expr, ExprKind::Closure, Node}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs index 0b0bd61ce77..57313dbab42 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/placeholder_error.rs @@ -3,10 +3,10 @@ use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::ValuePairs; use crate::infer::{SubregionOrigin, TypeTrace}; use crate::traits::{ObligationCause, ObligationCauseCode}; -use crate::ty::error::ExpectedFound; -use crate::ty::print::{FmtPrinter, Print, RegionHighlightMode}; -use crate::ty::subst::SubstsRef; -use crate::ty::{self, TyCtxt}; +use rustc::ty::error::ExpectedFound; +use rustc::ty::print::{FmtPrinter, Print, RegionHighlightMode}; +use rustc::ty::subst::SubstsRef; +use rustc::ty::{self, TyCtxt}; use rustc_errors::DiagnosticBuilder; use rustc_hir::def::Namespace; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs index c6fc4cd3c15..655e28bbd3d 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs @@ -3,8 +3,8 @@ use crate::infer::error_reporting::msg_span_from_free_region; use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; -use crate::ty::{BoundRegion, FreeRegion, RegionKind}; -use crate::util::common::ErrorReported; +use rustc::ty::{BoundRegion, FreeRegion, RegionKind}; +use rustc::util::common::ErrorReported; use rustc_errors::Applicability; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs index a33cb511133..f8cab9f84c8 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs @@ -4,8 +4,8 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use crate::infer::lexical_region_resolve::RegionResolutionError; use crate::infer::{Subtype, ValuePairs}; use crate::traits::ObligationCauseCode::CompareImplMethodObligation; -use crate::ty::Ty; -use crate::util::common::ErrorReported; +use rustc::ty::Ty; +use rustc::util::common::ErrorReported; use rustc_span::Span; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index 52ccb1454ee..4dc9096533b 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -2,7 +2,7 @@ //! anonymous regions. use crate::infer::error_reporting::nice_region_error::NiceRegionError; -use crate::ty::{self, DefIdTree, Region, Ty}; +use rustc::ty::{self, DefIdTree, Region, Ty}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::Span; diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index 0190989267b..63dded3b43d 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -31,8 +31,8 @@ //! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type //! inferencer knows "so far". -use crate::ty::fold::TypeFolder; -use crate::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::fold::TypeFolder; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_infer/infer/fudge.rs b/src/librustc_infer/infer/fudge.rs index d0b7bb32b98..16bf0f3d1c6 100644 --- a/src/librustc_infer/infer/fudge.rs +++ b/src/librustc_infer/infer/fudge.rs @@ -1,5 +1,5 @@ -use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::{self, ConstVid, FloatVid, IntVid, RegionVid, Ty, TyCtxt, TyVid}; use super::type_variable::TypeVariableOrigin; use super::InferCtxt; diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index 6ef92132bc7..2634d9cac3e 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -4,8 +4,8 @@ use super::InferCtxt; use super::Subtype; use crate::traits::ObligationCause; -use crate::ty::relate::{Relate, RelateResult, TypeRelation}; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::{self, Ty, TyCtxt}; /// "Greatest lower bound" (common subtype) pub struct Glb<'combine, 'infcx, 'tcx> { diff --git a/src/librustc_infer/infer/higher_ranked/mod.rs b/src/librustc_infer/infer/higher_ranked/mod.rs index 1b0f399ca33..33781188a95 100644 --- a/src/librustc_infer/infer/higher_ranked/mod.rs +++ b/src/librustc_infer/infer/higher_ranked/mod.rs @@ -5,8 +5,8 @@ use super::combine::CombineFields; use super::{HigherRankedType, InferCtxt, PlaceholderMap}; use crate::infer::CombinedSnapshot; -use crate::ty::relate::{Relate, RelateResult, TypeRelation}; -use crate::ty::{self, Binder, TypeFoldable}; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::{self, Binder, TypeFoldable}; impl<'a, 'tcx> CombineFields<'a, 'tcx> { pub fn higher_ranked_sub( diff --git a/src/librustc_infer/infer/lattice.rs b/src/librustc_infer/infer/lattice.rs index df475af1151..42f9b3ab770 100644 --- a/src/librustc_infer/infer/lattice.rs +++ b/src/librustc_infer/infer/lattice.rs @@ -23,9 +23,9 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::InferCtxt; use crate::traits::ObligationCause; -use crate::ty::relate::{RelateResult, TypeRelation}; -use crate::ty::TyVar; -use crate::ty::{self, Ty}; +use rustc::ty::relate::{RelateResult, TypeRelation}; +use rustc::ty::TyVar; +use rustc::ty::{self, Ty}; pub trait LatticeDir<'f, 'tcx>: TypeRelation<'tcx> { fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>; diff --git a/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs b/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs index a930e707c5c..eb52f10e408 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/graphviz.rs @@ -11,9 +11,9 @@ use graphviz as dot; use super::Constraint; use crate::infer::region_constraints::RegionConstraintData; use crate::infer::SubregionOrigin; -use crate::middle::free_region::RegionRelations; -use crate::middle::region; -use crate::ty; +use rustc::middle::free_region::RegionRelations; +use rustc::middle::region; +use rustc::ty; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::DefIndex; diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index 1b204e5ba6c..0b5536219e5 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -8,12 +8,12 @@ use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VerifyBound; use crate::infer::RegionVariableOrigin; use crate::infer::SubregionOrigin; -use crate::middle::free_region::RegionRelations; -use crate::ty::fold::TypeFoldable; -use crate::ty::{self, Ty, TyCtxt}; -use crate::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; -use crate::ty::{ReLateBound, RePlaceholder, ReScope, ReVar}; -use crate::ty::{Region, RegionVid}; +use rustc::middle::free_region::RegionRelations; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic}; +use rustc::ty::{ReLateBound, RePlaceholder, ReScope, ReVar}; +use rustc::ty::{Region, RegionVid}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::graph::implementation::{ Direction, Graph, NodeIndex, INCOMING, OUTGOING, diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index 6a699f803c7..b6d20ba1f3f 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -4,8 +4,8 @@ use super::InferCtxt; use super::Subtype; use crate::traits::ObligationCause; -use crate::ty::relate::{Relate, RelateResult, TypeRelation}; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; +use rustc::ty::{self, Ty, TyCtxt}; /// "Least upper bound" (common supertype) pub struct Lub<'combine, 'infcx, 'tcx> { diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index b7f83625757..c9e58c2aa73 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -5,7 +5,7 @@ pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; -pub use crate::ty::IntVarValue; +pub use rustc::ty::IntVarValue; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; @@ -650,8 +650,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn type_is_unconstrained_numeric(&'a self, ty: Ty<'_>) -> UnconstrainedNumeric { - use crate::ty::error::UnconstrainedNumeric::Neither; - use crate::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt}; + use rustc::ty::error::UnconstrainedNumeric::Neither; + use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedFloat, UnconstrainedInt}; match ty.kind { ty::Infer(ty::IntVar(vid)) => { if self.inner.borrow_mut().int_unification_table.probe_value(vid).is_some() { diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index 77e20e6ad8f..e35b8f9c8ec 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -24,11 +24,11 @@ use crate::infer::InferCtxt; use crate::infer::{ConstVarValue, ConstVariableValue}; use crate::traits::DomainGoal; -use crate::ty::error::TypeError; -use crate::ty::fold::{TypeFoldable, TypeVisitor}; -use crate::ty::relate::{self, Relate, RelateResult, TypeRelation}; -use crate::ty::subst::GenericArg; -use crate::ty::{self, InferConst, Ty, TyCtxt}; +use rustc::ty::error::TypeError; +use rustc::ty::fold::{TypeFoldable, TypeVisitor}; +use rustc::ty::relate::{self, Relate, RelateResult, TypeRelation}; +use rustc::ty::subst::GenericArg; +use rustc::ty::{self, InferConst, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use std::fmt::Debug; diff --git a/src/librustc_infer/infer/opaque_types/mod.rs b/src/librustc_infer/infer/opaque_types/mod.rs index 5ecd03e4123..06d45690e41 100644 --- a/src/librustc_infer/infer/opaque_types/mod.rs +++ b/src/librustc_infer/infer/opaque_types/mod.rs @@ -1,12 +1,12 @@ use crate::infer::error_reporting::{note_and_explain_free_region, note_and_explain_region}; use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; -use crate::middle::region; use crate::traits::{self, PredicateObligation}; -use crate::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; -use crate::ty::free_region_map::FreeRegionRelations; -use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; -use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt}; +use rustc::middle::region; use rustc::session::config::nightly_options; +use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; +use rustc::ty::free_region_map::FreeRegionRelations; +use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; +use rustc::ty::{self, GenericParamDefKind, Ty, TyCtxt}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::{struct_span_err, DiagnosticBuilder}; diff --git a/src/librustc_infer/infer/outlives/env.rs b/src/librustc_infer/infer/outlives/env.rs index ee2e629c2fc..aac6c7640ca 100644 --- a/src/librustc_infer/infer/outlives/env.rs +++ b/src/librustc_infer/infer/outlives/env.rs @@ -1,7 +1,7 @@ use crate::infer::{GenericKind, InferCtxt}; use crate::traits::query::outlives_bounds::{self, OutlivesBound}; -use crate::ty::free_region_map::FreeRegionMap; -use crate::ty::{self, Ty}; +use rustc::ty::free_region_map::FreeRegionMap; +use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_span::Span; diff --git a/src/librustc_infer/infer/outlives/obligations.rs b/src/librustc_infer/infer/outlives/obligations.rs index 88733f1901a..e3790b02734 100644 --- a/src/librustc_infer/infer/outlives/obligations.rs +++ b/src/librustc_infer/infer/outlives/obligations.rs @@ -63,9 +63,9 @@ use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::outlives::verify::VerifyBoundCx; use crate::infer::{self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, VerifyBound}; use crate::traits::ObligationCause; -use crate::ty::outlives::Component; -use crate::ty::subst::GenericArgKind; -use crate::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::outlives::Component; +use rustc::ty::subst::GenericArgKind; +use rustc::ty::{self, Region, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index 4a05bfc64b1..be6f868430d 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -1,8 +1,8 @@ use crate::infer::outlives::env::RegionBoundPairs; use crate::infer::{GenericKind, VerifyBound}; use crate::traits; -use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::{self, Ty, TyCtxt}; use rustc_data_structures::captures::Captures; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 29290cef2d2..74ffdc7a4f0 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -1,7 +1,7 @@ use super::*; use crate::infer::{CombinedSnapshot, PlaceholderMap}; -use crate::ty::error::TypeError; -use crate::ty::relate::RelateResult; +use rustc::ty::error::TypeError; +use rustc::ty::relate::RelateResult; impl<'tcx> RegionConstraintCollector<'tcx> { /// Searches region constraints created since `snapshot` that diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index c9acd1cf4a1..3510b927d96 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -1,7 +1,7 @@ use super::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use super::{FixupError, FixupResult, InferCtxt, Span}; -use crate::ty::fold::{TypeFolder, TypeVisitor}; -use crate::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; +use rustc::ty::fold::{TypeFolder, TypeVisitor}; +use rustc::ty::{self, Const, InferConst, Ty, TyCtxt, TypeFoldable}; /////////////////////////////////////////////////////////////////////////// // OPPORTUNISTIC VAR RESOLVER diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index ef4903358d5..2b770ced42a 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -2,10 +2,10 @@ use super::combine::{CombineFields, RelationDir}; use super::SubregionOrigin; use crate::traits::Obligation; -use crate::ty::fold::TypeFoldable; -use crate::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; -use crate::ty::TyVar; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::relate::{Cause, Relate, RelateResult, TypeRelation}; +use rustc::ty::TyVar; +use rustc::ty::{self, Ty, TyCtxt}; use std::mem; /// Ensures `a` is made a subtype of `b`. Returns `a` on success. diff --git a/src/librustc_infer/infer/type_variable.rs b/src/librustc_infer/infer/type_variable.rs index f391a054a2a..b59c5606691 100644 --- a/src/librustc_infer/infer/type_variable.rs +++ b/src/librustc_infer/infer/type_variable.rs @@ -1,4 +1,4 @@ -use crate::ty::{self, Ty, TyVid}; +use rustc::ty::{self, Ty, TyVid}; use rustc_hir::def_id::DefId; use rustc_span::symbol::Symbol; use rustc_span::Span; diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index d64c9e2f90b..d6619e5f7f8 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -56,12 +56,5 @@ extern crate log; #[macro_use] extern crate rustc; -use rustc::arena; -use rustc::dep_graph; -use rustc::hir; pub mod infer; -use rustc::middle; -pub use rustc_session as session; pub mod traits; -use rustc::ty; -use rustc::util; diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs index 3ab87ce8eb4..1a4f899ac85 100644 --- a/src/librustc_infer/traits/auto_trait.rs +++ b/src/librustc_infer/traits/auto_trait.rs @@ -5,8 +5,8 @@ use super::*; use crate::infer::region_constraints::{Constraint, RegionConstraintData}; use crate::infer::InferCtxt; -use crate::ty::fold::TypeFolder; -use crate::ty::{Region, RegionVid}; +use rustc::ty::fold::TypeFolder; +use rustc::ty::{Region, RegionVid}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; diff --git a/src/librustc_infer/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs index b28523d955d..82fa683a290 100644 --- a/src/librustc_infer/traits/chalk_fulfill.rs +++ b/src/librustc_infer/traits/chalk_fulfill.rs @@ -5,7 +5,7 @@ use crate::traits::{ Environment, FulfillmentError, FulfillmentErrorCode, InEnvironment, ObligationCause, PredicateObligation, SelectionError, TraitEngine, }; -use crate::ty::{self, Ty}; +use rustc::ty::{self, Ty}; use rustc_data_structures::fx::FxHashSet; pub use rustc::traits::ChalkCanonicalGoal as CanonicalGoal; diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs index 4f6c9428fc2..bd4129a4de7 100644 --- a/src/librustc_infer/traits/codegen/mod.rs +++ b/src/librustc_infer/traits/codegen/mod.rs @@ -7,8 +7,8 @@ use crate::infer::{InferCtxt, TyCtxtInferExt}; use crate::traits::{ FulfillmentContext, Obligation, ObligationCause, SelectionContext, TraitEngine, Vtable, }; -use crate::ty::fold::TypeFoldable; -use crate::ty::{self, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::{self, TyCtxt}; /// Attempts to resolve an obligation to a vtable. The result is /// a shallow vtable resolution, meaning that we do not diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs index cafdb0353d5..43c0fbc27e6 100644 --- a/src/librustc_infer/traits/coherence.rs +++ b/src/librustc_infer/traits/coherence.rs @@ -8,9 +8,9 @@ use crate::infer::{CombinedSnapshot, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::SkipLeakCheck; use crate::traits::{self, Normalized, Obligation, ObligationCause, SelectionContext}; -use crate::ty::fold::TypeFoldable; -use crate::ty::subst::Subst; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::Subst; +use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs index 84bfc86e6a9..ba144379616 100644 --- a/src/librustc_infer/traits/engine.rs +++ b/src/librustc_infer/traits/engine.rs @@ -1,6 +1,6 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; -use crate::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_hir::def_id::DefId; use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError}; diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs index ab2d74b1c8d..87c1107bd42 100644 --- a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs @@ -2,8 +2,8 @@ use super::{ ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, PredicateObligation, }; use crate::infer::InferCtxt; -use crate::ty::subst::Subst; -use crate::ty::{self, GenericParamDefKind}; +use rustc::ty::subst::Subst; +use rustc::ty::{self, GenericParamDefKind}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index 82b73518d09..4a78bcf4a87 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -6,8 +6,9 @@ use super::{ use crate::infer::InferCtxt; use crate::traits::error_reporting::suggest_constraining_type_param; use crate::traits::object_safety::object_safety_violations; -use crate::ty::TypeckTables; -use crate::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; + +use rustc::ty::TypeckTables; +use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_errors::{ error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, }; diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs index 07352a3f947..6055b0e74df 100644 --- a/src/librustc_infer/traits/fulfill.rs +++ b/src/librustc_infer/traits/fulfill.rs @@ -1,6 +1,6 @@ use crate::infer::{InferCtxt, ShallowResolver}; -use crate::ty::error::ExpectedFound; -use crate::ty::{self, ToPolyTraitRef, Ty, TypeFoldable}; +use rustc::ty::error::ExpectedFound; +use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 6226d38f88e..06c6d651813 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -24,12 +24,12 @@ pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; -use crate::middle::region; -use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::fold::TypeFoldable; -use crate::ty::subst::{InternalSubsts, SubstsRef}; -use crate::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; -use crate::util::common::ErrorReported; +use rustc::middle::region; +use rustc::ty::error::{ExpectedFound, TypeError}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::util::common::ErrorReported; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index e35b03a3431..d36d66e4e25 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -12,8 +12,8 @@ use super::elaborate_predicates; use crate::infer::TyCtxtInferExt; use crate::traits::{self, Obligation, ObligationCause}; -use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -553,7 +553,7 @@ fn virtual_call_violation_for_method<'tcx>( } else { // Do sanity check to make sure the receiver actually has the layout of a pointer. - use crate::ty::layout::Abi; + use rustc::ty::layout::Abi; let param_env = tcx.param_env(method.def_id); diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_infer/traits/on_unimplemented.rs index ca824d40e38..41201c1c7ae 100644 --- a/src/librustc_infer/traits/on_unimplemented.rs +++ b/src/librustc_infer/traits/on_unimplemented.rs @@ -1,7 +1,7 @@ use fmt_macros::{Parser, Piece, Position}; -use crate::ty::{self, GenericParamDefKind, TyCtxt}; -use crate::util::common::ErrorReported; +use rustc::ty::{self, GenericParamDefKind, TyCtxt}; +use rustc::util::common::ErrorReported; use rustc_attr as attr; use rustc_data_structures::fx::FxHashMap; diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index 5d9f4ddfd16..a7c3e9110ab 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -14,9 +14,9 @@ use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableI use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; -use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::subst::{InternalSubsts, Subst}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::snapshot_map::{Snapshot, SnapshotMap}; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; diff --git a/src/librustc_infer/traits/query/normalize.rs b/src/librustc_infer/traits/query/normalize.rs index 737b4fc6bb9..4577e3d2e1c 100644 --- a/src/librustc_infer/traits/query/normalize.rs +++ b/src/librustc_infer/traits/query/normalize.rs @@ -7,9 +7,9 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; use crate::traits::project::Normalized; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; -use crate::ty::fold::{TypeFoldable, TypeFolder}; -use crate::ty::subst::Subst; -use crate::ty::{self, Ty, TyCtxt}; +use rustc::ty::fold::{TypeFoldable, TypeFolder}; +use rustc::ty::subst::Subst; +use rustc::ty::{self, Ty, TyCtxt}; use super::NoSolution; diff --git a/src/librustc_infer/traits/query/outlives_bounds.rs b/src/librustc_infer/traits/query/outlives_bounds.rs index 594faffa5f3..eb32ebf5c4d 100644 --- a/src/librustc_infer/traits/query/outlives_bounds.rs +++ b/src/librustc_infer/traits/query/outlives_bounds.rs @@ -2,7 +2,7 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::query::NoSolution; use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt}; -use crate::ty::{self, Ty}; +use rustc::ty::{self, Ty}; use rustc_hir as hir; use rustc_span::source_map::Span; diff --git a/src/librustc_infer/traits/query/type_op/eq.rs b/src/librustc_infer/traits/query/type_op/eq.rs index 1de13430d46..3b6fbc7d8dd 100644 --- a/src/librustc_infer/traits/query/type_op/eq.rs +++ b/src/librustc_infer/traits/query/type_op/eq.rs @@ -1,6 +1,6 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::Fallible; -use crate::ty::{ParamEnvAnd, TyCtxt}; +use rustc::ty::{ParamEnvAnd, TyCtxt}; pub use rustc::traits::query::type_op::Eq; diff --git a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs b/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs index 6f45d76a8e9..3dad546872e 100644 --- a/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs +++ b/src/librustc_infer/traits/query/type_op/implied_outlives_bounds.rs @@ -1,7 +1,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::outlives_bounds::OutlivesBound; use crate::traits::query::Fallible; -use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::{ParamEnvAnd, Ty, TyCtxt}; #[derive(Clone, Debug, HashStable, TypeFoldable, Lift)] pub struct ImpliedOutlivesBounds<'tcx> { diff --git a/src/librustc_infer/traits/query/type_op/mod.rs b/src/librustc_infer/traits/query/type_op/mod.rs index 5f131e97056..eb4c0a029e1 100644 --- a/src/librustc_infer/traits/query/type_op/mod.rs +++ b/src/librustc_infer/traits/query/type_op/mod.rs @@ -4,8 +4,8 @@ use crate::infer::canonical::{ use crate::infer::{InferCtxt, InferOk}; use crate::traits::query::Fallible; use crate::traits::ObligationCause; -use crate::ty::fold::TypeFoldable; -use crate::ty::{ParamEnvAnd, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::{ParamEnvAnd, TyCtxt}; use std::fmt; use std::rc::Rc; diff --git a/src/librustc_infer/traits/query/type_op/normalize.rs b/src/librustc_infer/traits/query/type_op/normalize.rs index b1e0e29620d..d2eec53bf80 100644 --- a/src/librustc_infer/traits/query/type_op/normalize.rs +++ b/src/librustc_infer/traits/query/type_op/normalize.rs @@ -1,7 +1,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::Fallible; -use crate::ty::fold::TypeFoldable; -use crate::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::fold::TypeFoldable; +use rustc::ty::{self, Lift, ParamEnvAnd, Ty, TyCtxt}; use std::fmt; pub use rustc::traits::query::type_op::Normalize; diff --git a/src/librustc_infer/traits/query/type_op/outlives.rs b/src/librustc_infer/traits/query/type_op/outlives.rs index 35afa637968..b94948cffd6 100644 --- a/src/librustc_infer/traits/query/type_op/outlives.rs +++ b/src/librustc_infer/traits/query/type_op/outlives.rs @@ -1,7 +1,7 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::dropck_outlives::{trivial_dropck_outlives, DropckOutlivesResult}; use crate::traits::query::Fallible; -use crate::ty::{ParamEnvAnd, Ty, TyCtxt}; +use rustc::ty::{ParamEnvAnd, Ty, TyCtxt}; #[derive(Copy, Clone, Debug, HashStable, TypeFoldable, Lift)] pub struct DropckOutlives<'tcx> { diff --git a/src/librustc_infer/traits/query/type_op/prove_predicate.rs b/src/librustc_infer/traits/query/type_op/prove_predicate.rs index 92cfb82e27e..8c68f7db9e5 100644 --- a/src/librustc_infer/traits/query/type_op/prove_predicate.rs +++ b/src/librustc_infer/traits/query/type_op/prove_predicate.rs @@ -1,6 +1,6 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::Fallible; -use crate::ty::{ParamEnvAnd, Predicate, TyCtxt}; +use rustc::ty::{ParamEnvAnd, Predicate, TyCtxt}; pub use rustc::traits::query::type_op::ProvePredicate; diff --git a/src/librustc_infer/traits/query/type_op/subtype.rs b/src/librustc_infer/traits/query/type_op/subtype.rs index 2877a74aaff..053411b0cac 100644 --- a/src/librustc_infer/traits/query/type_op/subtype.rs +++ b/src/librustc_infer/traits/query/type_op/subtype.rs @@ -1,6 +1,6 @@ use crate::infer::canonical::{Canonicalized, CanonicalizedQueryResponse}; use crate::traits::query::Fallible; -use crate::ty::{ParamEnvAnd, TyCtxt}; +use rustc::ty::{ParamEnvAnd, TyCtxt}; pub use rustc::traits::query::type_op::Subtype; diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index 9abf030ca38..371268b5ee4 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -33,13 +33,13 @@ use super::{ VtableGeneratorData, VtableImplData, VtableObjectData, VtableTraitAliasData, }; -use crate::dep_graph::{DepKind, DepNodeIndex}; use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; -use crate::middle::lang_items; -use crate::ty::fast_reject; -use crate::ty::relate::TypeRelation; -use crate::ty::subst::{Subst, SubstsRef}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc::dep_graph::{DepKind, DepNodeIndex}; +use rustc::middle::lang_items; +use rustc::ty::fast_reject; +use rustc::ty::relate::TypeRelation; +use rustc::ty::subst::{Subst, SubstsRef}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs index d300b6f6dd4..ee1c737c208 100644 --- a/src/librustc_infer/traits/specialize/mod.rs +++ b/src/librustc_infer/traits/specialize/mod.rs @@ -15,9 +15,9 @@ use specialization_graph::GraphExt; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; -use crate::ty::subst::{InternalSubsts, Subst, SubstsRef}; -use crate::ty::{self, TyCtxt, TypeFoldable}; use rustc::lint::LintDiagnosticBuilder; +use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; +use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/traits/structural_impls.rs b/src/librustc_infer/traits/structural_impls.rs index 80731c7b189..6630f664f96 100644 --- a/src/librustc_infer/traits/structural_impls.rs +++ b/src/librustc_infer/traits/structural_impls.rs @@ -1,7 +1,7 @@ use crate::traits; use crate::traits::project::Normalized; -use crate::ty; -use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; +use rustc::ty; +use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use std::fmt; diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 1c0638d4528..c1612a3b9a7 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -3,9 +3,9 @@ use rustc_span::Span; use smallvec::smallvec; use smallvec::SmallVec; -use crate::ty::outlives::Component; -use crate::ty::subst::{GenericArg, Subst, SubstsRef}; -use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc::ty::outlives::Component; +use rustc::ty::subst::{GenericArg, Subst, SubstsRef}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs index 48721ec04e7..89a271d0111 100644 --- a/src/librustc_infer/traits/wf.rs +++ b/src/librustc_infer/traits/wf.rs @@ -1,9 +1,9 @@ use crate::infer::opaque_types::required_region_bounds; use crate::infer::InferCtxt; -use crate::middle::lang_items; use crate::traits::{self, AssocTypeBoundData}; -use crate::ty::subst::SubstsRef; -use crate::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; +use rustc::middle::lang_items; +use rustc::ty::subst::SubstsRef; +use rustc::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Ident}; From 0b93cfc1ee3d61987e9f3229370d79acd51544a1 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 8 Jan 2020 09:31:01 +0100 Subject: [PATCH 0255/1250] Prune features. --- src/librustc_infer/lib.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index d6619e5f7f8..31ce0458164 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -14,37 +14,14 @@ //! This API is completely unstable and subject to change. #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] -#![feature(arbitrary_self_types)] #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(const_fn)] -#![feature(const_transmute)] -#![feature(core_intrinsics)] #![feature(drain_filter)] -#![cfg_attr(windows, feature(libc))] #![feature(never_type)] -#![feature(exhaustive_patterns)] -#![feature(overlapping_marker_traits)] -#![feature(extern_types)] -#![feature(nll)] -#![feature(optin_builtin_traits)] -#![feature(option_expect_none)] #![feature(range_is_empty)] -#![feature(specialization)] -#![feature(unboxed_closures)] -#![feature(thread_local)] -#![feature(trace_macros)] -#![feature(trusted_len)] -#![feature(stmt_expr_attributes)] -#![feature(integer_atomics)] -#![feature(test)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![feature(log_syntax)] -#![feature(associated_type_bounds)] -#![feature(rustc_attrs)] -#![feature(hash_raw_entry)] #![recursion_limit = "512"] #[macro_use] From 5d5720835329230c60cb7b4f56e2a9b234dae6cf Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 8 Jan 2020 10:18:48 +0100 Subject: [PATCH 0256/1250] Gate macro use. --- src/librustc_infer/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 31ce0458164..6c66ef47f33 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -26,6 +26,7 @@ #[macro_use] extern crate rustc_macros; +#[cfg(target_arch = "x86_64")] #[macro_use] extern crate rustc_data_structures; #[macro_use] From e88500b5e18bbbad2323944d3c23f8a4465eb147 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 7 Feb 2020 09:06:08 +0100 Subject: [PATCH 0257/1250] Prune rustc dependencies. --- Cargo.lock | 2 -- src/librustc/Cargo.toml | 2 -- 2 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ff9d419c5d..f13a581bc79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3111,8 +3111,6 @@ dependencies = [ "bitflags", "byteorder", "chalk-engine", - "fmt_macros", - "graphviz", "jobserver", "log", "measureme", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index 782c6879ac5..af2be30cc0a 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -12,8 +12,6 @@ doctest = false [dependencies] arena = { path = "../libarena" } bitflags = "1.2.1" -fmt_macros = { path = "../libfmt_macros" } -graphviz = { path = "../libgraphviz" } jobserver = "0.1" scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } From bb482ebf2870bae6e1b69822f1c7d7d9d4b33103 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Feb 2020 13:08:36 +0100 Subject: [PATCH 0258/1250] suspend -> yield --- src/librustc/mir/mod.rs | 4 +--- src/test/mir-opt/generator-storage-dead-unwind.rs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a3e3a26db05..9b94f92acd4 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1475,9 +1475,7 @@ impl<'tcx> TerminatorKind<'tcx> { GeneratorDrop => write!(fmt, "generator_drop"), Resume => write!(fmt, "resume"), Abort => write!(fmt, "abort"), - Yield { value, resume_arg, .. } => { - write!(fmt, "{:?} = suspend({:?})", resume_arg, value) - } + Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Unreachable => write!(fmt, "unreachable"), Drop { location, .. } => write!(fmt, "drop({:?})", location), DropAndReplace { location, value, .. } => { diff --git a/src/test/mir-opt/generator-storage-dead-unwind.rs b/src/test/mir-opt/generator-storage-dead-unwind.rs index 98acce83759..82b216a99cf 100644 --- a/src/test/mir-opt/generator-storage-dead-unwind.rs +++ b/src/test/mir-opt/generator-storage-dead-unwind.rs @@ -49,7 +49,7 @@ fn main() { // StorageLive(_4); // _4 = Bar(const 6i32,); // ... -// _5 = suspend(move _6) -> [resume: bb2, drop: bb4]; +// _5 = yield(move _6) -> [resume: bb2, drop: bb4]; // } // bb1 (cleanup): { // resume; From 943e65396d7bc7b91bcc30407d323d06f4b20a22 Mon Sep 17 00:00:00 2001 From: Amos Onn Date: Sat, 15 Feb 2020 00:34:15 +0100 Subject: [PATCH 0259/1250] Improve #Safety of core::ptr::drop_in_place Added missing conditions: - Valid for writes - Valid for destructing --- src/libcore/ptr/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 7fb2d4f0399..88b490a25d5 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -119,10 +119,13 @@ mod mut_ptr; /// /// Behavior is undefined if any of the following conditions are violated: /// -/// * `to_drop` must be [valid] for reads. +/// * `to_drop` must be [valid] for both reads and writes. /// /// * `to_drop` must be properly aligned. /// +/// * The value `to_drop` points to must be valid for dropping, which may mean it must uphold +/// additional invariants - this is type-dependent. +/// /// Additionally, if `T` is not [`Copy`], using the pointed-to value after /// calling `drop_in_place` can cause undefined behavior. Note that `*to_drop = /// foo` counts as a use because it will cause the value to be dropped From bec5d37ee19c33bec96ed235f0197317d3728e0a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Feb 2020 14:44:16 +0100 Subject: [PATCH 0260/1250] debug_assert a few more raw pointer methods --- src/libcore/intrinsics.rs | 9 +++++---- src/libcore/ptr/mod.rs | 12 +++++++++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2cee23a5c75..9a23b54dfa0 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1423,13 +1423,14 @@ pub(crate) fn is_aligned_and_not_null(ptr: *const T) -> bool { } /// Checks whether the regions of memory starting at `src` and `dst` of size -/// `count * size_of::()` overlap. -fn overlaps(src: *const T, dst: *const T, count: usize) -> bool { +/// `count * size_of::()` do *not* overlap. +pub(crate) fn is_nonoverlapping(src: *const T, dst: *const T, count: usize) -> bool { let src_usize = src as usize; let dst_usize = dst as usize; let size = mem::size_of::().checked_mul(count).unwrap(); let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize }; - size > diff + let overlaps = size > diff; + !overlaps } /// Copies `count * size_of::()` bytes from `src` to `dst`. The source @@ -1524,7 +1525,7 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { debug_assert!(is_aligned_and_not_null(src), "attempt to copy from unaligned or null pointer"); debug_assert!(is_aligned_and_not_null(dst), "attempt to copy to unaligned or null pointer"); - debug_assert!(!overlaps(src, dst, count), "attempt to copy to overlapping memory"); + debug_assert!(is_nonoverlapping(src, dst, count), "attempt to copy to overlapping memory"); copy_nonoverlapping(src, dst, count) } diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 0ee50966f96..ce21773165a 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -72,7 +72,7 @@ use crate::cmp::Ordering; use crate::fmt; use crate::hash; -use crate::intrinsics; +use crate::intrinsics::{self, is_aligned_and_not_null, is_nonoverlapping}; use crate::mem::{self, MaybeUninit}; #[stable(feature = "rust1", since = "1.0.0")] @@ -389,6 +389,10 @@ pub unsafe fn swap(x: *mut T, y: *mut T) { #[inline] #[stable(feature = "swap_nonoverlapping", since = "1.27.0")] pub unsafe fn swap_nonoverlapping(x: *mut T, y: *mut T, count: usize) { + debug_assert!(is_aligned_and_not_null(x), "attempt to swap unaligned or null pointer"); + debug_assert!(is_aligned_and_not_null(y), "attempt to swap unaligned or null pointer"); + debug_assert!(is_nonoverlapping(x, y, count), "attempt to swap overlapping memory"); + let x = x as *mut u8; let y = y as *mut u8; let len = mem::size_of::() * count; @@ -612,6 +616,7 @@ pub unsafe fn replace(dst: *mut T, mut src: T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn read(src: *const T) -> T { + // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::::uninit(); copy_nonoverlapping(src, tmp.as_mut_ptr(), 1); tmp.assume_init() @@ -703,6 +708,7 @@ pub unsafe fn read(src: *const T) -> T { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn read_unaligned(src: *const T) -> T { + // `copy_nonoverlapping` takes care of debug_assert. let mut tmp = MaybeUninit::::uninit(); copy_nonoverlapping(src as *const u8, tmp.as_mut_ptr() as *mut u8, mem::size_of::()); tmp.assume_init() @@ -795,6 +801,7 @@ pub unsafe fn read_unaligned(src: *const T) -> T { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub unsafe fn write(dst: *mut T, src: T) { + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); intrinsics::move_val_init(&mut *dst, src) } @@ -887,6 +894,7 @@ pub unsafe fn write(dst: *mut T, src: T) { #[inline] #[stable(feature = "ptr_unaligned", since = "1.17.0")] pub unsafe fn write_unaligned(dst: *mut T, src: T) { + // `copy_nonoverlapping` takes care of debug_assert. copy_nonoverlapping(&src as *const T as *const u8, dst as *mut u8, mem::size_of::()); mem::forget(src); } @@ -956,6 +964,7 @@ pub unsafe fn write_unaligned(dst: *mut T, src: T) { #[inline] #[stable(feature = "volatile", since = "1.9.0")] pub unsafe fn read_volatile(src: *const T) -> T { + debug_assert!(is_aligned_and_not_null(src), "attempt to read from unaligned or null pointer"); intrinsics::volatile_load(src) } @@ -1024,6 +1033,7 @@ pub unsafe fn read_volatile(src: *const T) -> T { #[inline] #[stable(feature = "volatile", since = "1.9.0")] pub unsafe fn write_volatile(dst: *mut T, src: T) { + debug_assert!(is_aligned_and_not_null(dst), "attempt to write to unaligned or null pointer"); intrinsics::volatile_store(dst, src); } From d1a7ae7d1659dae412dde2eadeaf1cf7c9d87570 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 16 Feb 2020 17:12:03 +0900 Subject: [PATCH 0261/1250] Allow whitespaces in revision flags --- src/tools/compiletest/src/header.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 555e79d3e06..2a24a8c3c94 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -631,10 +631,6 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn let comment = if testfile.to_string_lossy().ends_with(".rs") { "//" } else { "#" }; - // FIXME: would be nice to allow some whitespace between comment and brace :) - // It took me like 2 days to debug why compile-flags weren’t taken into account for my test :) - let comment_with_brace = comment.to_string() + "["; - let mut rdr = BufReader::new(rdr); let mut ln = String::new(); @@ -650,7 +646,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn let ln = ln.trim(); if ln.starts_with("fn") || ln.starts_with("mod") { return; - } else if ln.starts_with(&comment_with_brace) { + } else if ln.starts_with(comment) && ln[comment.len()..].trim_start().starts_with('[') { // A comment like `//[foo]` is specific to revision `foo` if let Some(close_brace) = ln.find(']') { let open_brace = ln.find('[').unwrap(); @@ -663,10 +659,7 @@ fn iter_header(testfile: &Path, cfg: Option<&str>, rdr: R, it: &mut dyn it(ln[(close_brace + 1)..].trim_start()); } } else { - panic!( - "malformed condition directive: expected `{}foo]`, found `{}`", - comment_with_brace, ln - ) + panic!("malformed condition directive: expected `{}[foo]`, found `{}`", comment, ln) } } else if ln.starts_with(comment) { it(ln[comment.len()..].trim_start()); From 0891496898423bd03227a27492816ef56319d95c Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 16 Feb 2020 17:12:26 +0100 Subject: [PATCH 0262/1250] Improve documentation on iterators --- src/libcore/iter/mod.rs | 3 ++- src/libcore/iter/traits/exact_size.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 5fa9962f811..080b70c6368 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -43,7 +43,7 @@ //! are elements, and once they've all been exhausted, will return `None` to //! indicate that iteration is finished. Individual iterators may choose to //! resume iteration, and so calling [`next`] again may or may not eventually -//! start returning `Some(Item)` again at some point. +//! start returning `Some(Item)` again at some point (for example, see [`TryIter`]). //! //! [`Iterator`]'s full definition includes a number of other methods as well, //! but they are default methods, built on top of [`next`], and so you get @@ -56,6 +56,7 @@ //! [`Iterator`]: trait.Iterator.html //! [`next`]: trait.Iterator.html#tymethod.next //! [`Option`]: ../../std/option/enum.Option.html +//! [`TryIter`]: ../../std/sync/mpsc/struct.TryIter.html //! //! # The three forms of iteration //! diff --git a/src/libcore/iter/traits/exact_size.rs b/src/libcore/iter/traits/exact_size.rs index 4a7db348b18..946c3f85824 100644 --- a/src/libcore/iter/traits/exact_size.rs +++ b/src/libcore/iter/traits/exact_size.rs @@ -69,7 +69,8 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { - /// Returns the exact number of times the iterator will iterate. + /// Returns the exact length of the iterator, which is the number of times + /// the iterator will return `Some(T)` before returning `None`. /// /// This method has a default implementation, so you usually should not /// implement it directly. However, if you can provide a more efficient From 2ae493a767536b0a5180c788d9ecf2b7ea8bf749 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 16 Feb 2020 18:53:02 +0100 Subject: [PATCH 0263/1250] Stabilize {f32, f64}::{LOG2_10, LOG10_2} --- src/libcore/num/f32.rs | 4 ++-- src/libcore/num/f64.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index da8dd9acd9f..0a4fc6464ca 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -130,7 +130,7 @@ pub mod consts { pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32; /// log2(10) - #[unstable(feature = "extra_log_consts", issue = "50540")] + #[stable(feature = "extra_log_consts", since = "1.43.0")] pub const LOG2_10: f32 = 3.32192809488736234787031942948939018_f32; /// log10(e) @@ -138,7 +138,7 @@ pub mod consts { pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32; /// log10(2) - #[unstable(feature = "extra_log_consts", issue = "50540")] + #[stable(feature = "extra_log_consts", since = "1.43.0")] pub const LOG10_2: f32 = 0.301029995663981195213738894724493027_f32; /// ln(2) diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index a6081f184ab..a3acf0f23c4 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -126,7 +126,7 @@ pub mod consts { pub const E: f64 = 2.71828182845904523536028747135266250_f64; /// log2(10) - #[unstable(feature = "extra_log_consts", issue = "50540")] + #[stable(feature = "extra_log_consts", since = "1.43.0")] pub const LOG2_10: f64 = 3.32192809488736234787031942948939018_f64; /// log2(e) @@ -134,7 +134,7 @@ pub mod consts { pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64; /// log10(2) - #[unstable(feature = "extra_log_consts", issue = "50540")] + #[stable(feature = "extra_log_consts", since = "1.43.0")] pub const LOG10_2: f64 = 0.301029995663981195213738894724493027_f64; /// log10(e) From 914b855f40c10f1db627bef5543e5c2edfe50b14 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Sun, 2 Feb 2020 20:30:52 +0100 Subject: [PATCH 0264/1250] Fix comments outdated during #66648 --- src/liballoc/collections/btree/map.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 5b4b1c93347..74069bbf8a3 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -227,7 +227,7 @@ impl BTreeClone for BTreeMap { impl BTreeClone for BTreeMap { fn clone_from(&mut self, other: &Self) { // This truncates `self` to `other.len()` by calling `split_off` on - // the first key after `other.len()` elements if it exists + // the first key after `other.len()` elements if it exists. let split_off_key = if self.len() > other.len() { let diff = self.len() - other.len(); if diff <= other.len() { @@ -247,11 +247,10 @@ impl BTreeClone for BTreeMap { // After truncation, `self` is at most as long as `other` so this loop // replaces every key-value pair in `self`. Since `oiter` is in sorted // order and the structure of the `BTreeMap` stays the same, - // the BTree invariants are maintained at the end of the loop + // the BTree invariants are maintained at the end of the loop. while !siter.is_empty() { if let Some((ok, ov)) = oiter.next() { - // SAFETY: This is safe because the `siter.front != siter.back` check - // ensures that `siter` is nonempty + // SAFETY: This is safe because `siter` is nonempty. let (sk, sv) = unsafe { siter.next_unchecked() }; sk.clone_from(ok); sv.clone_from(ov); @@ -259,7 +258,7 @@ impl BTreeClone for BTreeMap { break; } } - // If `other` is longer than `self`, the remaining elements are inserted + // If `other` is longer than `self`, the remaining elements are inserted. self.extend(oiter.map(|(k, v)| ((*k).clone(), (*v).clone()))); } } From da226dd9dcff81aba6a6bd032057816e88555abf Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Sun, 16 Feb 2020 20:01:41 +0100 Subject: [PATCH 0265/1250] Lighten tests, in particular for Miri, yet test and explain more --- src/liballoc/tests/btree/map.rs | 52 ++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 0a26d7bf427..4a9af64f9d4 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -15,7 +15,7 @@ fn test_basic_large() { #[cfg(not(miri))] // Miri is too slow let size = 10000; #[cfg(miri)] - let size = 200; + let size = 144; // to obtain height 3 tree (having edges to both kinds of nodes) assert_eq!(map.len(), 0); for i in 0..size { @@ -381,8 +381,8 @@ fn test_range_small() { } #[test] -fn test_range_depth_2() { - // Assuming that node.CAPACITY is 11, having 12 pairs implies a depth 2 tree +fn test_range_height_2() { + // Assuming that node.CAPACITY is 11, having 12 pairs implies a height 2 tree // with 2 leaves. Depending on details we don't want or need to rely upon, // the single key at the root will be 6 or 7. @@ -524,7 +524,7 @@ fn test_range_1000() { #[cfg(not(miri))] // Miri is too slow let size = 1000; #[cfg(miri)] - let size = 200; + let size = 144; // to obtain height 3 tree (having edges to both kinds of nodes) let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { @@ -561,14 +561,15 @@ fn test_range_borrowed_key() { #[test] fn test_range() { - #[cfg(not(miri))] // Miri is too slow let size = 200; + #[cfg(not(miri))] // Miri is too slow + let step = 1; #[cfg(miri)] - let size = 30; + let step = 66; let map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - for i in 0..size { - for j in i..size { + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { let mut kvs = map.range((Included(&i), Included(&j))).map(|(&k, &v)| (k, v)); let mut pairs = (i..=j).map(|i| (i, i)); @@ -583,14 +584,15 @@ fn test_range() { #[test] fn test_range_mut() { - #[cfg(not(miri))] // Miri is too slow let size = 200; + #[cfg(not(miri))] // Miri is too slow + let step = 1; #[cfg(miri)] - let size = 30; + let step = 66; let mut map: BTreeMap<_, _> = (0..size).map(|i| (i, i)).collect(); - for i in 0..size { - for j in i..size { + for i in (0..size).step_by(step) { + for j in (i..size).step_by(step) { let mut kvs = map.range_mut((Included(&i), Included(&j))).map(|(&k, &mut v)| (k, v)); let mut pairs = (i..=j).map(|i| (i, i)); @@ -758,10 +760,7 @@ fn test_bad_zst() { #[test] fn test_clone() { let mut map = BTreeMap::new(); - #[cfg(not(miri))] // Miri is too slow - let size = 100; - #[cfg(miri)] - let size = 30; + let size = 12; // to obtain height 2 tree (having edges to leaf nodes) assert_eq!(map.len(), 0); for i in 0..size { @@ -788,24 +787,36 @@ fn test_clone() { assert_eq!(map.len(), size / 2 - i - 1); assert_eq!(map, map.clone()); } + + // Full 2-level and minimal 3-level tree (sizes 143, 144 -- the only ones we clone for). + for i in 1..=144 { + assert_eq!(map.insert(i, i), None); + assert_eq!(map.len(), i); + if i >= 143 { + assert_eq!(map, map.clone()); + } + } } #[test] fn test_clone_from() { let mut map1 = BTreeMap::new(); - let size = 30; + let max_size = 12; // to obtain height 2 tree (having edges to leaf nodes) - for i in 0..size { + // Range to max_size inclusive, because i is the size of map1 being tested. + for i in 0..=max_size { let mut map2 = BTreeMap::new(); for j in 0..i { let mut map1_copy = map2.clone(); - map1_copy.clone_from(&map1); + map1_copy.clone_from(&map1); // small cloned from large assert_eq!(map1_copy, map1); let mut map2_copy = map1.clone(); - map2_copy.clone_from(&map2); + map2_copy.clone_from(&map2); // large cloned from small assert_eq!(map2_copy, map2); map2.insert(100 * j + 1, 2 * j + 1); } + map2.clone_from(&map1); // same length + assert_eq!(map2, map1); map1.insert(i, 10 * i); } } @@ -956,6 +967,7 @@ create_append_test!(test_append_145, 145); // Tests for several randomly chosen sizes. create_append_test!(test_append_170, 170); create_append_test!(test_append_181, 181); +#[cfg(not(miri))] // Miri is too slow create_append_test!(test_append_239, 239); #[cfg(not(miri))] // Miri is too slow create_append_test!(test_append_1700, 1700); From 84c024d92f34206d0f02ab814c6e5bd3abb876c3 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sun, 16 Feb 2020 23:23:44 +0100 Subject: [PATCH 0266/1250] Clarify mir block merging --- src/librustc_mir/transform/simplify.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index d8de9f2180d..1534b9bdcea 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -95,6 +95,10 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { let mut start = START_BLOCK; + // Vec of the blocks that should be merged. We store the indices here, instead of the + // statements itself to avoid moving the (relatively) large statements twice. + // We do not push the statements directly into the target block (`bb`) as that is slower + // due to additional reallocations let mut merged_blocks = Vec::new(); loop { let mut changed = false; @@ -116,6 +120,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } let mut inner_changed = true; + merged_blocks.clear(); while inner_changed { inner_changed = false; inner_changed |= self.simplify_branch(&mut terminator); @@ -134,7 +139,6 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { } self.basic_blocks[bb].statements = statements; } - merged_blocks.clear(); self.basic_blocks[bb].terminator = Some(terminator); From a9b5c692d9319a993ca5dfa6e853a3f5d3f68079 Mon Sep 17 00:00:00 2001 From: spunit262 <45582704+spunit262@users.noreply.github.com> Date: Thu, 13 Feb 2020 23:51:47 -0700 Subject: [PATCH 0267/1250] Ignore GDB versions with broken str printing. https://sourceware.org/bugzilla/show_bug.cgi?id=22236 --- src/test/debuginfo/empty-string.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs index 8c5f67a6604..bc4fac3183c 100644 --- a/src/test/debuginfo/empty-string.rs +++ b/src/test/debuginfo/empty-string.rs @@ -2,6 +2,7 @@ // ignore-android: FIXME(#10381) // compile-flags:-g // min-gdb-version: 7.7 +// ignore-gdb-version: 7.11.90 - 8.0.9 // min-lldb-version: 310 // === GDB TESTS =================================================================================== From c53693d34d83e6221dc8b93a2c4e17e66fa6f0e2 Mon Sep 17 00:00:00 2001 From: Fisher Darling Date: Thu, 12 Dec 2019 21:18:21 -0700 Subject: [PATCH 0268/1250] Handle recursion_limit parsing errors --- src/librustc/lib.rs | 1 + src/librustc/middle/recursion_limit.rs | 46 ++++++++++++++++--- src/test/ui/recursion_limit/empty.rs | 6 +++ src/test/ui/recursion_limit/empty.stderr | 10 ++++ src/test/ui/recursion_limit/invalid_digit.rs | 6 +++ .../ui/recursion_limit/invalid_digit.stderr | 10 ++++ src/test/ui/recursion_limit/overflow.rs | 7 +++ src/test/ui/recursion_limit/overflow.stderr | 10 ++++ src/test/ui/recursion_limit/zero.rs | 12 +++++ src/test/ui/recursion_limit/zero.stderr | 10 ++++ 10 files changed, 112 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/recursion_limit/empty.rs create mode 100644 src/test/ui/recursion_limit/empty.stderr create mode 100644 src/test/ui/recursion_limit/invalid_digit.rs create mode 100644 src/test/ui/recursion_limit/invalid_digit.stderr create mode 100644 src/test/ui/recursion_limit/overflow.rs create mode 100644 src/test/ui/recursion_limit/overflow.stderr create mode 100644 src/test/ui/recursion_limit/zero.rs create mode 100644 src/test/ui/recursion_limit/zero.stderr diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index ceac68704d2..b5c88b33b4a 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -50,6 +50,7 @@ #![feature(associated_type_bounds)] #![feature(rustc_attrs)] #![feature(hash_raw_entry)] +#![feature(int_error_matching)] #![recursion_limit = "512"] #[macro_use] diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/recursion_limit.rs index b33cde8e2af..be530da5910 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/recursion_limit.rs @@ -6,26 +6,60 @@ // just peeks and looks for that attribute. use crate::session::Session; +use core::num::IntErrorKind; +use rustc::bug; use rustc_span::symbol::{sym, Symbol}; use syntax::ast; use rustc_data_structures::sync::Once; pub fn update_limits(sess: &Session, krate: &ast::Crate) { - update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 128); - update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576); + update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); + update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); } -fn update_limit(krate: &ast::Crate, limit: &Once, name: Symbol, default: usize) { +fn update_limit( + sess: &Session, + krate: &ast::Crate, + limit: &Once, + name: Symbol, + default: usize, +) { for attr in &krate.attrs { if !attr.check_name(name) { continue; } if let Some(s) = attr.value_str() { - if let Some(n) = s.as_str().parse().ok() { - limit.set(n); - return; + match s.as_str().parse() { + Ok(n) => { + limit.set(n); + return; + } + Err(e) => { + let mut err = sess.struct_span_err( + attr.span, + "`recursion_limit` must be a non-negative integer", + ); + + let value_span = attr + .meta() + .and_then(|meta| meta.name_value_literal().cloned()) + .map(|lit| lit.span) + .unwrap_or(attr.span); + + let error_str = match e.kind() { + IntErrorKind::Overflow => "`recursion_limit` is too large", + IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer", + IntErrorKind::InvalidDigit => "not a valid integer", + IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"), + IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"), + kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), + }; + + err.span_label(value_span, error_str); + err.emit(); + } } } } diff --git a/src/test/ui/recursion_limit/empty.rs b/src/test/ui/recursion_limit/empty.rs new file mode 100644 index 00000000000..2a064f3e115 --- /dev/null +++ b/src/test/ui/recursion_limit/empty.rs @@ -0,0 +1,6 @@ +// Test the parse error for an empty recursion_limit + +#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer + //~| `recursion_limit` must be a non-negative integer + +fn main() {} diff --git a/src/test/ui/recursion_limit/empty.stderr b/src/test/ui/recursion_limit/empty.stderr new file mode 100644 index 00000000000..690c33a7463 --- /dev/null +++ b/src/test/ui/recursion_limit/empty.stderr @@ -0,0 +1,10 @@ +error: `recursion_limit` must be a non-negative integer + --> $DIR/empty.rs:3:1 + | +LL | #![recursion_limit = ""] + | ^^^^^^^^^^^^^^^^^^^^^--^ + | | + | `recursion_limit` must be a non-negative integer + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/invalid_digit.rs b/src/test/ui/recursion_limit/invalid_digit.rs new file mode 100644 index 00000000000..903d8040476 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_digit.rs @@ -0,0 +1,6 @@ +// Test the parse error for an invalid digit in recursion_limit + +#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer + //~| not a valid integer + +fn main() {} diff --git a/src/test/ui/recursion_limit/invalid_digit.stderr b/src/test/ui/recursion_limit/invalid_digit.stderr new file mode 100644 index 00000000000..1dcfea547c0 --- /dev/null +++ b/src/test/ui/recursion_limit/invalid_digit.stderr @@ -0,0 +1,10 @@ +error: `recursion_limit` must be a non-negative integer + --> $DIR/invalid_digit.rs:3:1 + | +LL | #![recursion_limit = "-100"] + | ^^^^^^^^^^^^^^^^^^^^^------^ + | | + | not a valid integer + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/overflow.rs b/src/test/ui/recursion_limit/overflow.rs new file mode 100644 index 00000000000..6487b1350aa --- /dev/null +++ b/src/test/ui/recursion_limit/overflow.rs @@ -0,0 +1,7 @@ +// Test the parse error for an overflowing recursion_limit + +#![recursion_limit = "999999999999999999999999"] +//~^ ERROR `recursion_limit` must be a non-negative integer +//~| `recursion_limit` is too large + +fn main() {} diff --git a/src/test/ui/recursion_limit/overflow.stderr b/src/test/ui/recursion_limit/overflow.stderr new file mode 100644 index 00000000000..c3fc11989dc --- /dev/null +++ b/src/test/ui/recursion_limit/overflow.stderr @@ -0,0 +1,10 @@ +error: `recursion_limit` must be a non-negative integer + --> $DIR/overflow.rs:3:1 + | +LL | #![recursion_limit = "999999999999999999999999"] + | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ + | | + | `recursion_limit` is too large + +error: aborting due to previous error + diff --git a/src/test/ui/recursion_limit/zero.rs b/src/test/ui/recursion_limit/zero.rs new file mode 100644 index 00000000000..f7199944e00 --- /dev/null +++ b/src/test/ui/recursion_limit/zero.rs @@ -0,0 +1,12 @@ +// Test that a `recursion_limit` of 0 is valid + +#![recursion_limit = "0"] + +macro_rules! test { + () => {}; + ($tt:tt) => { test!(); }; +} + +test!(test); //~ ERROR 10:1: 10:13: recursion limit reached while expanding `test!` + +fn main() {} diff --git a/src/test/ui/recursion_limit/zero.stderr b/src/test/ui/recursion_limit/zero.stderr new file mode 100644 index 00000000000..6358805d89d --- /dev/null +++ b/src/test/ui/recursion_limit/zero.stderr @@ -0,0 +1,10 @@ +error: recursion limit reached while expanding `test!` + --> $DIR/zero.rs:10:1 + | +LL | test!(test); + | ^^^^^^^^^^^^ + | + = help: consider adding a `#![recursion_limit="0"]` attribute to your crate (`zero`) + +error: aborting due to previous error + From eb12ed889d86de7139d6485f18736f13c0f5a076 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 15 Feb 2020 12:10:59 +0900 Subject: [PATCH 0269/1250] Rename `FunctionRetTy` to `FnRetTy` --- src/librustc_ast_lowering/expr.rs | 8 ++++---- src/librustc_ast_lowering/lib.rs | 18 +++++++++--------- src/librustc_ast_lowering/path.rs | 4 ++-- src/librustc_ast_passes/ast_validation.rs | 2 +- src/librustc_ast_passes/feature_gate.rs | 4 ++-- src/librustc_ast_pretty/pprust.rs | 4 ++-- src/librustc_ast_pretty/pprust/tests.rs | 6 ++---- .../deriving/generic/mod.rs | 2 +- .../global_allocator.rs | 2 +- src/librustc_builtin_macros/test.rs | 4 ++-- src/librustc_builtin_macros/test_harness.rs | 2 +- src/librustc_expand/build.rs | 4 ++-- src/librustc_hir/hir.rs | 10 +++++----- src/librustc_hir/intravisit.rs | 4 ++-- .../infer/error_reporting/need_type_info.rs | 6 +++--- .../nice_region_error/named_anon_conflict.rs | 4 ++-- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_interface/util.rs | 4 ++-- src/librustc_lint/types.rs | 2 +- .../diagnostics/conflict_errors.rs | 2 +- .../borrow_check/diagnostics/region_name.rs | 4 ++-- src/librustc_parse/parser/expr.rs | 6 ++---- src/librustc_parse/parser/ty.rs | 10 ++++------ src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/lifetimes.rs | 4 ++-- src/librustc_save_analysis/dump_visitor.rs | 10 +++++----- src/librustc_save_analysis/lib.rs | 4 ++-- src/librustc_save_analysis/sig.rs | 8 ++++---- src/librustc_typeck/astconv.rs | 4 ++-- src/librustc_typeck/check/closure.rs | 6 +++--- src/librustc_typeck/check/coercion.rs | 6 +++--- src/librustc_typeck/check/mod.rs | 10 +++++----- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 6 +++--- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/clean/types.rs | 14 +++++++------- src/librustdoc/clean/utils.rs | 4 ++-- src/librustdoc/html/format.rs | 2 +- src/libsyntax/ast.rs | 13 ++++++------- src/libsyntax/mut_visit.rs | 6 +++--- src/libsyntax/visit.rs | 6 +++--- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 2 +- 42 files changed, 111 insertions(+), 118 deletions(-) diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index b51d4765583..e2dd55b4cba 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -480,8 +480,8 @@ impl<'hir> LoweringContext<'_, 'hir> { body: impl FnOnce(&mut Self) -> hir::Expr<'hir>, ) -> hir::ExprKind<'hir> { let output = match ret_ty { - Some(ty) => FunctionRetTy::Ty(ty), - None => FunctionRetTy::Default(span), + Some(ty) => FnRetTy::Ty(ty), + None => FnRetTy::Default(span), }; let ast_decl = FnDecl { inputs: vec![], output }; let decl = self.lower_fn_decl(&ast_decl, None, /* impl trait allowed */ false, None); @@ -721,7 +721,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_decl_span: Span, ) -> hir::ExprKind<'hir> { let outer_decl = - FnDecl { inputs: decl.inputs.clone(), output: FunctionRetTy::Default(fn_decl_span) }; + FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. @@ -747,7 +747,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // `|x: u8| future_from_generator(|| -> X { ... })`. let body_id = this.lower_fn_body(&outer_decl, |this| { let async_ret_ty = - if let FunctionRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None }; + if let FnRetTy::Ty(ty) = &decl.output { Some(ty.clone()) } else { None }; let async_body = this.make_async_expr( capture_clause, closure_id, diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 30fe7de5df4..56c844b37da 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -1725,16 +1725,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) } else { match decl.output { - FunctionRetTy::Ty(ref ty) => { + FnRetTy::Ty(ref ty) => { let context = match in_band_ty_params { Some((def_id, _)) if impl_trait_return_allow => { ImplTraitContext::OpaqueTy(Some(def_id), hir::OpaqueTyOrigin::FnReturn) } _ => ImplTraitContext::disallowed(), }; - hir::FunctionRetTy::Return(self.lower_ty(ty, context)) + hir::FnRetTy::Return(self.lower_ty(ty, context)) } - FunctionRetTy::Default(span) => hir::FunctionRetTy::DefaultReturn(span), + FnRetTy::Default(span) => hir::FnRetTy::DefaultReturn(span), } }; @@ -1781,10 +1781,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // `elided_lt_replacement`: replacement for elided lifetimes in the return type fn lower_async_fn_ret_ty( &mut self, - output: &FunctionRetTy, + output: &FnRetTy, fn_def_id: DefId, opaque_ty_node_id: NodeId, - ) -> hir::FunctionRetTy<'hir> { + ) -> hir::FnRetTy<'hir> { debug!( "lower_async_fn_ret_ty(\ output={:?}, \ @@ -1949,19 +1949,19 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // only the lifetime parameters that we must supply. let opaque_ty_ref = hir::TyKind::Def(hir::ItemId { id: opaque_ty_id }, generic_args); let opaque_ty = self.ty(opaque_ty_span, opaque_ty_ref); - hir::FunctionRetTy::Return(self.arena.alloc(opaque_ty)) + hir::FnRetTy::Return(self.arena.alloc(opaque_ty)) } /// Transforms `-> T` into `Future` fn lower_async_fn_output_type_to_future_bound( &mut self, - output: &FunctionRetTy, + output: &FnRetTy, fn_def_id: DefId, span: Span, ) -> hir::GenericBound<'hir> { // Compute the `T` in `Future` from the return type. let output_ty = match output { - FunctionRetTy::Ty(ty) => { + FnRetTy::Ty(ty) => { // Not `OpaqueTyOrigin::AsyncFn`: that's only used for the // `impl Future` opaque type that `async fn` implicitly // generates. @@ -1969,7 +1969,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ImplTraitContext::OpaqueTy(Some(fn_def_id), hir::OpaqueTyOrigin::FnReturn); self.lower_ty(ty, context) } - FunctionRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), + FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])), }; // "" diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index e5f7df6dbf9..b45a06e1c1d 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -397,8 +397,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { inputs.iter().map(|ty| this.lower_ty_direct(ty, ImplTraitContext::disallowed())), ); let output_ty = match output { - FunctionRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()), - FunctionRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])), + FnRetTy::Ty(ty) => this.lower_ty(&ty, ImplTraitContext::disallowed()), + FnRetTy::Default(_) => this.arena.alloc(this.ty_tup(span, &[])), }; let args = smallvec![GenericArg::Type(this.ty_tup(span, inputs))]; let binding = this.output_ty_binding(output_ty.span, output_ty); diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 2f0495b8b5a..584f7b4b4bb 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -954,7 +954,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } GenericArgs::Parenthesized(ref data) => { walk_list!(self, visit_ty, &data.inputs); - if let FunctionRetTy::Ty(ty) = &data.output { + if let FnRetTy::Ty(ty) = &data.output { // `-> Foo` syntax is essentially an associated type binding, // so it is also allowed to contain nested `impl Trait`. self.with_impl_trait(None, |this| this.visit_ty(ty)); diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 0b21de4d78b..d57c7495a07 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -419,8 +419,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { visit::walk_ty(self, ty) } - fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FunctionRetTy) { - if let ast::FunctionRetTy::Ty(ref output_ty) = *ret_ty { + fn visit_fn_ret_ty(&mut self, ret_ty: &'a ast::FnRetTy) { + if let ast::FnRetTy::Ty(ref output_ty) = *ret_ty { if let ast::TyKind::Never = output_ty.kind { // Do nothing. } else { diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 75938470b6f..20b1ff06034 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -2673,8 +2673,8 @@ impl<'a> State<'a> { self.end(); } - crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FunctionRetTy) { - if let ast::FunctionRetTy::Ty(ty) = fn_ret_ty { + crate fn print_fn_ret_ty(&mut self, fn_ret_ty: &ast::FnRetTy) { + if let ast::FnRetTy::Ty(ty) = fn_ret_ty { self.space_if_not_bol(); self.ibox(INDENT_UNIT); self.word_space("->"); diff --git a/src/librustc_ast_pretty/pprust/tests.rs b/src/librustc_ast_pretty/pprust/tests.rs index 279e6f518a7..2c938453533 100644 --- a/src/librustc_ast_pretty/pprust/tests.rs +++ b/src/librustc_ast_pretty/pprust/tests.rs @@ -34,10 +34,8 @@ fn test_fun_to_string() { with_default_globals(|| { let abba_ident = ast::Ident::from_str("abba"); - let decl = ast::FnDecl { - inputs: Vec::new(), - output: ast::FunctionRetTy::Default(rustc_span::DUMMY_SP), - }; + let decl = + ast::FnDecl { inputs: Vec::new(), output: ast::FnRetTy::Default(rustc_span::DUMMY_SP) }; let generics = ast::Generics::default(); assert_eq!( fun_to_string(&decl, ast::FnHeader::default(), abba_ident, &generics), diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 5cf233e222e..c2bd2ac90e3 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -957,7 +957,7 @@ impl<'a> MethodDef<'a> { let ret_type = self.get_ret_ty(cx, trait_, generics, type_ident); let method_ident = cx.ident_of(self.name, trait_.span); - let fn_decl = cx.fn_decl(args, ast::FunctionRetTy::Ty(ret_type)); + let fn_decl = cx.fn_decl(args, ast::FnRetTy::Ty(ret_type)); let body_block = cx.block_expr(body); let unsafety = if self.is_unsafe { ast::Unsafe::Yes(trait_.span) } else { ast::Unsafe::No }; diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs index 52f033e8b14..3ffb1d2206a 100644 --- a/src/librustc_builtin_macros/global_allocator.rs +++ b/src/librustc_builtin_macros/global_allocator.rs @@ -63,7 +63,7 @@ impl AllocFnFactory<'_, '_> { let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, mk)).collect(); let result = self.call_allocator(method.name, args); let (output_ty, output_expr) = self.ret_ty(&method.output, result); - let decl = self.cx.fn_decl(abi_args, ast::FunctionRetTy::Ty(output_ty)); + let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty)); let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() }; let sig = FnSig { decl, header }; let kind = ItemKind::Fn(sig, Generics::default(), Some(self.cx.block_expr(output_expr))); diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 02a0bc00c11..2e38a7880c6 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -391,8 +391,8 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { // If the termination trait is active, the compiler will check that the output // type implements the `Termination` trait as `libtest` enforces that. let has_output = match sig.decl.output { - ast::FunctionRetTy::Default(..) => false, - ast::FunctionRetTy::Ty(ref t) if t.kind.is_unit() => false, + ast::FnRetTy::Default(..) => false, + ast::FnRetTy::Ty(ref t) if t.kind.is_unit() => false, _ => true, }; diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 70f1c0e4e2d..f0ea256cf2b 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -305,7 +305,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { ecx.block(sp, vec![call_test_main]) }; - let decl = ecx.fn_decl(vec![], ast::FunctionRetTy::Ty(main_ret_ty)); + let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty)); let sig = ast::FnSig { decl, header: ast::FnHeader::default() }; let main = ast::ItemKind::Fn(sig, ast::Generics::default(), Some(main_body)); diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index af22e46eb6a..9030001542d 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -519,7 +519,7 @@ impl<'a> ExtCtxt<'a> { pub fn lambda(&self, span: Span, ids: Vec, body: P) -> P { let fn_decl = self.fn_decl( ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(), - ast::FunctionRetTy::Default(span), + ast::FnRetTy::Default(span), ); // FIXME -- We are using `span` as the span of the `|...|` @@ -569,7 +569,7 @@ impl<'a> ExtCtxt<'a> { } // FIXME: unused `self` - pub fn fn_decl(&self, inputs: Vec, output: ast::FunctionRetTy) -> P { + pub fn fn_decl(&self, inputs: Vec, output: ast::FnRetTy) -> P { P(ast::FnDecl { inputs, output }) } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index f13e2f18604..56a8e2cfd02 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -5,7 +5,7 @@ use crate::itemlikevisit; use crate::print; crate use BlockCheckMode::*; -crate use FunctionRetTy::*; +crate use FnRetTy::*; crate use UnsafeSource::*; use rustc_data_structures::fx::FxHashSet; @@ -2082,7 +2082,7 @@ pub struct FnDecl<'hir> { /// /// Additional argument data is stored in the function's [body](Body::parameters). pub inputs: &'hir [Ty<'hir>], - pub output: FunctionRetTy<'hir>, + pub output: FnRetTy<'hir>, pub c_variadic: bool, /// Does the function have an implicit self? pub implicit_self: ImplicitSelfKind, @@ -2148,7 +2148,7 @@ impl Defaultness { } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] -pub enum FunctionRetTy<'hir> { +pub enum FnRetTy<'hir> { /// Return type is not specified. /// /// Functions default to `()` and @@ -2159,7 +2159,7 @@ pub enum FunctionRetTy<'hir> { Return(&'hir Ty<'hir>), } -impl fmt::Display for FunctionRetTy<'_> { +impl fmt::Display for FnRetTy<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Return(ref ty) => print::to_string(print::NO_ANN, |s| s.print_type(ty)).fmt(f), @@ -2168,7 +2168,7 @@ impl fmt::Display for FunctionRetTy<'_> { } } -impl FunctionRetTy<'_> { +impl FnRetTy<'_> { pub fn span(&self) -> Span { match *self { Self::DefaultReturn(span) => span, diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 539a0eee0e3..f574449c6b9 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -865,8 +865,8 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( } } -pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FunctionRetTy<'v>) { - if let FunctionRetTy::Return(ref output_ty) = *ret_ty { +pub fn walk_fn_ret_ty<'v, V: Visitor<'v>>(visitor: &mut V, ret_ty: &'v FnRetTy<'v>) { + if let FnRetTy::Return(ref output_ty) = *ret_ty { visitor.visit_ty(output_ty) } } diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index c8a465654b6..a1e6a0a325a 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -7,7 +7,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FunctionRetTy, HirId, Local, Pat}; +use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat}; use rustc_span::source_map::DesugaringKind; use rustc_span::symbol::kw; use rustc_span::Span; @@ -108,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { fn closure_return_type_suggestion( span: Span, err: &mut DiagnosticBuilder<'_>, - output: &FunctionRetTy<'_>, + output: &FnRetTy<'_>, body: &Body<'_>, descr: &str, name: &str, @@ -117,7 +117,7 @@ fn closure_return_type_suggestion( parent_descr: Option<&str>, ) { let (arrow, post) = match output { - FunctionRetTy::DefaultReturn(_) => ("-> ", " "), + FnRetTy::DefaultReturn(_) => ("-> ", " "), _ => ("", ""), }; let suggestion = match body.value.kind { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs index b3197556053..02ce357967c 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs @@ -3,7 +3,7 @@ use crate::infer::error_reporting::nice_region_error::NiceRegionError; use rustc::ty; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; -use rustc_hir::{FunctionRetTy, TyKind}; +use rustc_hir::{FnRetTy, TyKind}; impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { /// When given a `ConcreteFailure` for a function with parameters containing a named region and @@ -79,7 +79,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { return None; } - if let FunctionRetTy::Return(ty) = &fndecl.output { + if let FnRetTy::Return(ty) = &fndecl.output { if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) { // This is an impl Trait return that evaluates de need of 'static. // We handle this case better in `static_impl_trait`. diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index 4a78bcf4a87..50ae7c4fbbf 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -594,7 +594,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { _ => return false, }; - let ret_ty = if let hir::FunctionRetTy::Return(ret_ty) = sig.decl.output { + let ret_ty = if let hir::FnRetTy::Return(ret_ty) = sig.decl.output { ret_ty } else { return false; diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 659323d1c25..72abfa15a1f 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -620,8 +620,8 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { ret } - fn should_ignore_fn(ret_ty: &ast::FunctionRetTy) -> bool { - if let ast::FunctionRetTy::Ty(ref ty) = ret_ty { + fn should_ignore_fn(ret_ty: &ast::FnRetTy) -> bool { + if let ast::FnRetTy::Ty(ref ty) = ret_ty { fn involves_impl_trait(ty: &ast::Ty) -> bool { match ty.kind { ast::TyKind::ImplTrait(..) => true, diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 5ffa9c1747f..703a6959ab2 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -953,7 +953,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { self.check_type_for_ffi_and_report_errors(input_hir.span, input_ty, false); } - if let hir::FunctionRetTy::Return(ref ret_hir) = decl.output { + if let hir::FnRetTy::Return(ref ret_hir) = decl.output { let ret_ty = sig.output(); if !ret_ty.is_unit() { self.check_type_for_ffi_and_report_errors(ret_hir.span, ret_ty, false); diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index d1a03c41580..0ed7dd03f3a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1885,7 +1885,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // as the HIR doesn't have full types for closure arguments. let return_ty = *sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); - if let hir::FunctionRetTy::Return(ty) = &fn_decl.output { + if let hir::FnRetTy::Return(ty) = &fn_decl.output { if let hir::TyKind::Rptr(lifetime, _) = ty.kind { return_span = lifetime.span; } diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 09d61d9ad9a..01ace742876 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -645,8 +645,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .. }) => ( match return_ty.output { - hir::FunctionRetTy::DefaultReturn(_) => tcx.sess.source_map().end_point(*span), - hir::FunctionRetTy::Return(_) => return_ty.output.span(), + hir::FnRetTy::DefaultReturn(_) => tcx.sess.source_map().end_point(*span), + hir::FnRetTy::Return(_) => return_ty.output.span(), }, if gen_move.is_some() { " of generator" } else { " of closure" }, ), diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 20b9df0a2d9..51822ab2ea5 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -10,9 +10,7 @@ use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use std::mem; use syntax::ast::{self, AttrStyle, AttrVec, CaptureBy, Field, Ident, Lit, DUMMY_NODE_ID}; -use syntax::ast::{ - AnonConst, BinOp, BinOpKind, FnDecl, FunctionRetTy, Mac, Param, Ty, TyKind, UnOp, -}; +use syntax::ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, Mac, Param, Ty, TyKind, UnOp}; use syntax::ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use syntax::ptr::P; use syntax::token::{self, Token, TokenKind}; @@ -1358,7 +1356,7 @@ impl<'a> Parser<'a> { let decl = self.parse_fn_block_decl()?; let decl_hi = self.prev_span; let body = match decl.output { - FunctionRetTy::Default(_) => { + FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR; self.parse_expr_res(restrictions, None)? } diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index f56ae65a03d..29615ac1470 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -5,9 +5,7 @@ use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole}; use rustc_errors::{pluralize, struct_span_err, Applicability, PResult}; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym}; -use syntax::ast::{ - self, BareFnTy, FunctionRetTy, GenericParam, Ident, Lifetime, MutTy, Ty, TyKind, -}; +use syntax::ast::{self, BareFnTy, FnRetTy, GenericParam, Ident, Lifetime, MutTy, Ty, TyKind}; use syntax::ast::{ GenericBound, GenericBounds, PolyTraitRef, TraitBoundModifier, TraitObjectSyntax, }; @@ -91,13 +89,13 @@ impl<'a> Parser<'a> { &mut self, allow_plus: AllowPlus, recover_qpath: RecoverQPath, - ) -> PResult<'a, FunctionRetTy> { + ) -> PResult<'a, FnRetTy> { Ok(if self.eat(&token::RArrow) { // FIXME(Centril): Can we unconditionally `allow_plus`? let ty = self.parse_ty_common(allow_plus, recover_qpath, AllowCVariadic::No)?; - FunctionRetTy::Ty(ty) + FnRetTy::Ty(ty) } else { - FunctionRetTy::Default(self.token.span.shrink_to_lo()) + FnRetTy::Default(self.token.span.shrink_to_lo()) }) } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index bcf558d1563..997b1a4da8c 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2035,7 +2035,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Resolve arguments: this.resolve_params(&fn_decl.inputs); // No need to resolve return type -- - // the outer closure return type is `FunctionRetTy::Default`. + // the outer closure return type is `FnRetTy::Default`. // Now resolve the inner closure { diff --git a/src/librustc_resolve/lifetimes.rs b/src/librustc_resolve/lifetimes.rs index 5bc5222f9fc..b9c5f4992f6 100644 --- a/src/librustc_resolve/lifetimes.rs +++ b/src/librustc_resolve/lifetimes.rs @@ -881,8 +881,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { fn visit_fn_decl(&mut self, fd: &'tcx hir::FnDecl<'tcx>) { let output = match fd.output { - hir::FunctionRetTy::DefaultReturn(_) => None, - hir::FunctionRetTy::Return(ref ty) => Some(&**ty), + hir::FnRetTy::DefaultReturn(_) => None, + hir::FnRetTy::Return(ref ty) => Some(&**ty), }; self.visit_fn_like_elision(&fd.inputs, output); } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 01e3e3f3685..a445b0ea1b8 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -285,7 +285,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { v.visit_ty(&arg.ty); } - if let ast::FunctionRetTy::Ty(ref ret_ty) = sig.decl.output { + if let ast::FnRetTy::Ty(ref ret_ty) = sig.decl.output { // In async functions, return types are desugared and redefined // as an `impl Trait` existential type. Because of this, to match // the definition paths when resolving nested types we need to @@ -374,7 +374,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { v.visit_ty(&arg.ty) } - if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { + if let ast::FnRetTy::Ty(ref ret_ty) = decl.output { if let ast::TyKind::ImplTrait(..) = ret_ty.kind { // FIXME: Opaque type desugaring prevents us from easily // processing trait bounds. See `visit_ty` for more details. @@ -792,7 +792,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { for t in &data.inputs { self.visit_ty(t); } - if let ast::FunctionRetTy::Ty(ty) = &data.output { + if let ast::FnRetTy::Ty(ty) = &data.output { self.visit_ty(ty); } } @@ -1449,7 +1449,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&arg.ty); } - if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { + if let ast::FnRetTy::Ty(ref ret_ty) = decl.output { self.visit_ty(&ret_ty); } @@ -1528,7 +1528,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&arg.ty); } - if let ast::FunctionRetTy::Ty(ref ret_ty) = decl.output { + if let ast::FnRetTy::Ty(ref ret_ty) = decl.output { self.visit_ty(&ret_ty); } } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 401e1722751..eea7376590e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -880,8 +880,8 @@ fn make_signature(decl: &ast::FnDecl, generics: &ast::Generics) -> String { sig.push_str(&decl.inputs.iter().map(param_to_string).collect::>().join(", ")); sig.push(')'); match decl.output { - ast::FunctionRetTy::Default(_) => sig.push_str(" -> ()"), - ast::FunctionRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))), + ast::FnRetTy::Default(_) => sig.push_str(" -> ()"), + ast::FnRetTy::Ty(ref t) => sig.push_str(&format!(" -> {}", ty_to_string(t))), } sig diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index d3c4d6d5723..4f5c388f2a9 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -241,7 +241,7 @@ impl Sig for ast::Ty { refs.extend(nested.refs.into_iter()); } text.push(')'); - if let ast::FunctionRetTy::Ty(ref t) = f.decl.output { + if let ast::FnRetTy::Ty(ref t) = f.decl.output { text.push_str(" -> "); let nested = t.make(offset + text.len(), None, scx)?; text.push_str(&nested.text); @@ -392,7 +392,7 @@ impl Sig for ast::Item { } sig.text.push(')'); - if let ast::FunctionRetTy::Ty(ref t) = decl.output { + if let ast::FnRetTy::Ty(ref t) = decl.output { sig.text.push_str(" -> "); let nested = t.make(offset + sig.text.len(), None, scx)?; sig.text.push_str(&nested.text); @@ -743,7 +743,7 @@ impl Sig for ast::ForeignItem { } sig.text.push(')'); - if let ast::FunctionRetTy::Ty(ref t) = decl.output { + if let ast::FnRetTy::Ty(ref t) = decl.output { sig.text.push_str(" -> "); let nested = t.make(offset + sig.text.len(), None, scx)?; sig.text.push_str(&nested.text); @@ -911,7 +911,7 @@ fn make_method_signature( } sig.text.push(')'); - if let ast::FunctionRetTy::Ty(ref t) = m.decl.output { + if let ast::FnRetTy::Ty(ref t) = m.decl.output { sig.text.push_str(" -> "); let nested = t.make(sig.text.len(), None, scx)?; sig.text.push_str(&nested.text); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c0574d6d9fd..69970faab3f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2827,11 +2827,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let input_tys = decl.inputs.iter().map(|a| self.ty_of_arg(a, None)); let output_ty = match decl.output { - hir::FunctionRetTy::Return(ref output) => { + hir::FnRetTy::Return(ref output) => { visitor.visit_ty(output); self.ast_ty_to_ty(output) } - hir::FunctionRetTy::DefaultReturn(..) => tcx.mk_unit(), + hir::FnRetTy::DefaultReturn(..) => tcx.mk_unit(), }; debug!("ty_of_fn: output_ty={:?}", output_ty); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index ae6bed476f3..e17c65faf1f 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -555,8 +555,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // First, convert the types that the user supplied (if any). let supplied_arguments = decl.inputs.iter().map(|a| astconv.ast_ty_to_ty(a)); let supplied_return = match decl.output { - hir::FunctionRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output), - hir::FunctionRetTy::DefaultReturn(_) => match body.generator_kind { + hir::FnRetTy::Return(ref output) => astconv.ast_ty_to_ty(&output), + hir::FnRetTy::DefaultReturn(_) => match body.generator_kind { // In the case of the async block that we create for a function body, // we expect the return type of the block to match that of the enclosing // function. @@ -703,7 +703,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.types.err }); - if let hir::FunctionRetTy::Return(ref output) = decl.output { + if let hir::FnRetTy::Return(ref output) = decl.output { astconv.ast_ty_to_ty(&output); } diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index ce44fdab323..c327a7996b6 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -1363,7 +1363,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fcx: &FnCtxt<'a, 'tcx>, expected: Ty<'tcx>, sp: Span, - fn_output: &hir::FunctionRetTy<'_>, + fn_output: &hir::FnRetTy<'_>, ) { let return_sp = fn_output.span(); err.span_label(return_sp, "expected because this return type..."); @@ -1389,7 +1389,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let has_impl = snippet_iter.next().map_or(false, |s| s == "impl"); // Only suggest `Box` if `Trait` in `impl Trait` is object safe. let mut is_object_safe = false; - if let hir::FunctionRetTy::Return(ty) = fn_output { + if let hir::FnRetTy::Return(ty) = fn_output { // Get the return type. if let hir::TyKind::Def(..) = ty.kind { let ty = AstConv::ast_ty_to_ty(fcx, ty); @@ -1430,7 +1430,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { fn is_return_ty_unsized(&self, fcx: &FnCtxt<'a, 'tcx>, blk_id: hir::HirId) -> bool { if let Some((fn_decl, _)) = fcx.get_fn_decl(blk_id) { - if let hir::FunctionRetTy::Return(ty) = fn_decl.output { + if let hir::FnRetTy::Return(ty) = fn_decl.output { let ty = AstConv::ast_ty_to_ty(fcx, ty); if let ty::Dynamic(..) = ty.kind { return true; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 748a44a7297..9656cbb6bd6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5153,7 +5153,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Only suggest changing the return type for methods that // haven't set a return type at all (and aren't `fn main()` or an impl). match (&fn_decl.output, found.is_suggestable(), can_suggest, expected.is_unit()) { - (&hir::FunctionRetTy::DefaultReturn(span), true, true, true) => { + (&hir::FnRetTy::DefaultReturn(span), true, true, true) => { err.span_suggestion( span, "try adding a return type", @@ -5162,18 +5162,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); true } - (&hir::FunctionRetTy::DefaultReturn(span), false, true, true) => { + (&hir::FnRetTy::DefaultReturn(span), false, true, true) => { err.span_label(span, "possibly return type missing here?"); true } - (&hir::FunctionRetTy::DefaultReturn(span), _, false, true) => { + (&hir::FnRetTy::DefaultReturn(span), _, false, true) => { // `fn main()` must return `()`, do not suggest changing return type err.span_label(span, "expected `()` because of default return type"); true } // expectation was caused by something else, not the default return - (&hir::FunctionRetTy::DefaultReturn(_), _, _, false) => false, - (&hir::FunctionRetTy::Return(ref ty), _, _, _) => { + (&hir::FnRetTy::DefaultReturn(_), _, _, false) => false, + (&hir::FnRetTy::Return(ref ty), _, _, _) => { // Only point to return type if the expected type is the return type, as if they // are not, the expectation must have been caused by something else. debug!("suggest_missing_return_type: return type {:?} node {:?}", ty, ty.kind); diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index ef5188c94ff..4ffc3bf8e78 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -214,7 +214,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem } } match sig.decl.output { - hir::FunctionRetTy::Return(ty) if could_be_self(trait_def_id, ty) => { + hir::FnRetTy::Return(ty) if could_be_self(trait_def_id, ty) => { trait_should_be_self.push(ty.span); } _ => {} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 80d914d8d0a..e8913b6927a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1360,8 +1360,8 @@ fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { } } -pub fn get_infer_ret_ty(output: &'hir hir::FunctionRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { - if let hir::FunctionRetTy::Return(ref ty) = output { +pub fn get_infer_ret_ty(output: &'hir hir::FnRetTy<'hir>) -> Option<&'hir hir::Ty<'hir>> { + if let hir::FnRetTy::Return(ref ty) = output { if is_suggestable_infer_ty(ty) { return Some(&**ty); } @@ -2079,7 +2079,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( for (input, ty) in decl.inputs.iter().zip(*fty.inputs().skip_binder()) { check(&input, ty) } - if let hir::FunctionRetTy::Return(ref ty) = decl.output { + if let hir::FnRetTy::Return(ref ty) = decl.output { check(&ty, *fty.output().skip_binder()) } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index ee432647084..820937b21c8 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -43,7 +43,7 @@ use utils::*; pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res}; -pub use self::types::FunctionRetTy::*; +pub use self::types::FnRetTy::*; pub use self::types::ItemEnum::*; pub use self::types::SelfTy::*; pub use self::types::Type::*; @@ -1001,8 +1001,8 @@ impl<'tcx> Clean for (DefId, ty::PolyFnSig<'tcx>) { } } -impl Clean for hir::FunctionRetTy<'_> { - fn clean(&self, cx: &DocContext<'_>) -> FunctionRetTy { +impl Clean for hir::FnRetTy<'_> { + fn clean(&self, cx: &DocContext<'_>) -> FnRetTy { match *self { Self::Return(ref typ) => Return(typ.clean(cx)), Self::DefaultReturn(..) => DefaultReturn, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 8501fee56cf..2f220cbc9be 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -35,7 +35,7 @@ use crate::doctree; use crate::html::item_type::ItemType; use crate::html::render::{cache, ExternalLocation}; -use self::FunctionRetTy::*; +use self::FnRetTy::*; use self::ItemEnum::*; use self::SelfTy::*; use self::Type::*; @@ -862,7 +862,7 @@ pub struct Function { #[derive(Clone, PartialEq, Eq, Debug, Hash)] pub struct FnDecl { pub inputs: Arguments, - pub output: FunctionRetTy, + pub output: FnRetTy, pub c_variadic: bool, pub attrs: Attributes, } @@ -881,12 +881,12 @@ impl FnDecl { /// /// This function will panic if the return type does not match the expected sugaring for async /// functions. - pub fn sugared_async_return_type(&self) -> FunctionRetTy { + pub fn sugared_async_return_type(&self) -> FnRetTy { match &self.output { - FunctionRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] { + FnRetTy::Return(Type::ImplTrait(bounds)) => match &bounds[0] { GenericBound::TraitBound(PolyTrait { trait_, .. }, ..) => { let bindings = trait_.bindings().unwrap(); - FunctionRetTy::Return(bindings[0].ty().clone()) + FnRetTy::Return(bindings[0].ty().clone()) } _ => panic!("unexpected desugaring of async function"), }, @@ -931,12 +931,12 @@ impl Argument { } #[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum FunctionRetTy { +pub enum FnRetTy { Return(Type), DefaultReturn, } -impl GetDefId for FunctionRetTy { +impl GetDefId for FnRetTy { fn def_id(&self) -> Option { match *self { Return(ref ty) => ty.def_id(), diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index ef357056504..b76db6804f8 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -1,7 +1,7 @@ use crate::clean::auto_trait::AutoTraitFinder; use crate::clean::blanket_impl::BlanketImplFinder; use crate::clean::{ - inline, Clean, Crate, Deprecation, ExternalCrate, FnDecl, FunctionRetTy, Generic, GenericArg, + inline, Clean, Crate, Deprecation, ExternalCrate, FnDecl, FnRetTy, Generic, GenericArg, GenericArgs, GenericBound, Generics, GetDefId, ImportSource, Item, ItemEnum, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Span, Stability, Type, TypeBinding, TypeKind, Visibility, WherePredicate, @@ -273,7 +273,7 @@ pub fn get_all_types( } let ret_types = match decl.output { - FunctionRetTy::Return(ref return_type) => { + FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { ret.insert(return_type.clone()); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index c3313ba63ef..ec615fc8589 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -933,7 +933,7 @@ impl clean::Arguments { } } -impl clean::FunctionRetTy { +impl clean::FnRetTy { crate fn print(&self) -> impl fmt::Display + '_ { display_fn(move |f| match self { clean::Return(clean::Tuple(tys)) if tys.is_empty() => Ok(()), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d101473d76b..a9c6fcddc77 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -243,7 +243,7 @@ pub struct ParenthesizedArgs { pub inputs: Vec>, /// `C` - pub output: FunctionRetTy, + pub output: FnRetTy, } impl ParenthesizedArgs { @@ -2083,7 +2083,7 @@ impl Param { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct FnDecl { pub inputs: Vec, - pub output: FunctionRetTy, + pub output: FnRetTy, } impl FnDecl { @@ -2168,8 +2168,7 @@ impl fmt::Debug for ImplPolarity { } #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub enum FunctionRetTy { - // FIXME(Centril): Rename to `FnRetTy` and in HIR also. +pub enum FnRetTy { /// Returns type is not specified. /// /// Functions default to `()` and closures default to inference. @@ -2179,11 +2178,11 @@ pub enum FunctionRetTy { Ty(P), } -impl FunctionRetTy { +impl FnRetTy { pub fn span(&self) -> Span { match *self { - FunctionRetTy::Default(span) => span, - FunctionRetTy::Ty(ref ty) => ty.span, + FnRetTy::Default(span) => span, + FnRetTy::Ty(ref ty) => ty.span, } } } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index f130b0a2ee4..2afe4159e93 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -744,10 +744,10 @@ pub fn noop_visit_fn_decl(decl: &mut P, vis: &mut T) { noop_visit_fn_ret_ty(output, vis); } -pub fn noop_visit_fn_ret_ty(fn_ret_ty: &mut FunctionRetTy, vis: &mut T) { +pub fn noop_visit_fn_ret_ty(fn_ret_ty: &mut FnRetTy, vis: &mut T) { match fn_ret_ty { - FunctionRetTy::Default(span) => vis.visit_span(span), - FunctionRetTy::Ty(ty) => vis.visit_ty(ty), + FnRetTy::Default(span) => vis.visit_span(span), + FnRetTy::Ty(ty) => vis.visit_ty(ty), } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 73e731397c3..26f3773bea8 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -215,7 +215,7 @@ pub trait Visitor<'ast>: Sized { fn visit_vis(&mut self, vis: &'ast Visibility) { walk_vis(self, vis) } - fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FunctionRetTy) { + fn visit_fn_ret_ty(&mut self, ret_ty: &'ast FnRetTy) { walk_fn_ret_ty(self, ret_ty) } fn visit_fn_header(&mut self, _header: &'ast FnHeader) { @@ -594,8 +594,8 @@ pub fn walk_where_predicate<'a, V: Visitor<'a>>(visitor: &mut V, predicate: &'a } } -pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FunctionRetTy) { - if let FunctionRetTy::Ty(ref output_ty) = *ret_ty { +pub fn walk_fn_ret_ty<'a, V: Visitor<'a>>(visitor: &mut V, ret_ty: &'a FnRetTy) { + if let FnRetTy::Ty(ref output_ty) = *ret_ty { visitor.visit_ty(output_ty) } } diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 7ac75c605f2..38576ef39d1 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -117,7 +117,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P)) { 11 => { let decl = P(FnDecl { inputs: vec![], - output: FunctionRetTy::Default(DUMMY_SP), + output: FnRetTy::Default(DUMMY_SP), }); iter_exprs(depth - 1, &mut |e| g( ExprKind::Closure(CaptureBy::Value, From 8bafe883b6bb273b7a256d7720e638b267c2e574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Feb 2020 22:45:48 -0800 Subject: [PATCH 0270/1250] Select an appropriate unused lifetime name in suggestion --- src/librustc_typeck/collect.rs | 50 ++++++++++++++++--- ...iated-types-project-from-hrtb-in-struct.rs | 11 +++- ...d-types-project-from-hrtb-in-struct.stderr | 23 +++++++-- 3 files changed, 71 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 80d914d8d0a..ca3bcac1206 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -33,7 +33,7 @@ use rustc::ty::{self, AdtKind, Const, ToPolyTraitRef, Ty, TyCtxt}; use rustc::ty::{ReprOptions, ToPredicate, WithConstness}; use rustc_attr::{list_contains_name, mark_used, InlineAttr, OptimizeAttr}; use rustc_data_structures::captures::Captures; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; @@ -369,10 +369,12 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { hir::ItemKind::Enum(_, generics) | hir::ItemKind::Struct(_, generics) | hir::ItemKind::Union(_, generics) => { - // FIXME: look for an appropriate lt name if `'a` is already used + let lt_name = get_new_lifetime_name(self.tcx, poly_trait_ref, generics); let (lt_sp, sugg) = match &generics.params[..] { - [] => (generics.span, "<'a>".to_string()), - [bound, ..] => (bound.span.shrink_to_lo(), "'a, ".to_string()), + [] => (generics.span, format!("<{}>", lt_name)), + [bound, ..] => { + (bound.span.shrink_to_lo(), format!("{}, ", lt_name)) + } }; let suggestions = vec![ (lt_sp, sugg), @@ -387,7 +389,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { ty::EarlyBoundRegion { def_id: item_def_id, index: 0, - name: Symbol::intern("'a"), + name: Symbol::intern(<_name), }, )) }) @@ -445,6 +447,43 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } } +/// Synthesize a new lifetime name that doesn't clash with any of the lifetimes already present. +fn get_new_lifetime_name<'tcx>( + tcx: TyCtxt<'tcx>, + poly_trait_ref: ty::PolyTraitRef<'tcx>, + generics: &hir::Generics<'tcx>, +) -> String { + let existing_lifetimes = tcx + .collect_referenced_late_bound_regions(&poly_trait_ref) + .into_iter() + .filter_map(|lt| { + if let ty::BoundRegion::BrNamed(_, name) = lt { + Some(name.as_str().to_string()) + } else { + None + } + }) + .chain(generics.params.iter().filter_map(|param| { + if let hir::GenericParamKind::Lifetime { .. } = ¶m.kind { + Some(param.name.ident().as_str().to_string()) + } else { + None + } + })) + .collect::>(); + + let a_to_z_repeat_n = |n| { + (b'a'..=b'z').map(move |c| { + let mut s = format!("'"); + s.extend(std::iter::repeat(char::from(c)).take(n)); + s + }) + }; + + // If all single char lifetime names are present, we wrap around and double the chars. + (1..).flat_map(a_to_z_repeat_n).find(|lt| !existing_lifetimes.contains(lt.as_str())).unwrap() +} + /// Returns the predicates defined on `item_def_id` of the form /// `X: Foo` where `X` is the type parameter `def_id`. fn type_param_predicates( @@ -1588,7 +1627,6 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { /// Returns a list of user-specified type predicates for the definition with ID `def_id`. /// N.B., this does not include any implied/inferred constraints. fn explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> { - use rustc_data_structures::fx::FxHashSet; use rustc_hir::*; debug!("explicit_predicates_of(def_id={:?})", def_id); diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs index 8a5777d4d7c..58f186d7775 100644 --- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs +++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.rs @@ -12,11 +12,12 @@ struct SomeStruct Foo<&'x isize>> { //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context } -enum SomeEnum Foo<&'x isize>> { +enum SomeEnum<'b, I: for<'a> Foo<&'a isize>> { TupleVariant(I::A), //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context StructVariant { field: I::A }, //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context + OkVariant(&'b usize), } // FIXME(eddyb) This one doesn't even compile because of the unsupported syntax. @@ -26,7 +27,13 @@ enum SomeEnum Foo<&'x isize>> { // } struct YetAnotherStruct<'a, I: for<'x> Foo<&'x isize>> { - field: >::A + field: >::A, +} + +struct Why<'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, + 'y, 'z, 'aa, I: for<'l, 'm> Foo<&'l &'m isize>> { + field: I::A, + //~^ ERROR cannot extract an associated type from a higher-ranked trait bound in this context } pub fn main() {} diff --git a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr index c71bc70ea6c..e3fd2860ebc 100644 --- a/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr +++ b/src/test/ui/associated-types/associated-types-project-from-hrtb-in-struct.stderr @@ -18,8 +18,8 @@ LL | TupleVariant(I::A), | help: use a fully qualified path with explicit lifetimes | -LL | enum SomeEnum<'a, I: for<'x> Foo<&'x isize>> { -LL | TupleVariant(>::A), +LL | enum SomeEnum<'c, 'b, I: for<'a> Foo<&'a isize>> { +LL | TupleVariant(>::A), | error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context @@ -30,11 +30,24 @@ LL | StructVariant { field: I::A }, | help: use a fully qualified path with explicit lifetimes | -LL | enum SomeEnum<'a, I: for<'x> Foo<&'x isize>> { +LL | enum SomeEnum<'c, 'b, I: for<'a> Foo<&'a isize>> { LL | TupleVariant(I::A), LL | -LL | StructVariant { field: >::A }, +LL | StructVariant { field: >::A }, | -error: aborting due to 3 previous errors +error[E0212]: cannot extract an associated type from a higher-ranked trait bound in this context + --> $DIR/associated-types-project-from-hrtb-in-struct.rs:35:12 + | +LL | field: I::A, + | ^^^^ + | +help: use a fully qualified path with explicit lifetimes + | +LL | struct Why<'bb, 'a, 'b, 'c, 'd, 'e, 'f, 'g, 'h, 'i, 'j, 'k, 'n, 'o, 'p, 'q, 'r, 's, 't, 'u, 'v, 'w, 'x, +LL | 'y, 'z, 'aa, I: for<'l, 'm> Foo<&'l &'m isize>> { +LL | field: >::A, + | + +error: aborting due to 4 previous errors From e5b2c66dea8e2d721612089ebfa00e0799cd5e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 14 Feb 2020 17:49:16 -0800 Subject: [PATCH 0271/1250] Do not ICE when encountering `yield` inside `async` block --- src/librustc/hir/map/hir_id_validator.rs | 4 ++-- src/librustc/hir/map/mod.rs | 2 +- src/test/ui/generator/async-generator-issue-67158.rs | 6 ++++++ src/test/ui/generator/async-generator-issue-67158.stderr | 9 +++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/generator/async-generator-issue-67158.rs create mode 100644 src/test/ui/generator/async-generator-issue-67158.stderr diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index c721faafbec..a4f9193c0eb 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -7,7 +7,7 @@ use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId}; -pub fn check_crate(hir_map: &Map<'_>) { +pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) { hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); @@ -24,7 +24,7 @@ pub fn check_crate(hir_map: &Map<'_>) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - bug!("{}", message); + sess.delay_span_bug(rustc_span::DUMMY_SP, &message); } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1645420892a..adda0cde24f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -1235,7 +1235,7 @@ pub fn map_crate<'hir>( let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions }; sess.time("validate_HIR_map", || { - hir_id_validator::check_crate(&map); + hir_id_validator::check_crate(&map, sess); }); map diff --git a/src/test/ui/generator/async-generator-issue-67158.rs b/src/test/ui/generator/async-generator-issue-67158.rs new file mode 100644 index 00000000000..8125a7a9bb6 --- /dev/null +++ b/src/test/ui/generator/async-generator-issue-67158.rs @@ -0,0 +1,6 @@ +#![feature(generators)] +// edition:2018 +// Regression test for #67158. +fn main() { + async { yield print!(":C") }; //~ ERROR `async` generators are not yet supported +} diff --git a/src/test/ui/generator/async-generator-issue-67158.stderr b/src/test/ui/generator/async-generator-issue-67158.stderr new file mode 100644 index 00000000000..7270d188e8b --- /dev/null +++ b/src/test/ui/generator/async-generator-issue-67158.stderr @@ -0,0 +1,9 @@ +error[E0727]: `async` generators are not yet supported + --> $DIR/async-generator-issue-67158.rs:5:13 + | +LL | async { yield print!(":C") }; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0727`. From 045b7d53a3fe94d2f6cb32d029a3f5d74e174ed9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 17 Feb 2020 11:16:28 +0100 Subject: [PATCH 0272/1250] ast: add a FIXME --- src/libsyntax/ast.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 8154ae2f307..a7314240615 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2600,6 +2600,8 @@ impl ItemKind { } } +// FIXME(Centril): These definitions should be unmerged; +// see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975 pub type ForeignItem = Item; pub type ForeignItemKind = AssocItemKind; From 79c166ef73df00eac96aaeadcb326c972c22068c Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 5 Feb 2020 15:47:01 +0100 Subject: [PATCH 0273/1250] ci: switch macOS builders to 10.15 --- src/bootstrap/test.rs | 4 ++-- src/ci/azure-pipelines/auto.yml | 2 +- src/ci/azure-pipelines/steps/run.yml | 4 ---- src/ci/azure-pipelines/try.yml | 2 +- src/ci/scripts/install-clang.sh | 4 +--- src/ci/scripts/switch-xcode.sh | 13 ------------- 6 files changed, 5 insertions(+), 24 deletions(-) delete mode 100755 src/ci/scripts/switch-xcode.sh diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 43561fa4f2f..3d6d4065fe8 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1051,10 +1051,10 @@ impl Step for Compiletest { cmd.arg("--docck-python").arg(builder.python()); if builder.config.build.ends_with("apple-darwin") { - // Force /usr/bin/python on macOS for LLDB tests because we're loading the + // Force /usr/bin/python3 on macOS for LLDB tests because we're loading the // LLDB plugin's compiled module which only works with the system python // (namely not Homebrew-installed python) - cmd.arg("--lldb-python").arg("/usr/bin/python"); + cmd.arg("--lldb-python").arg("/usr/bin/python3"); } else { cmd.arg("--lldb-python").arg(builder.python()); } diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml index 79a49fc48be..74b7469ea27 100644 --- a/src/ci/azure-pipelines/auto.yml +++ b/src/ci/azure-pipelines/auto.yml @@ -63,7 +63,7 @@ jobs: - job: macOS timeoutInMinutes: 600 pool: - vmImage: macos-10.13 + vmImage: macos-10.15 steps: - template: steps/run.yml strategy: diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index f536388b25b..1532608f0c0 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -48,10 +48,6 @@ steps: displayName: Install clang condition: and(succeeded(), not(variables.SKIP_JOB)) -- bash: src/ci/scripts/switch-xcode.sh - displayName: Switch to Xcode 9.3 - condition: and(succeeded(), not(variables.SKIP_JOB)) - - bash: src/ci/scripts/install-wix.sh displayName: Install wix condition: and(succeeded(), not(variables.SKIP_JOB)) diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index b6177b2cc9b..f8ddf0eb46c 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -25,7 +25,7 @@ jobs: # - job: macOS # timeoutInMinutes: 600 # pool: -# vmImage: macos-10.13 +# vmImage: macos-10.15 # steps: # - template: steps/run.yml # strategy: diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index e16a4814197..c242f5d4562 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -19,9 +19,7 @@ if isMacOS; then # native clang is configured to use the correct path, but our custom one # doesn't. This sets the SDKROOT environment variable to the SDK so that # our own clang can figure out the correct include path on its own. - if ! [[ -d "/usr/include" ]]; then - ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" - fi + ciCommandSetEnv SDKROOT "$(xcrun --sdk macosx --show-sdk-path)" # Configure `AR` specifically so rustbuild doesn't try to infer it as # `clang-ar` by accident. diff --git a/src/ci/scripts/switch-xcode.sh b/src/ci/scripts/switch-xcode.sh deleted file mode 100755 index 2cbb2ddbc70..00000000000 --- a/src/ci/scripts/switch-xcode.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -# Switch to XCode 9.3 on OSX since it seems to be the last version that supports -# i686-apple-darwin. We'll eventually want to upgrade this and it will probably -# force us to drop i686-apple-darwin, but let's keep the wheels turning for now. - -set -euo pipefail -IFS=$'\n\t' - -source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" - -if isMacOS; then - sudo xcode-select --switch /Applications/Xcode_9.3.app -fi From 535fc0f43ab40a1f4982f80a3d922e6e202c6702 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 16 Feb 2020 19:11:13 -0500 Subject: [PATCH 0274/1250] Add documentation for the `-Zself-profile` flag --- .../src/compiler-flags/self-profile.md | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/self-profile.md diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile.md b/src/doc/unstable-book/src/compiler-flags/self-profile.md new file mode 100644 index 00000000000..6de1c774f7c --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/self-profile.md @@ -0,0 +1,47 @@ +# `self-profile` + +-------------------- + +The `-Zself-profile` compiler flag enables rustc's internal profiler. +When enabled, the compiler will output three binary files in the specified directory (or the current working directory if no directory is specified). +These files can be analyzed by using the tools in the [`measureme`] repository. + +To control the data recorded in the trace files, use the `-Zself-profile-events` flag. + +For example: + +First, run a compilation session and provide the `-Zself-profile` flag: + +```console +$ rustc --crate-name foo -Zself-profile` +``` + +This will generate three files in the working directory such as: + +- `foo-1234.events` +- `foo-1234.string_data` +- `foo-1234.string_index` + +Where `foo` is the name of the crate and `1234` is the process id of the rustc process. + +To get a summary of where the compiler is spending its time: + +```console +$ ../measureme/target/release/summarize summarize foo-1234 +``` + +To generate a flamegraph of the same data: + +```console +$ ../measureme/target/release/inferno foo-1234 +``` + +To dump the event data in a Chromium-profiler compatible format: + +```console +$ ../measureme/target/release/crox foo-1234 +``` + +For more information, consult the [`measureme`] documentation. + +[`measureme`]: https://github.com/rust-lang/measureme.git From 3b431234e06962983df6e0ce17cd074c2ab380bd Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 17 Feb 2020 13:28:03 +0900 Subject: [PATCH 0275/1250] Update Clippy --- Cargo.lock | 2 +- src/tools/clippy | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f13a581bc79..beda3993353 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,7 +498,7 @@ dependencies = [ "itertools 0.8.0", "lazy_static 1.4.0", "matches", - "pulldown-cmark 0.6.1", + "pulldown-cmark 0.7.0", "quine-mc_cluskey", "regex-syntax", "semver", diff --git a/src/tools/clippy b/src/tools/clippy index 07f1736390e..b91ae16eb1a 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 07f1736390e1d4dd88cf9fae4ab7737ee5e086b7 +Subproject commit b91ae16eb1ab03b996de5ffc44db054244c1d2f6 From 6c45e4540be20b7027ee6364eefc444b432b82ba Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 15 Feb 2020 18:18:13 -0500 Subject: [PATCH 0276/1250] Drop unused argument to float functions --- src/libcore/fmt/float.rs | 2 - src/libcore/num/flt2dec/mod.rs | 2 - src/libcore/tests/num/flt2dec/mod.rs | 460 +++++++++++++-------------- 3 files changed, 224 insertions(+), 240 deletions(-) diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 284e94926dc..5ef673009bb 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -29,7 +29,6 @@ where *num, sign, precision, - false, buf.get_mut(), parts.get_mut(), ); @@ -59,7 +58,6 @@ where *num, sign, precision, - false, buf.get_mut(), parts.get_mut(), ); diff --git a/src/libcore/num/flt2dec/mod.rs b/src/libcore/num/flt2dec/mod.rs index 93a2348447e..f5cd26a1852 100644 --- a/src/libcore/num/flt2dec/mod.rs +++ b/src/libcore/num/flt2dec/mod.rs @@ -462,7 +462,6 @@ pub fn to_shortest_str<'a, T, F>( v: T, sign: Sign, frac_digits: usize, - _upper: bool, buf: &'a mut [u8], parts: &'a mut [Part<'a>], ) -> Formatted<'a> @@ -679,7 +678,6 @@ pub fn to_exact_fixed_str<'a, T, F>( v: T, sign: Sign, frac_digits: usize, - _upper: bool, buf: &'a mut [u8], parts: &'a mut [Part<'a>], ) -> Formatted<'a> diff --git a/src/libcore/tests/num/flt2dec/mod.rs b/src/libcore/tests/num/flt2dec/mod.rs index f6935048246..e945d9c4a54 100644 --- a/src/libcore/tests/num/flt2dec/mod.rs +++ b/src/libcore/tests/num/flt2dec/mod.rs @@ -500,94 +500,91 @@ where { use core::num::flt2dec::Sign::*; - fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String + fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8]) -> (usize, i16), { to_string_with_parts(|buf, parts| { - to_shortest_str(|d, b| f(d, b), v, sign, frac_digits, upper, buf, parts) + to_shortest_str(|d, b| f(d, b), v, sign, frac_digits, buf, parts) }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); - - assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0, false), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 0, true), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 0, false), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 0, true), "+inf"); - assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1, true), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64, true), "NaN"); - assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1, true), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, 0, false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3.14"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3.14"); - assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3.14"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3.14"); - assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); - assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); - - assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0.000000000075"); - assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000000000075"); - assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075"); - assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750"); - - assert_eq!(to_string(f, 1.9971e20, Minus, 0, false), "199710000000000000000"); - assert_eq!(to_string(f, 1.9971e20, Minus, 1, false), "199710000000000000000.0"); - assert_eq!(to_string(f, 1.9971e20, Minus, 8, false), "199710000000000000000.00000000"); - - assert_eq!(to_string(f, f32::MAX, Minus, 0, false), format!("34028235{:0>31}", "")); - assert_eq!(to_string(f, f32::MAX, Minus, 1, false), format!("34028235{:0>31}.0", "")); - assert_eq!(to_string(f, f32::MAX, Minus, 8, false), format!("34028235{:0>31}.00000000", "")); + assert_eq!(to_string(f, 0.0, Minus, 0), "0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); + assert_eq!(to_string(f, -0.0, Minus, 0), "0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); + assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); + assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); + assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); + + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 0), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 0), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 0), "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, 0), "3.14"); + assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3.14"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3.14"); + assert_eq!(to_string(f, -3.14, Minus, 0), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3.14"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3.14"); + assert_eq!(to_string(f, 3.14, Minus, 1), "3.14"); + assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); + + assert_eq!(to_string(f, 7.5e-11, Minus, 0), "0.000000000075"); + assert_eq!(to_string(f, 7.5e-11, Minus, 3), "0.000000000075"); + assert_eq!(to_string(f, 7.5e-11, Minus, 12), "0.000000000075"); + assert_eq!(to_string(f, 7.5e-11, Minus, 13), "0.0000000000750"); + + assert_eq!(to_string(f, 1.9971e20, Minus, 0), "199710000000000000000"); + assert_eq!(to_string(f, 1.9971e20, Minus, 1), "199710000000000000000.0"); + assert_eq!(to_string(f, 1.9971e20, Minus, 8), "199710000000000000000.00000000"); + + assert_eq!(to_string(f, f32::MAX, Minus, 0), format!("34028235{:0>31}", "")); + assert_eq!(to_string(f, f32::MAX, Minus, 1), format!("34028235{:0>31}.0", "")); + assert_eq!(to_string(f, f32::MAX, Minus, 8), format!("34028235{:0>31}.00000000", "")); let minf32 = ldexp_f32(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, 0, false), format!("0.{:0>44}1", "")); - assert_eq!(to_string(f, minf32, Minus, 45, false), format!("0.{:0>44}1", "")); - assert_eq!(to_string(f, minf32, Minus, 46, false), format!("0.{:0>44}10", "")); + assert_eq!(to_string(f, minf32, Minus, 0), format!("0.{:0>44}1", "")); + assert_eq!(to_string(f, minf32, Minus, 45), format!("0.{:0>44}1", "")); + assert_eq!(to_string(f, minf32, Minus, 46), format!("0.{:0>44}10", "")); - assert_eq!(to_string(f, f64::MAX, Minus, 0, false), format!("17976931348623157{:0>292}", "")); - assert_eq!(to_string(f, f64::MAX, Minus, 1, false), format!("17976931348623157{:0>292}.0", "")); - assert_eq!( - to_string(f, f64::MAX, Minus, 8, false), - format!("17976931348623157{:0>292}.00000000", "") - ); + assert_eq!(to_string(f, f64::MAX, Minus, 0), format!("17976931348623157{:0>292}", "")); + assert_eq!(to_string(f, f64::MAX, Minus, 1), format!("17976931348623157{:0>292}.0", "")); + assert_eq!(to_string(f, f64::MAX, Minus, 8), format!("17976931348623157{:0>292}.00000000", "")); let minf64 = ldexp_f64(1.0, -1074); - assert_eq!(to_string(f, minf64, Minus, 0, false), format!("0.{:0>323}5", "")); - assert_eq!(to_string(f, minf64, Minus, 324, false), format!("0.{:0>323}5", "")); - assert_eq!(to_string(f, minf64, Minus, 325, false), format!("0.{:0>323}50", "")); + assert_eq!(to_string(f, minf64, Minus, 0), format!("0.{:0>323}5", "")); + assert_eq!(to_string(f, minf64, Minus, 324), format!("0.{:0>323}5", "")); + assert_eq!(to_string(f, minf64, Minus, 325), format!("0.{:0>323}50", "")); if cfg!(miri) { // Miri is too slow @@ -595,7 +592,7 @@ where } // very large output - assert_eq!(to_string(f, 1.1, Minus, 80000, false), format!("1.1{:0>79999}", "")); + assert_eq!(to_string(f, 1.1, Minus, 80000), format!("1.1{:0>79999}", "")); } pub fn to_shortest_exp_str_test(mut f_: F) @@ -996,166 +993,157 @@ where { use core::num::flt2dec::Sign::*; - fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize, upper: bool) -> String + fn to_string(f: &mut F, v: T, sign: Sign, frac_digits: usize) -> String where T: DecodableFloat, F: FnMut(&Decoded, &mut [u8], i16) -> (usize, i16), { to_string_with_parts(|buf, parts| { - to_exact_fixed_str(|d, b, l| f(d, b, l), v, sign, frac_digits, upper, buf, parts) + to_exact_fixed_str(|d, b, l| f(d, b, l), v, sign, frac_digits, buf, parts) }) } let f = &mut f_; - assert_eq!(to_string(f, 0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, Minus, 0, false), "0"); - assert_eq!(to_string(f, -0.0, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.0, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.0, Minus, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusRaw, 1, true), "0.0"); - assert_eq!(to_string(f, 0.0, MinusPlus, 1, true), "+0.0"); - assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1, true), "+0.0"); - assert_eq!(to_string(f, -0.0, Minus, 8, true), "0.00000000"); - assert_eq!(to_string(f, -0.0, MinusRaw, 8, true), "-0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlus, 8, true), "+0.00000000"); - assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8, true), "-0.00000000"); - - assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0, false), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1, true), "inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 8, false), "+inf"); - assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 64, true), "+inf"); - assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1, true), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8, false), "NaN"); - assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64, true), "NaN"); - assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1, true), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8, false), "-inf"); - assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64, true), "-inf"); - - assert_eq!(to_string(f, 3.14, Minus, 0, false), "3"); - assert_eq!(to_string(f, 3.14, MinusRaw, 0, false), "3"); - assert_eq!(to_string(f, 3.14, MinusPlus, 0, false), "+3"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0, false), "+3"); - assert_eq!(to_string(f, -3.14, Minus, 0, false), "-3"); - assert_eq!(to_string(f, -3.14, MinusRaw, 0, false), "-3"); - assert_eq!(to_string(f, -3.14, MinusPlus, 0, false), "-3"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0, false), "-3"); - assert_eq!(to_string(f, 3.14, Minus, 1, true), "3.1"); - assert_eq!(to_string(f, 3.14, MinusRaw, 2, true), "3.14"); - assert_eq!(to_string(f, 3.14, MinusPlus, 3, true), "+3.140"); - assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4, true), "+3.1400"); - assert_eq!(to_string(f, -3.14, Minus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusRaw, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlus, 8, true), "-3.14000000"); - assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8, true), "-3.14000000"); - - assert_eq!(to_string(f, 0.195, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.195, MinusRaw, 0, false), "0"); - assert_eq!(to_string(f, 0.195, MinusPlus, 0, false), "+0"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0, false), "+0"); - assert_eq!(to_string(f, -0.195, Minus, 0, false), "-0"); - assert_eq!(to_string(f, -0.195, MinusRaw, 0, false), "-0"); - assert_eq!(to_string(f, -0.195, MinusPlus, 0, false), "-0"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0, false), "-0"); - assert_eq!(to_string(f, 0.195, Minus, 1, true), "0.2"); - assert_eq!(to_string(f, 0.195, MinusRaw, 2, true), "0.20"); - assert_eq!(to_string(f, 0.195, MinusPlus, 3, true), "+0.195"); - assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4, true), "+0.1950"); - assert_eq!(to_string(f, -0.195, Minus, 5, true), "-0.19500"); - assert_eq!(to_string(f, -0.195, MinusRaw, 6, true), "-0.195000"); - assert_eq!(to_string(f, -0.195, MinusPlus, 7, true), "-0.1950000"); - assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8, true), "-0.19500000"); - - assert_eq!(to_string(f, 999.5, Minus, 0, false), "1000"); - assert_eq!(to_string(f, 999.5, Minus, 1, false), "999.5"); - assert_eq!(to_string(f, 999.5, Minus, 2, false), "999.50"); - assert_eq!(to_string(f, 999.5, Minus, 3, false), "999.500"); - assert_eq!(to_string(f, 999.5, Minus, 30, false), "999.500000000000000000000000000000"); - - assert_eq!(to_string(f, 0.5, Minus, 0, false), "1"); - assert_eq!(to_string(f, 0.5, Minus, 1, false), "0.5"); - assert_eq!(to_string(f, 0.5, Minus, 2, false), "0.50"); - assert_eq!(to_string(f, 0.5, Minus, 3, false), "0.500"); - - assert_eq!(to_string(f, 0.95, Minus, 0, false), "1"); - assert_eq!(to_string(f, 0.95, Minus, 1, false), "0.9"); // because it really is less than 0.95 - assert_eq!(to_string(f, 0.95, Minus, 2, false), "0.95"); - assert_eq!(to_string(f, 0.95, Minus, 3, false), "0.950"); - assert_eq!(to_string(f, 0.95, Minus, 10, false), "0.9500000000"); - assert_eq!(to_string(f, 0.95, Minus, 30, false), "0.949999999999999955591079014994"); - - assert_eq!(to_string(f, 0.095, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.095, Minus, 1, false), "0.1"); - assert_eq!(to_string(f, 0.095, Minus, 2, false), "0.10"); - assert_eq!(to_string(f, 0.095, Minus, 3, false), "0.095"); - assert_eq!(to_string(f, 0.095, Minus, 4, false), "0.0950"); - assert_eq!(to_string(f, 0.095, Minus, 10, false), "0.0950000000"); - assert_eq!(to_string(f, 0.095, Minus, 30, false), "0.095000000000000001110223024625"); - - assert_eq!(to_string(f, 0.0095, Minus, 0, false), "0"); - assert_eq!(to_string(f, 0.0095, Minus, 1, false), "0.0"); - assert_eq!(to_string(f, 0.0095, Minus, 2, false), "0.01"); - assert_eq!(to_string(f, 0.0095, Minus, 3, false), "0.009"); // really is less than 0.0095 - assert_eq!(to_string(f, 0.0095, Minus, 4, false), "0.0095"); - assert_eq!(to_string(f, 0.0095, Minus, 5, false), "0.00950"); - assert_eq!(to_string(f, 0.0095, Minus, 10, false), "0.0095000000"); - assert_eq!(to_string(f, 0.0095, Minus, 30, false), "0.009499999999999999764077607267"); - - assert_eq!(to_string(f, 7.5e-11, Minus, 0, false), "0"); - assert_eq!(to_string(f, 7.5e-11, Minus, 3, false), "0.000"); - assert_eq!(to_string(f, 7.5e-11, Minus, 10, false), "0.0000000001"); - assert_eq!(to_string(f, 7.5e-11, Minus, 11, false), "0.00000000007"); // ditto - assert_eq!(to_string(f, 7.5e-11, Minus, 12, false), "0.000000000075"); - assert_eq!(to_string(f, 7.5e-11, Minus, 13, false), "0.0000000000750"); - assert_eq!(to_string(f, 7.5e-11, Minus, 20, false), "0.00000000007500000000"); - assert_eq!(to_string(f, 7.5e-11, Minus, 30, false), "0.000000000074999999999999999501"); - - assert_eq!(to_string(f, 1.0e25, Minus, 0, false), "10000000000000000905969664"); - assert_eq!(to_string(f, 1.0e25, Minus, 1, false), "10000000000000000905969664.0"); - assert_eq!(to_string(f, 1.0e25, Minus, 3, false), "10000000000000000905969664.000"); - - assert_eq!(to_string(f, 1.0e-6, Minus, 0, false), "0"); - assert_eq!(to_string(f, 1.0e-6, Minus, 3, false), "0.000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 6, false), "0.000001"); - assert_eq!(to_string(f, 1.0e-6, Minus, 9, false), "0.000001000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 12, false), "0.000001000000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 22, false), "0.0000010000000000000000"); - assert_eq!(to_string(f, 1.0e-6, Minus, 23, false), "0.00000099999999999999995"); - assert_eq!(to_string(f, 1.0e-6, Minus, 24, false), "0.000000999999999999999955"); - assert_eq!(to_string(f, 1.0e-6, Minus, 25, false), "0.0000009999999999999999547"); - assert_eq!(to_string(f, 1.0e-6, Minus, 35, false), "0.00000099999999999999995474811182589"); + assert_eq!(to_string(f, 0.0, Minus, 0), "0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 0), "0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 0), "+0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 0), "+0"); + assert_eq!(to_string(f, -0.0, Minus, 0), "0"); + assert_eq!(to_string(f, -0.0, MinusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.0, MinusPlus, 0), "+0"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 0), "-0"); + assert_eq!(to_string(f, 0.0, Minus, 1), "0.0"); + assert_eq!(to_string(f, 0.0, MinusRaw, 1), "0.0"); + assert_eq!(to_string(f, 0.0, MinusPlus, 1), "+0.0"); + assert_eq!(to_string(f, 0.0, MinusPlusRaw, 1), "+0.0"); + assert_eq!(to_string(f, -0.0, Minus, 8), "0.00000000"); + assert_eq!(to_string(f, -0.0, MinusRaw, 8), "-0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlus, 8), "+0.00000000"); + assert_eq!(to_string(f, -0.0, MinusPlusRaw, 8), "-0.00000000"); + + assert_eq!(to_string(f, 1.0 / 0.0, Minus, 0), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusRaw, 1), "inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlus, 8), "+inf"); + assert_eq!(to_string(f, 1.0 / 0.0, MinusPlusRaw, 64), "+inf"); + assert_eq!(to_string(f, 0.0 / 0.0, Minus, 0), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusRaw, 1), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlus, 8), "NaN"); + assert_eq!(to_string(f, 0.0 / 0.0, MinusPlusRaw, 64), "NaN"); + assert_eq!(to_string(f, -1.0 / 0.0, Minus, 0), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusRaw, 1), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlus, 8), "-inf"); + assert_eq!(to_string(f, -1.0 / 0.0, MinusPlusRaw, 64), "-inf"); + + assert_eq!(to_string(f, 3.14, Minus, 0), "3"); + assert_eq!(to_string(f, 3.14, MinusRaw, 0), "3"); + assert_eq!(to_string(f, 3.14, MinusPlus, 0), "+3"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 0), "+3"); + assert_eq!(to_string(f, -3.14, Minus, 0), "-3"); + assert_eq!(to_string(f, -3.14, MinusRaw, 0), "-3"); + assert_eq!(to_string(f, -3.14, MinusPlus, 0), "-3"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 0), "-3"); + assert_eq!(to_string(f, 3.14, Minus, 1), "3.1"); + assert_eq!(to_string(f, 3.14, MinusRaw, 2), "3.14"); + assert_eq!(to_string(f, 3.14, MinusPlus, 3), "+3.140"); + assert_eq!(to_string(f, 3.14, MinusPlusRaw, 4), "+3.1400"); + assert_eq!(to_string(f, -3.14, Minus, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusRaw, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlus, 8), "-3.14000000"); + assert_eq!(to_string(f, -3.14, MinusPlusRaw, 8), "-3.14000000"); + + assert_eq!(to_string(f, 0.195, Minus, 0), "0"); + assert_eq!(to_string(f, 0.195, MinusRaw, 0), "0"); + assert_eq!(to_string(f, 0.195, MinusPlus, 0), "+0"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 0), "+0"); + assert_eq!(to_string(f, -0.195, Minus, 0), "-0"); + assert_eq!(to_string(f, -0.195, MinusRaw, 0), "-0"); + assert_eq!(to_string(f, -0.195, MinusPlus, 0), "-0"); + assert_eq!(to_string(f, -0.195, MinusPlusRaw, 0), "-0"); + assert_eq!(to_string(f, 0.195, Minus, 1), "0.2"); + assert_eq!(to_string(f, 0.195, MinusRaw, 2), "0.20"); + assert_eq!(to_string(f, 0.195, MinusPlus, 3), "+0.195"); + assert_eq!(to_string(f, 0.195, MinusPlusRaw, 4), "+0.1950"); + assert_eq!(to_string(f, -0.195, Minus, 5), "-0.19500"); + assert_eq!(to_string(f, -0.195, MinusRaw, 6), "-0.195000"); + assert_eq!(to_string(f, -0.195, MinusPlus, 7), "-0.1950000"); + assert_eq!(to_string(f, -0.195, MinusPlusRaw, 8), "-0.19500000"); + + assert_eq!(to_string(f, 999.5, Minus, 0), "1000"); + assert_eq!(to_string(f, 999.5, Minus, 1), "999.5"); + assert_eq!(to_string(f, 999.5, Minus, 2), "999.50"); + assert_eq!(to_string(f, 999.5, Minus, 3), "999.500"); + assert_eq!(to_string(f, 999.5, Minus, 30), "999.500000000000000000000000000000"); + + assert_eq!(to_string(f, 0.5, Minus, 0), "1"); + assert_eq!(to_string(f, 0.5, Minus, 1), "0.5"); + assert_eq!(to_string(f, 0.5, Minus, 2), "0.50"); + assert_eq!(to_string(f, 0.5, Minus, 3), "0.500"); + + assert_eq!(to_string(f, 0.95, Minus, 0), "1"); + assert_eq!(to_string(f, 0.95, Minus, 1), "0.9"); // because it really is less than 0.95 + assert_eq!(to_string(f, 0.95, Minus, 2), "0.95"); + assert_eq!(to_string(f, 0.95, Minus, 3), "0.950"); + assert_eq!(to_string(f, 0.95, Minus, 10), "0.9500000000"); + assert_eq!(to_string(f, 0.95, Minus, 30), "0.949999999999999955591079014994"); + + assert_eq!(to_string(f, 0.095, Minus, 0), "0"); + assert_eq!(to_string(f, 0.095, Minus, 1), "0.1"); + assert_eq!(to_string(f, 0.095, Minus, 2), "0.10"); + assert_eq!(to_string(f, 0.095, Minus, 3), "0.095"); + assert_eq!(to_string(f, 0.095, Minus, 4), "0.0950"); + assert_eq!(to_string(f, 0.095, Minus, 10), "0.0950000000"); + assert_eq!(to_string(f, 0.095, Minus, 30), "0.095000000000000001110223024625"); + + assert_eq!(to_string(f, 0.0095, Minus, 0), "0"); + assert_eq!(to_string(f, 0.0095, Minus, 1), "0.0"); + assert_eq!(to_string(f, 0.0095, Minus, 2), "0.01"); + assert_eq!(to_string(f, 0.0095, Minus, 3), "0.009"); // really is less than 0.0095 + assert_eq!(to_string(f, 0.0095, Minus, 4), "0.0095"); + assert_eq!(to_string(f, 0.0095, Minus, 5), "0.00950"); + assert_eq!(to_string(f, 0.0095, Minus, 10), "0.0095000000"); + assert_eq!(to_string(f, 0.0095, Minus, 30), "0.009499999999999999764077607267"); + + assert_eq!(to_string(f, 7.5e-11, Minus, 0), "0"); + assert_eq!(to_string(f, 7.5e-11, Minus, 3), "0.000"); + assert_eq!(to_string(f, 7.5e-11, Minus, 10), "0.0000000001"); + assert_eq!(to_string(f, 7.5e-11, Minus, 11), "0.00000000007"); // ditto + assert_eq!(to_string(f, 7.5e-11, Minus, 12), "0.000000000075"); + assert_eq!(to_string(f, 7.5e-11, Minus, 13), "0.0000000000750"); + assert_eq!(to_string(f, 7.5e-11, Minus, 20), "0.00000000007500000000"); + assert_eq!(to_string(f, 7.5e-11, Minus, 30), "0.000000000074999999999999999501"); + + assert_eq!(to_string(f, 1.0e25, Minus, 0), "10000000000000000905969664"); + assert_eq!(to_string(f, 1.0e25, Minus, 1), "10000000000000000905969664.0"); + assert_eq!(to_string(f, 1.0e25, Minus, 3), "10000000000000000905969664.000"); + + assert_eq!(to_string(f, 1.0e-6, Minus, 0), "0"); + assert_eq!(to_string(f, 1.0e-6, Minus, 3), "0.000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 6), "0.000001"); + assert_eq!(to_string(f, 1.0e-6, Minus, 9), "0.000001000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 12), "0.000001000000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 22), "0.0000010000000000000000"); + assert_eq!(to_string(f, 1.0e-6, Minus, 23), "0.00000099999999999999995"); + assert_eq!(to_string(f, 1.0e-6, Minus, 24), "0.000000999999999999999955"); + assert_eq!(to_string(f, 1.0e-6, Minus, 25), "0.0000009999999999999999547"); + assert_eq!(to_string(f, 1.0e-6, Minus, 35), "0.00000099999999999999995474811182589"); + assert_eq!(to_string(f, 1.0e-6, Minus, 45), "0.000000999999999999999954748111825886258685614"); assert_eq!( - to_string(f, 1.0e-6, Minus, 45, false), - "0.000000999999999999999954748111825886258685614" - ); - assert_eq!( - to_string(f, 1.0e-6, Minus, 55, false), + to_string(f, 1.0e-6, Minus, 55), "0.0000009999999999999999547481118258862586856139387236908" ); assert_eq!( - to_string(f, 1.0e-6, Minus, 65, false), + to_string(f, 1.0e-6, Minus, 65), "0.00000099999999999999995474811182588625868561393872369080781936646" ); assert_eq!( - to_string(f, 1.0e-6, Minus, 75, false), + to_string(f, 1.0e-6, Minus, 75), "0.000000999999999999999954748111825886258685613938723690807819366455078125000" ); - assert_eq!(to_string(f, f32::MAX, Minus, 0, false), "340282346638528859811704183484516925440"); - assert_eq!( - to_string(f, f32::MAX, Minus, 1, false), - "340282346638528859811704183484516925440.0" - ); - assert_eq!( - to_string(f, f32::MAX, Minus, 2, false), - "340282346638528859811704183484516925440.00" - ); + assert_eq!(to_string(f, f32::MAX, Minus, 0), "340282346638528859811704183484516925440"); + assert_eq!(to_string(f, f32::MAX, Minus, 1), "340282346638528859811704183484516925440.0"); + assert_eq!(to_string(f, f32::MAX, Minus, 2), "340282346638528859811704183484516925440.00"); if cfg!(miri) { // Miri is too slow @@ -1163,24 +1151,24 @@ where } let minf32 = ldexp_f32(1.0, -149); - assert_eq!(to_string(f, minf32, Minus, 0, false), "0"); - assert_eq!(to_string(f, minf32, Minus, 1, false), "0.0"); - assert_eq!(to_string(f, minf32, Minus, 2, false), "0.00"); - assert_eq!(to_string(f, minf32, Minus, 4, false), "0.0000"); - assert_eq!(to_string(f, minf32, Minus, 8, false), "0.00000000"); - assert_eq!(to_string(f, minf32, Minus, 16, false), "0.0000000000000000"); - assert_eq!(to_string(f, minf32, Minus, 32, false), "0.00000000000000000000000000000000"); + assert_eq!(to_string(f, minf32, Minus, 0), "0"); + assert_eq!(to_string(f, minf32, Minus, 1), "0.0"); + assert_eq!(to_string(f, minf32, Minus, 2), "0.00"); + assert_eq!(to_string(f, minf32, Minus, 4), "0.0000"); + assert_eq!(to_string(f, minf32, Minus, 8), "0.00000000"); + assert_eq!(to_string(f, minf32, Minus, 16), "0.0000000000000000"); + assert_eq!(to_string(f, minf32, Minus, 32), "0.00000000000000000000000000000000"); assert_eq!( - to_string(f, minf32, Minus, 64, false), + to_string(f, minf32, Minus, 64), "0.0000000000000000000000000000000000000000000014012984643248170709" ); assert_eq!( - to_string(f, minf32, Minus, 128, false), + to_string(f, minf32, Minus, 128), "0.0000000000000000000000000000000000000000000014012984643248170709\ 2372958328991613128026194187651577175706828388979108268586060149" ); assert_eq!( - to_string(f, minf32, Minus, 256, false), + to_string(f, minf32, Minus, 256), "0.0000000000000000000000000000000000000000000014012984643248170709\ 2372958328991613128026194187651577175706828388979108268586060148\ 6638188362121582031250000000000000000000000000000000000000000000\ @@ -1188,7 +1176,7 @@ where ); assert_eq!( - to_string(f, f64::MAX, Minus, 0, false), + to_string(f, f64::MAX, Minus, 0), "1797693134862315708145274237317043567980705675258449965989174768\ 0315726078002853876058955863276687817154045895351438246423432132\ 6889464182768467546703537516986049910576551282076245490090389328\ @@ -1196,7 +1184,7 @@ where 26204144723168738177180919299881250404026184124858368" ); assert_eq!( - to_string(f, f64::MAX, Minus, 10, false), + to_string(f, f64::MAX, Minus, 10), "1797693134862315708145274237317043567980705675258449965989174768\ 0315726078002853876058955863276687817154045895351438246423432132\ 6889464182768467546703537516986049910576551282076245490090389328\ @@ -1205,16 +1193,16 @@ where ); let minf64 = ldexp_f64(1.0, -1074); - assert_eq!(to_string(f, minf64, Minus, 0, false), "0"); - assert_eq!(to_string(f, minf64, Minus, 1, false), "0.0"); - assert_eq!(to_string(f, minf64, Minus, 10, false), "0.0000000000"); + assert_eq!(to_string(f, minf64, Minus, 0), "0"); + assert_eq!(to_string(f, minf64, Minus, 1), "0.0"); + assert_eq!(to_string(f, minf64, Minus, 10), "0.0000000000"); assert_eq!( - to_string(f, minf64, Minus, 100, false), + to_string(f, minf64, Minus, 100), "0.0000000000000000000000000000000000000000000000000000000000000000\ 000000000000000000000000000000000000" ); assert_eq!( - to_string(f, minf64, Minus, 1000, false), + to_string(f, minf64, Minus, 1000), "0.0000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000\ 0000000000000000000000000000000000000000000000000000000000000000\ @@ -1234,15 +1222,15 @@ where ); // very large output - assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("10.{:0>80000}", "")); - assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>80000}", "")); + assert_eq!(to_string(f, 0.0, Minus, 80000), format!("0.{:0>80000}", "")); + assert_eq!(to_string(f, 1.0e1, Minus, 80000), format!("10.{:0>80000}", "")); + assert_eq!(to_string(f, 1.0e0, Minus, 80000), format!("1.{:0>80000}", "")); assert_eq!( - to_string(f, 1.0e-1, Minus, 80000, false), + to_string(f, 1.0e-1, Minus, 80000), format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "") ); assert_eq!( - to_string(f, 1.0e-20, Minus, 80000, false), + to_string(f, 1.0e-20, Minus, 80000), format!( "0.0000000000000000000099999999999999994515327145420957165172950370\ 2787392447107715776066783064379706047475337982177734375{:0>79881}", From 34ef8f5441d5335c4177abd622383ed34a6e9315 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 15 Feb 2020 18:47:34 -0500 Subject: [PATCH 0277/1250] Move to using an extern type for opaqueness This prevents accidental dereferences and so forth of the Void type, as well as cleaning up the error message to reference Opaque rather than the more complicated PhantomData type. --- src/libcore/fmt/mod.rs | 16 ++++------------ src/test/ui/fmt/send-sync.stderr | 20 ++++++++------------ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 3f2c9654706..0c51a802fab 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -238,16 +238,8 @@ pub struct Formatter<'a> { // NB. Argument is essentially an optimized partially applied formatting function, // equivalent to `exists T.(&T, fn(&T, &mut Formatter<'_>) -> Result`. -struct Void { - _priv: (), - /// Erases all oibits, because `Void` erases the type of the object that - /// will be used to produce formatted output. Since we do not know what - /// oibits the real types have (and they can have any or none), we need to - /// take the most conservative approach and forbid all oibits. - /// - /// It was added after #45197 showed that one could share a `!Sync` - /// object across threads by passing it into `format_args!`. - _oibit_remover: PhantomData<*mut dyn Fn()>, +extern "C" { + type Opaque; } /// This struct represents the generic "argument" which is taken by the Xprintf @@ -259,8 +251,8 @@ struct Void { #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] #[doc(hidden)] pub struct ArgumentV1<'a> { - value: &'a Void, - formatter: fn(&Void, &mut Formatter<'_>) -> Result, + value: &'a Opaque, + formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } impl<'a> ArgumentV1<'a> { diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr index be6e41afaf8..c8439764eff 100644 --- a/src/test/ui/fmt/send-sync.stderr +++ b/src/test/ui/fmt/send-sync.stderr @@ -1,34 +1,30 @@ -error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely +error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely --> $DIR/send-sync.rs:8:5 | LL | fn send(_: T) {} | ---- ---- required by this bound in `send` ... LL | send(format_args!("{:?}", c)); - | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + | ^^^^ `core::fmt::Opaque` cannot be shared between threads safely | - = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` - = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` - = note: required because it appears within the type `core::fmt::Void` - = note: required because it appears within the type `&core::fmt::Void` + = help: within `[std::fmt::ArgumentV1<'_>]`, the trait `std::marker::Sync` is not implemented for `core::fmt::Opaque` + = note: required because it appears within the type `&core::fmt::Opaque` = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because of the requirements on the impl of `std::marker::Send` for `&[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `std::fmt::Arguments<'_>` -error[E0277]: `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely +error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely --> $DIR/send-sync.rs:9:5 | LL | fn sync(_: T) {} | ---- ---- required by this bound in `sync` ... LL | sync(format_args!("{:?}", c)); - | ^^^^ `*mut (dyn std::ops::Fn() + 'static)` cannot be shared between threads safely + | ^^^^ `core::fmt::Opaque` cannot be shared between threads safely | - = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `*mut (dyn std::ops::Fn() + 'static)` - = note: required because it appears within the type `std::marker::PhantomData<*mut (dyn std::ops::Fn() + 'static)>` - = note: required because it appears within the type `core::fmt::Void` - = note: required because it appears within the type `&core::fmt::Void` + = help: within `std::fmt::Arguments<'_>`, the trait `std::marker::Sync` is not implemented for `core::fmt::Opaque` + = note: required because it appears within the type `&core::fmt::Opaque` = note: required because it appears within the type `std::fmt::ArgumentV1<'_>` = note: required because it appears within the type `[std::fmt::ArgumentV1<'_>]` = note: required because it appears within the type `&[std::fmt::ArgumentV1<'_>]` From f6bfdc95445180aee579dcacc6e6bdc4e6ecf56f Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 16 Feb 2020 10:17:01 -0500 Subject: [PATCH 0278/1250] Move the show_usize marker function to a static Currently, function items are always tagged unnamed_addr, which means that casting a function to a function pointer is not guaranteed to produce a deterministic address. However, once a function pointer is created, we do expect that to remain stable. So, this changes the show_usize function to a static containing a function pointer and uses that for comparisons. Notably, a *static* may have 'unstable' address, but the function pointer within it must be constant. Resolves issue 58320. --- src/libcore/fmt/mod.rs | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 0c51a802fab..993b1073493 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -255,12 +255,19 @@ pub struct ArgumentV1<'a> { formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } -impl<'a> ArgumentV1<'a> { - #[inline(never)] - fn show_usize(x: &usize, f: &mut Formatter<'_>) -> Result { - Display::fmt(x, f) - } +// This gurantees a single stable value for the function pointer associated with +// indices/counts in the formatting infrastructure. +// +// Note that a function defined as such would not be correct as functions are +// always tagged unnamed_addr with the current lowering to LLVM IR, so their +// address is not considered important to LLVM and as such the as_usize cast +// could have been miscompiled. In practice, we never call as_usize on non-usize +// containing data (as a matter of static generation of the formatting +// arguments), so this is merely an additional check. +#[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] +static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {}; +impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { @@ -270,11 +277,13 @@ impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn from_usize(x: &usize) -> ArgumentV1<'_> { - ArgumentV1::new(x, ArgumentV1::show_usize) + ArgumentV1::new(x, USIZE_MARKER) } fn as_usize(&self) -> Option { - if self.formatter as usize == ArgumentV1::show_usize as usize { + if self.formatter as usize == USIZE_MARKER as usize { + // SAFETY: The `formatter` field is only set to USIZE_MARKER if + // the value is a usize, so this is safe Some(unsafe { *(self.value as *const _ as *const usize) }) } else { None From 2e07892c7dd71f2025b68dcf8c144d53b3560511 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 16 Feb 2020 21:42:37 +0100 Subject: [PATCH 0279/1250] Do not emit note suggesting to implement trait to foreign type Update tests Extend to other operations Refractor check in a separate function Fix more tests --- src/librustc_typeck/check/op.rs | 33 ++++++++++--------- src/test/ui/autoderef-full-lval.stderr | 4 --- src/test/ui/binop/binop-bitxor-str.stderr | 2 -- src/test/ui/binop/binop-mul-bool.stderr | 2 -- src/test/ui/binop/binop-typeck.stderr | 2 -- .../core-traits-no-impls-length-33.stderr | 4 --- .../note-unsupported.stderr | 4 --- src/test/ui/error-codes/E0067.stderr | 2 -- src/test/ui/error-festival.stderr | 2 -- src/test/ui/for/for-loop-type-error.stderr | 2 -- src/test/ui/issues/issue-14915.stderr | 2 -- src/test/ui/issues/issue-24363.stderr | 2 -- src/test/ui/issues/issue-31076.stderr | 4 --- src/test/ui/issues/issue-35668.stderr | 2 -- src/test/ui/issues/issue-40610.stderr | 2 -- src/test/ui/issues/issue-41394.stderr | 2 -- src/test/ui/issues/issue-59488.stderr | 3 -- src/test/ui/minus-string.stderr | 2 -- src/test/ui/pattern/pattern-tyvar-2.stderr | 2 -- .../disallowed-positions.stderr | 6 ---- src/test/ui/span/issue-39018.stderr | 4 --- .../trait-resolution-in-overloaded-op.stderr | 2 -- src/test/ui/unop-neg-bool.stderr | 2 -- src/test/ui/vec/vec-res-add.stderr | 2 -- 24 files changed, 17 insertions(+), 77 deletions(-) diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 86b00c2f0d3..bb31e979b73 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -5,7 +5,7 @@ use super::{FnCtxt, Needs}; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::TyKind::{Adt, Array, Char, FnDef, Never, Ref, Str, Tuple, Uint}; use rustc::ty::{self, Ty, TypeFoldable}; -use rustc_errors::{self, struct_span_err, Applicability}; +use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_span::Span; @@ -321,11 +321,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty, missing_trait )); } else if !suggested_deref { - err.note(&format!( - "an implementation of `{}` might \ - be missing for `{}`", - missing_trait, lhs_ty - )); + suggest_impl_missing(&mut err, lhs_ty, &missing_trait); } } err.emit(); @@ -467,11 +463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { lhs_ty, missing_trait )); } else if !suggested_deref && !involves_fn { - err.note(&format!( - "an implementation of `{}` might \ - be missing for `{}`", - missing_trait, lhs_ty - )); + suggest_impl_missing(&mut err, lhs_ty, &missing_trait); } } err.emit(); @@ -707,11 +699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::UnOp::UnNot => "std::ops::Not", hir::UnOp::UnDeref => "std::ops::UnDerf", }; - err.note(&format!( - "an implementation of `{}` might \ - be missing for `{}`", - missing_trait, operand_ty - )); + suggest_impl_missing(&mut err, operand_ty, &missing_trait); } } err.emit(); @@ -929,3 +917,16 @@ fn is_builtin_binop<'tcx>(lhs: Ty<'tcx>, rhs: Ty<'tcx>, op: hir::BinOp) -> bool } } } + +/// If applicable, note that an implementation of `trait` for `ty` may fix the error. +fn suggest_impl_missing(err: &mut DiagnosticBuilder<'_>, ty: Ty<'_>, missing_trait: &str) { + if let Adt(def, _) = ty.peel_refs().kind { + if def.did.is_local() { + err.note(&format!( + "an implementation of `{}` might \ + be missing for `{}`", + missing_trait, ty + )); + } + } +} diff --git a/src/test/ui/autoderef-full-lval.stderr b/src/test/ui/autoderef-full-lval.stderr index e2870ef8062..f094388794e 100644 --- a/src/test/ui/autoderef-full-lval.stderr +++ b/src/test/ui/autoderef-full-lval.stderr @@ -5,8 +5,6 @@ LL | let z: isize = a.x + b.y; | --- ^ --- std::boxed::Box | | | std::boxed::Box - | - = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box` error[E0369]: cannot add `std::boxed::Box` to `std::boxed::Box` --> $DIR/autoderef-full-lval.rs:21:33 @@ -15,8 +13,6 @@ LL | let answer: isize = forty.a + two.a; | ------- ^ ----- std::boxed::Box | | | std::boxed::Box - | - = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box` error: aborting due to 2 previous errors diff --git a/src/test/ui/binop/binop-bitxor-str.stderr b/src/test/ui/binop/binop-bitxor-str.stderr index 9a0d301d863..18c1ce0ff02 100644 --- a/src/test/ui/binop/binop-bitxor-str.stderr +++ b/src/test/ui/binop/binop-bitxor-str.stderr @@ -5,8 +5,6 @@ LL | fn main() { let x = "a".to_string() ^ "b".to_string(); } | --------------- ^ --------------- std::string::String | | | std::string::String - | - = note: an implementation of `std::ops::BitXor` might be missing for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/binop/binop-mul-bool.stderr b/src/test/ui/binop/binop-mul-bool.stderr index ade22025589..859c44a859e 100644 --- a/src/test/ui/binop/binop-mul-bool.stderr +++ b/src/test/ui/binop/binop-mul-bool.stderr @@ -5,8 +5,6 @@ LL | fn main() { let x = true * false; } | ---- ^ ----- bool | | | bool - | - = note: an implementation of `std::ops::Mul` might be missing for `bool` error: aborting due to previous error diff --git a/src/test/ui/binop/binop-typeck.stderr b/src/test/ui/binop/binop-typeck.stderr index ebf82079ef2..42d91081999 100644 --- a/src/test/ui/binop/binop-typeck.stderr +++ b/src/test/ui/binop/binop-typeck.stderr @@ -5,8 +5,6 @@ LL | let z = x + y; | - ^ - {integer} | | | bool - | - = note: an implementation of `std::ops::Add` might be missing for `bool` error: aborting due to previous error diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index 781a179624e..c03377d74e9 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -23,8 +23,6 @@ LL | [0_usize; 33] == [1_usize; 33] | ------------- ^^ ------------- [usize; 33] | | | [usize; 33] - | - = note: an implementation of `std::cmp::PartialEq` might be missing for `[usize; 33]` error[E0369]: binary operation `<` cannot be applied to type `[usize; 33]` --> $DIR/core-traits-no-impls-length-33.rs:19:19 @@ -33,8 +31,6 @@ LL | [0_usize; 33] < [1_usize; 33] | ------------- ^ ------------- [usize; 33] | | | [usize; 33] - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `[usize; 33]` error[E0277]: the trait bound `&[usize; 33]: std::iter::IntoIterator` is not satisfied --> $DIR/core-traits-no-impls-length-33.rs:24:14 diff --git a/src/test/ui/destructuring-assignment/note-unsupported.stderr b/src/test/ui/destructuring-assignment/note-unsupported.stderr index a6805c32a6e..d4e25930d22 100644 --- a/src/test/ui/destructuring-assignment/note-unsupported.stderr +++ b/src/test/ui/destructuring-assignment/note-unsupported.stderr @@ -16,8 +16,6 @@ LL | (a, b) += (3, 4); | ------^^^^^^^^^^ | | | cannot use `+=` on type `({integer}, {integer})` - | - = note: an implementation of `std::ops::AddAssign` might be missing for `({integer}, {integer})` error[E0067]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:7:12 @@ -48,8 +46,6 @@ LL | [a, b] += [3, 4]; | ------^^^^^^^^^^ | | | cannot use `+=` on type `[{integer}; 2]` - | - = note: an implementation of `std::ops::AddAssign` might be missing for `[{integer}; 2]` error[E0067]: invalid left-hand side of assignment --> $DIR/note-unsupported.rs:11:12 diff --git a/src/test/ui/error-codes/E0067.stderr b/src/test/ui/error-codes/E0067.stderr index 526503798b3..fad8270fd5a 100644 --- a/src/test/ui/error-codes/E0067.stderr +++ b/src/test/ui/error-codes/E0067.stderr @@ -5,8 +5,6 @@ LL | LinkedList::new() += 1; | -----------------^^^^^ | | | cannot use `+=` on type `std::collections::LinkedList<_>` - | - = note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>` error[E0067]: invalid left-hand side of assignment --> $DIR/E0067.rs:4:23 diff --git a/src/test/ui/error-festival.stderr b/src/test/ui/error-festival.stderr index 9b69b373364..fb5290bf64e 100644 --- a/src/test/ui/error-festival.stderr +++ b/src/test/ui/error-festival.stderr @@ -23,8 +23,6 @@ LL | x += 2; | -^^^^^ | | | cannot use `+=` on type `&str` - | - = note: an implementation of `std::ops::AddAssign` might be missing for `&str` error[E0599]: no method named `z` found for reference `&str` in the current scope --> $DIR/error-festival.rs:16:7 diff --git a/src/test/ui/for/for-loop-type-error.stderr b/src/test/ui/for/for-loop-type-error.stderr index 0ed26384f40..c93a3b9b25c 100644 --- a/src/test/ui/for/for-loop-type-error.stderr +++ b/src/test/ui/for/for-loop-type-error.stderr @@ -5,8 +5,6 @@ LL | let x = () + (); | -- ^ -- () | | | () - | - = note: an implementation of `std::ops::Add` might be missing for `()` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-14915.stderr b/src/test/ui/issues/issue-14915.stderr index 00b9909af59..3c34a8a3467 100644 --- a/src/test/ui/issues/issue-14915.stderr +++ b/src/test/ui/issues/issue-14915.stderr @@ -5,8 +5,6 @@ LL | println!("{}", x + 1); | - ^ - {integer} | | | std::boxed::Box - | - = note: an implementation of `std::ops::Add` might be missing for `std::boxed::Box` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-24363.stderr b/src/test/ui/issues/issue-24363.stderr index a60fb24ec12..16537e21ae0 100644 --- a/src/test/ui/issues/issue-24363.stderr +++ b/src/test/ui/issues/issue-24363.stderr @@ -11,8 +11,6 @@ LL | ()+() | --^-- () | | | () - | - = note: an implementation of `std::ops::Add` might be missing for `()` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-31076.stderr b/src/test/ui/issues/issue-31076.stderr index 5d65734cd23..4c0e1cf7ebb 100644 --- a/src/test/ui/issues/issue-31076.stderr +++ b/src/test/ui/issues/issue-31076.stderr @@ -5,8 +5,6 @@ LL | let x = 5 + 6; | - ^ - {integer} | | | {integer} - | - = note: an implementation of `std::ops::Add` might be missing for `{integer}` error[E0369]: cannot add `i32` to `i32` --> $DIR/issue-31076.rs:15:18 @@ -15,8 +13,6 @@ LL | let y = 5i32 + 6i32; | ---- ^ ---- i32 | | | i32 - | - = note: an implementation of `std::ops::Add` might be missing for `i32` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-35668.stderr b/src/test/ui/issues/issue-35668.stderr index 9d5796a5eef..98e8e6366b9 100644 --- a/src/test/ui/issues/issue-35668.stderr +++ b/src/test/ui/issues/issue-35668.stderr @@ -5,8 +5,6 @@ LL | a.iter().map(|a| a*a) | -^- &T | | | &T - | - = note: an implementation of `std::ops::Mul` might be missing for `&T` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-40610.stderr b/src/test/ui/issues/issue-40610.stderr index 95f45c168e1..b4e302dfffc 100644 --- a/src/test/ui/issues/issue-40610.stderr +++ b/src/test/ui/issues/issue-40610.stderr @@ -5,8 +5,6 @@ LL | () + f(&[1.0]); | -- ^ --------- () | | | () - | - = note: an implementation of `std::ops::Add` might be missing for `()` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-41394.stderr b/src/test/ui/issues/issue-41394.stderr index 3f60ea4bbf7..47a24547d45 100644 --- a/src/test/ui/issues/issue-41394.stderr +++ b/src/test/ui/issues/issue-41394.stderr @@ -5,8 +5,6 @@ LL | A = "" + 1 | -- ^ - {integer} | | | &str - | - = note: an implementation of `std::ops::Add` might be missing for `&str` error[E0080]: evaluation of constant value failed --> $DIR/issue-41394.rs:7:9 diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index 2ac5577e0a0..58f1376b19d 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -58,8 +58,6 @@ LL | foo > bar; | --- ^ --- fn(i64) -> i64 {bar} | | | fn() -> i32 {foo} - | - = note: an implementation of `std::cmp::PartialOrd` might be missing for `fn() -> i32 {foo}` error[E0308]: mismatched types --> $DIR/issue-59488.rs:25:11 @@ -79,7 +77,6 @@ LL | assert_eq!(Foo::Bar, i); | fn(usize) -> Foo {Foo::Bar} | fn(usize) -> Foo {Foo::Bar} | - = note: an implementation of `std::cmp::PartialEq` might be missing for `fn(usize) -> Foo {Foo::Bar}` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `std::fmt::Debug` diff --git a/src/test/ui/minus-string.stderr b/src/test/ui/minus-string.stderr index 9177082cf0b..3fbec7c89c9 100644 --- a/src/test/ui/minus-string.stderr +++ b/src/test/ui/minus-string.stderr @@ -3,8 +3,6 @@ error[E0600]: cannot apply unary operator `-` to type `std::string::String` | LL | fn main() { -"foo".to_string(); } | ^^^^^^^^^^^^^^^^^^ cannot apply unary operator `-` - | - = note: an implementation of `std::ops::Neg` might be missing for `std::string::String` error: aborting due to previous error diff --git a/src/test/ui/pattern/pattern-tyvar-2.stderr b/src/test/ui/pattern/pattern-tyvar-2.stderr index bb3e61017d4..95662444640 100644 --- a/src/test/ui/pattern/pattern-tyvar-2.stderr +++ b/src/test/ui/pattern/pattern-tyvar-2.stderr @@ -5,8 +5,6 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; | - ^ - {integer} | | | std::vec::Vec - | - = note: an implementation of `std::ops::Mul` might be missing for `std::vec::Vec` error: aborting due to previous error diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 084f070989b..39874a6c680 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -560,8 +560,6 @@ error[E0600]: cannot apply unary operator `-` to type `bool` | LL | if -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` - | - = note: an implementation of `std::ops::Neg` might be missing for `bool` error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` --> $DIR/disallowed-positions.rs:46:8 @@ -748,8 +746,6 @@ error[E0600]: cannot apply unary operator `-` to type `bool` | LL | while -let 0 = 0 {} | ^^^^^^^^^^ cannot apply unary operator `-` - | - = note: an implementation of `std::ops::Neg` might be missing for `bool` error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` --> $DIR/disallowed-positions.rs:110:11 @@ -927,8 +923,6 @@ error[E0600]: cannot apply unary operator `-` to type `bool` | LL | -let 0 = 0; | ^^^^^^^^^^ cannot apply unary operator `-` - | - = note: an implementation of `std::ops::Neg` might be missing for `bool` error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` --> $DIR/disallowed-positions.rs:183:5 diff --git a/src/test/ui/span/issue-39018.stderr b/src/test/ui/span/issue-39018.stderr index 8a32561bd01..8caa5bea4ac 100644 --- a/src/test/ui/span/issue-39018.stderr +++ b/src/test/ui/span/issue-39018.stderr @@ -136,8 +136,6 @@ LL | let _ = &c + &d; | -- ^ -- &&str | | | &&str - | - = note: an implementation of `std::ops::Add` might be missing for `&&str` error[E0369]: cannot add `&str` to `&&str` --> $DIR/issue-39018.rs:35:16 @@ -146,8 +144,6 @@ LL | let _ = &c + d; | -- ^ - &str | | | &&str - | - = note: an implementation of `std::ops::Add` might be missing for `&&str` error[E0369]: cannot add `&&str` to `&str` --> $DIR/issue-39018.rs:36:15 diff --git a/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr index 8d7ba36c665..29216f36f5f 100644 --- a/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr +++ b/src/test/ui/traits/trait-resolution-in-overloaded-op.stderr @@ -5,8 +5,6 @@ LL | a * b | - ^ - f64 | | | &T - | - = note: an implementation of `std::ops::Mul` might be missing for `&T` error: aborting due to previous error diff --git a/src/test/ui/unop-neg-bool.stderr b/src/test/ui/unop-neg-bool.stderr index 18273013749..9913747b88e 100644 --- a/src/test/ui/unop-neg-bool.stderr +++ b/src/test/ui/unop-neg-bool.stderr @@ -3,8 +3,6 @@ error[E0600]: cannot apply unary operator `-` to type `bool` | LL | -true; | ^^^^^ cannot apply unary operator `-` - | - = note: an implementation of `std::ops::Neg` might be missing for `bool` error: aborting due to previous error diff --git a/src/test/ui/vec/vec-res-add.stderr b/src/test/ui/vec/vec-res-add.stderr index 1cc12a222e5..2d41583268c 100644 --- a/src/test/ui/vec/vec-res-add.stderr +++ b/src/test/ui/vec/vec-res-add.stderr @@ -5,8 +5,6 @@ LL | let k = i + j; | - ^ - std::vec::Vec | | | std::vec::Vec - | - = note: an implementation of `std::ops::Add` might be missing for `std::vec::Vec` error: aborting due to previous error From 7ac4154643a952fed1d942adcb78e27b17ad41dd Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 17 Feb 2020 08:09:34 +0100 Subject: [PATCH 0280/1250] perf: Buffer stderr when writing json errors/warnings Since `stderr` is unbuffered, writing out json messages actually take up about ~10%/0.1s of the runtime of the `inflate` benchmark. cc #64413 --- src/librustc_errors/json.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs index ffdff6acec5..f0cfd815a2c 100644 --- a/src/librustc_errors/json.rs +++ b/src/librustc_errors/json.rs @@ -48,7 +48,7 @@ impl JsonEmitter { macro_backtrace: bool, ) -> JsonEmitter { JsonEmitter { - dst: Box::new(io::stderr()), + dst: Box::new(io::BufWriter::new(io::stderr())), registry, sm: source_map, pretty, From 0b1e08cb557768f168266c7bbcdcb93fcf372a66 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 17 Feb 2020 16:03:07 +0100 Subject: [PATCH 0281/1250] parse: recover `mut (x @ y)` as `(mut x @ mut y)`. --- src/librustc_parse/parser/pat.rs | 29 +++++++++++-------------- src/test/ui/parser/mut-patterns.rs | 2 ++ src/test/ui/parser/mut-patterns.stderr | 30 ++++++++++++++++---------- 3 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index ec6d4db6102..520d325f16b 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -503,17 +503,18 @@ impl<'a> Parser<'a> { // Parse the pattern we hope to be an identifier. let mut pat = self.parse_pat(Some("identifier"))?; - // Add `mut` to any binding in the parsed pattern. - let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat); - - // Unwrap; If we don't have `mut $ident`, error. - let pat = pat.into_inner(); - match &pat.kind { - PatKind::Ident(..) => {} - _ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding), + // If we don't have `mut $ident (@ pat)?`, error. + if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind { + // Don't recurse into the subpattern. + // `mut` on the outer binding doesn't affect the inner bindings. + *m = Mutability::Mut; + } else { + // Add `mut` to any binding in the parsed pattern. + let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat); + self.ban_mut_general_pat(mut_span, &pat, changed_any_binding); } - Ok(pat.kind) + Ok(pat.into_inner().kind) } /// Recover on `mut ref? ident @ pat` and suggest @@ -542,14 +543,10 @@ impl<'a> Parser<'a> { } fn visit_pat(&mut self, pat: &mut P) { - if let PatKind::Ident(ref mut bm, ..) = pat.kind { - if let BindingMode::ByValue(ref mut m @ Mutability::Not) = bm { - *m = Mutability::Mut; - } + if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind + { self.0 = true; - // Don't recurse into the subpattern, mut on the outer - // binding doesn't affect the inner bindings. - return; + *m = Mutability::Mut; } noop_visit_pat(pat, self); } diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs index 66fd5893af5..8b83d6ab2f8 100644 --- a/src/test/ui/parser/mut-patterns.rs +++ b/src/test/ui/parser/mut-patterns.rs @@ -9,6 +9,8 @@ pub fn main() { let mut _ = 0; //~ ERROR `mut` must be followed by a named binding let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding + let mut (x @ y) = 0; //~ ERROR `mut` must be attached to each individual binding + let mut mut x = 0; //~^ ERROR `mut` on a binding may not be repeated //~| remove the additional `mut`s diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr index 5f4c349d7d6..9a6af7394bf 100644 --- a/src/test/ui/parser/mut-patterns.stderr +++ b/src/test/ui/parser/mut-patterns.stderr @@ -14,14 +14,22 @@ LL | let mut (_, _) = (0, 0); | = note: `mut` may be followed by `variable` and `variable @ pattern` +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:12:9 + | +LL | let mut (x @ y) = 0; + | ^^^^^^^^^^^ help: add `mut` to each binding: `(mut x @ mut y)` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:12:13 + --> $DIR/mut-patterns.rs:14:13 | LL | let mut mut x = 0; | ^^^ help: remove the additional `mut`s error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:17:9 + --> $DIR/mut-patterns.rs:19:9 | LL | let mut Foo { x: x } = Foo { x: 3 }; | ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }` @@ -29,7 +37,7 @@ LL | let mut Foo { x: x } = Foo { x: 3 }; = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:21:9 + --> $DIR/mut-patterns.rs:23:9 | LL | let mut Foo { x } = Foo { x: 3 }; | ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }` @@ -37,13 +45,13 @@ LL | let mut Foo { x } = Foo { x: 3 }; = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` on a binding may not be repeated - --> $DIR/mut-patterns.rs:26:13 + --> $DIR/mut-patterns.rs:28:13 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^ help: remove the additional `mut`s error: expected identifier, found reserved keyword `yield` - --> $DIR/mut-patterns.rs:26:17 + --> $DIR/mut-patterns.rs:28:17 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found reserved keyword @@ -54,7 +62,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0); | ^^^^^^^ error: expected identifier, found reserved keyword `become` - --> $DIR/mut-patterns.rs:26:23 + --> $DIR/mut-patterns.rs:28:23 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^ expected identifier, found reserved keyword @@ -65,7 +73,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ^^^^^^^^ error: expected identifier, found keyword `await` - --> $DIR/mut-patterns.rs:26:31 + --> $DIR/mut-patterns.rs:28:31 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^ expected identifier, found keyword @@ -76,7 +84,7 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0); | ^^^^^^^ error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:26:9 + --> $DIR/mut-patterns.rs:28:9 | LL | let mut mut yield(become, await) = r#yield(0, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)` @@ -84,7 +92,7 @@ LL | let mut mut yield(become, await) = r#yield(0, 0); = note: `mut` may be followed by `variable` and `variable @ pattern` error: `mut` must be attached to each individual binding - --> $DIR/mut-patterns.rs:35:9 + --> $DIR/mut-patterns.rs:37:9 | LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` @@ -92,7 +100,7 @@ LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) = note: `mut` may be followed by `variable` and `variable @ pattern` error: expected identifier, found `x` - --> $DIR/mut-patterns.rs:42:21 + --> $DIR/mut-patterns.rs:44:21 | LL | let mut $p = 0; | ^^ expected identifier @@ -102,5 +110,5 @@ LL | foo!(x); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 12 previous errors +error: aborting due to 13 previous errors From ee064befa06ad54193786c9169672f9349d0bfaf Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 17 Feb 2020 16:46:51 +0100 Subject: [PATCH 0282/1250] Ensure diagnostics are printed in the correct order Even when buffered. Ideally we would flush only when the emitter is done, but that requires larger changes. This gives most of the benefit of buffering in any case. --- src/librustc_errors/json.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs index f0cfd815a2c..97b9ca924bb 100644 --- a/src/librustc_errors/json.rs +++ b/src/librustc_errors/json.rs @@ -104,7 +104,8 @@ impl Emitter for JsonEmitter { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { writeln!(&mut self.dst, "{}", as_json(&data)) - }; + } + .and_then(|_| self.dst.flush()); if let Err(e) = result { panic!("failed to print diagnostics: {:?}", e); } @@ -116,7 +117,8 @@ impl Emitter for JsonEmitter { writeln!(&mut self.dst, "{}", as_pretty_json(&data)) } else { writeln!(&mut self.dst, "{}", as_json(&data)) - }; + } + .and_then(|_| self.dst.flush()); if let Err(e) = result { panic!("failed to print notification: {:?}", e); } From 6e15faf68a2b1af57d6c94392329d148882d1650 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Mon, 10 Feb 2020 19:55:49 +0100 Subject: [PATCH 0283/1250] Querify object_safety_violations. --- src/librustc/query/mod.rs | 3 + src/librustc/traits/mod.rs | 132 +++++++++++++++ .../infer/error_reporting/mod.rs | 3 +- .../traits/error_reporting/mod.rs | 5 +- .../traits/error_reporting/suggestions.rs | 3 +- src/librustc_infer/traits/mod.rs | 3 +- src/librustc_infer/traits/object_safety.rs | 151 ++---------------- src/librustc_typeck/check/cast.rs | 3 +- src/librustc_typeck/check/coercion.rs | 3 +- src/librustc_typeck/check/wfcheck.rs | 2 +- 10 files changed, 154 insertions(+), 154 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5e279975d15..df08501f007 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -656,6 +656,9 @@ rustc_queries! { query is_object_safe(key: DefId) -> bool { desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) } } + query object_safety_violations(key: DefId) -> Vec { + desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) } + } /// Gets the ParameterEnvironment for a given item; this environment /// will be in "user-facing" mode, meaning that it is suitabe for diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c000aa7c25e..de2ec53e51e 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -16,8 +16,10 @@ use crate::ty::{self, AdtKind, List, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::{Span, DUMMY_SP}; +use smallvec::SmallVec; use syntax::ast; +use std::borrow::Cow; use std::fmt::Debug; use std::rc::Rc; @@ -737,3 +739,133 @@ where tcx: TyCtxt<'tcx>, ) -> Option; } + +#[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum ObjectSafetyViolation { + /// `Self: Sized` declared on the trait. + SizedSelf(SmallVec<[Span; 1]>), + + /// Supertrait reference references `Self` an in illegal location + /// (e.g., `trait Foo : Bar`). + SupertraitSelf(SmallVec<[Span; 1]>), + + /// Method has something illegal. + Method(ast::Name, MethodViolationCode, Span), + + /// Associated const. + AssocConst(ast::Name, Span), +} + +impl ObjectSafetyViolation { + pub fn error_msg(&self) -> Cow<'static, str> { + match *self { + ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), + ObjectSafetyViolation::SupertraitSelf(ref spans) => { + if spans.iter().any(|sp| *sp != DUMMY_SP) { + "it uses `Self` as a type parameter in this".into() + } else { + "it cannot use `Self` as a type parameter in a supertrait or `where`-clause" + .into() + } + } + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { + format!("associated function `{}` has no `self` parameter", name).into() + } + ObjectSafetyViolation::Method( + name, + MethodViolationCode::ReferencesSelfInput(_), + DUMMY_SP, + ) => format!("method `{}` references the `Self` type in its parameters", name).into(), + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => { + format!("method `{}` references the `Self` type in this parameter", name).into() + } + ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => { + format!("method `{}` references the `Self` type in its return type", name).into() + } + ObjectSafetyViolation::Method( + name, + MethodViolationCode::WhereClauseReferencesSelf, + _, + ) => { + format!("method `{}` references the `Self` type in its `where` clause", name).into() + } + ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => { + format!("method `{}` has generic type parameters", name).into() + } + ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { + format!("method `{}`'s `self` parameter cannot be dispatched on", name).into() + } + ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => { + format!("it contains associated `const` `{}`", name).into() + } + ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), + } + } + + pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> { + Some(match *self { + ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => { + return None; + } + ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => ( + format!( + "consider turning `{}` into a method by giving it a `&self` argument or \ + constraining it so it does not apply to trait objects", + name + ), + sugg.map(|(sugg, sp)| (sugg.to_string(), sp)), + ), + ObjectSafetyViolation::Method( + name, + MethodViolationCode::UndispatchableReceiver, + span, + ) => ( + format!("consider changing method `{}`'s `self` parameter to be `&self`", name) + .into(), + Some(("&Self".to_string(), span)), + ), + ObjectSafetyViolation::AssocConst(name, _) + | ObjectSafetyViolation::Method(name, ..) => { + (format!("consider moving `{}` to another trait", name), None) + } + }) + } + + pub fn spans(&self) -> SmallVec<[Span; 1]> { + // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so + // diagnostics use a `note` instead of a `span_label`. + match self { + ObjectSafetyViolation::SupertraitSelf(spans) + | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), + ObjectSafetyViolation::AssocConst(_, span) + | ObjectSafetyViolation::Method(_, _, span) + if *span != DUMMY_SP => + { + smallvec![*span] + } + _ => smallvec![], + } + } +} + +/// Reasons a method might not be object-safe. +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] +pub enum MethodViolationCode { + /// e.g., `fn foo()` + StaticMethod(Option<(&'static str, Span)>), + + /// e.g., `fn foo(&self, x: Self)` + ReferencesSelfInput(usize), + + /// e.g., `fn foo(&self) -> Self` + ReferencesSelfOutput, + + /// e.g., `fn foo(&self) where Self: Clone` + WhereClauseReferencesSelf, + + /// e.g., `fn foo()` + Generic, + + /// the method's receiver (`self` argument) can't be dispatched on + UndispatchableReceiver, +} diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 77119b8618f..243feb16237 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -52,7 +52,6 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa use crate::infer::opaque_types; use crate::infer::{self, SuppressRegionErrors}; use crate::traits::error_reporting::report_object_safety_error; -use crate::traits::object_safety_violations; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, }; @@ -1618,7 +1617,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let failure_code = trace.cause.as_failure_code(terr); let mut diag = match failure_code { FailureCode::Error0038(did) => { - let violations = object_safety_violations(self.tcx, did); + let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } FailureCode::Error0317(failure_str) => { diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 4bc8ffc3d2f..2fc7c178977 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -12,7 +12,6 @@ use super::{ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, TyCtxtInferExt}; -use crate::traits::object_safety_violations; use rustc::mir::interpret::ErrorHandled; use rustc::session::DiagnosticMessageId; use rustc::ty::error::ExpectedFound; @@ -748,7 +747,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = object_safety_violations(self.tcx, trait_def_id); + let violations = self.tcx.object_safety_violations(trait_def_id); report_object_safety_error(self.tcx, span, trait_def_id, violations) } @@ -912,7 +911,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } TraitNotObjectSafe(did) => { - let violations = object_safety_violations(self.tcx, did); + let violations = self.tcx.object_safety_violations(did); report_object_safety_error(self.tcx, span, did, violations) } diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index 50ae7c4fbbf..f1206ddf909 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -5,7 +5,6 @@ use super::{ use crate::infer::InferCtxt; use crate::traits::error_reporting::suggest_constraining_type_param; -use crate::traits::object_safety::object_safety_violations; use rustc::ty::TypeckTables; use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; @@ -587,7 +586,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // If the `dyn Trait` is not object safe, do not suggest `Box`. predicates .principal_def_id() - .map_or(true, |def_id| object_safety_violations(self.tcx, def_id).is_empty()) + .map_or(true, |def_id| self.tcx.object_safety_violations(def_id).is_empty()) } // We only want to suggest `impl Trait` to `dyn Trait`s. // For example, `fn foo() -> str` needs to be filtered out. diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 06c6d651813..64bc9f2cb92 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -47,7 +47,6 @@ pub use self::engine::{TraitEngine, TraitEngineExt}; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; -pub use self::object_safety::object_safety_violations; pub use self::object_safety::MethodViolationCode; pub use self::object_safety::ObjectSafetyViolation; pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; @@ -636,8 +635,8 @@ impl<'tcx> TraitObligation<'tcx> { } pub fn provide(providers: &mut ty::query::Providers<'_>) { + object_safety::provide(providers); *providers = ty::query::Providers { - is_object_safe: object_safety::is_object_safe_provider, specialization_graph_of: specialize::specialization_graph_provider, specializes: specialize::specializes, codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index d36d66e4e25..f409c22831f 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -19,142 +19,12 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_session::lint::builtin::WHERE_CLAUSES_OBJECT_SAFETY; use rustc_span::symbol::Symbol; -use rustc_span::{Span, DUMMY_SP}; -use smallvec::{smallvec, SmallVec}; -use syntax::ast; +use rustc_span::Span; +use smallvec::SmallVec; -use std::borrow::Cow; -use std::iter::{self}; +use std::iter; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum ObjectSafetyViolation { - /// `Self: Sized` declared on the trait. - SizedSelf(SmallVec<[Span; 1]>), - - /// Supertrait reference references `Self` an in illegal location - /// (e.g., `trait Foo : Bar`). - SupertraitSelf(SmallVec<[Span; 1]>), - - /// Method has something illegal. - Method(ast::Name, MethodViolationCode, Span), - - /// Associated const. - AssocConst(ast::Name, Span), -} - -impl ObjectSafetyViolation { - pub fn error_msg(&self) -> Cow<'static, str> { - match *self { - ObjectSafetyViolation::SizedSelf(_) => "it requires `Self: Sized`".into(), - ObjectSafetyViolation::SupertraitSelf(ref spans) => { - if spans.iter().any(|sp| *sp != DUMMY_SP) { - "it uses `Self` as a type parameter in this".into() - } else { - "it cannot use `Self` as a type parameter in a supertrait or `where`-clause" - .into() - } - } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(_), _) => { - format!("associated function `{}` has no `self` parameter", name).into() - } - ObjectSafetyViolation::Method( - name, - MethodViolationCode::ReferencesSelfInput(_), - DUMMY_SP, - ) => format!("method `{}` references the `Self` type in its parameters", name).into(), - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfInput(_), _) => { - format!("method `{}` references the `Self` type in this parameter", name).into() - } - ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelfOutput, _) => { - format!("method `{}` references the `Self` type in its return type", name).into() - } - ObjectSafetyViolation::Method( - name, - MethodViolationCode::WhereClauseReferencesSelf, - _, - ) => { - format!("method `{}` references the `Self` type in its `where` clause", name).into() - } - ObjectSafetyViolation::Method(name, MethodViolationCode::Generic, _) => { - format!("method `{}` has generic type parameters", name).into() - } - ObjectSafetyViolation::Method(name, MethodViolationCode::UndispatchableReceiver, _) => { - format!("method `{}`'s `self` parameter cannot be dispatched on", name).into() - } - ObjectSafetyViolation::AssocConst(name, DUMMY_SP) => { - format!("it contains associated `const` `{}`", name).into() - } - ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(), - } - } - - pub fn solution(&self) -> Option<(String, Option<(String, Span)>)> { - Some(match *self { - ObjectSafetyViolation::SizedSelf(_) | ObjectSafetyViolation::SupertraitSelf(_) => { - return None; - } - ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod(sugg), _) => ( - format!( - "consider turning `{}` into a method by giving it a `&self` argument or \ - constraining it so it does not apply to trait objects", - name - ), - sugg.map(|(sugg, sp)| (sugg.to_string(), sp)), - ), - ObjectSafetyViolation::Method( - name, - MethodViolationCode::UndispatchableReceiver, - span, - ) => ( - format!("consider changing method `{}`'s `self` parameter to be `&self`", name) - .into(), - Some(("&Self".to_string(), span)), - ), - ObjectSafetyViolation::AssocConst(name, _) - | ObjectSafetyViolation::Method(name, ..) => { - (format!("consider moving `{}` to another trait", name), None) - } - }) - } - - pub fn spans(&self) -> SmallVec<[Span; 1]> { - // When `span` comes from a separate crate, it'll be `DUMMY_SP`. Treat it as `None` so - // diagnostics use a `note` instead of a `span_label`. - match self { - ObjectSafetyViolation::SupertraitSelf(spans) - | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(), - ObjectSafetyViolation::AssocConst(_, span) - | ObjectSafetyViolation::Method(_, _, span) - if *span != DUMMY_SP => - { - smallvec![*span] - } - _ => smallvec![], - } - } -} - -/// Reasons a method might not be object-safe. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum MethodViolationCode { - /// e.g., `fn foo()` - StaticMethod(Option<(&'static str, Span)>), - - /// e.g., `fn foo(&self, x: Self)` - ReferencesSelfInput(usize), - - /// e.g., `fn foo(&self) -> Self` - ReferencesSelfOutput, - - /// e.g., `fn foo(&self) where Self: Clone` - WhereClauseReferencesSelf, - - /// e.g., `fn foo()` - Generic, - - /// the method's receiver (`self` argument) can't be dispatched on - UndispatchableReceiver, -} +pub use crate::traits::{MethodViolationCode, ObjectSafetyViolation}; /// Returns the object safety violations that affect /// astconv -- currently, `Self` in supertraits. This is needed @@ -176,10 +46,7 @@ pub fn astconv_object_safety_violations( violations } -pub fn object_safety_violations( - tcx: TyCtxt<'_>, - trait_def_id: DefId, -) -> Vec { +fn object_safety_violations(tcx: TyCtxt<'_>, trait_def_id: DefId) -> Vec { debug_assert!(tcx.generics_of(trait_def_id).has_self); debug!("object_safety_violations: {:?}", trait_def_id); @@ -905,6 +772,10 @@ fn contains_illegal_self_type_reference<'tcx>( error } -pub(super) fn is_object_safe_provider(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { - object_safety_violations(tcx, trait_def_id).is_empty() +fn is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { + tcx.object_safety_violations(trait_def_id).is_empty() +} + +pub fn provide(providers: &mut ty::query::Providers<'_>) { + *providers = ty::query::Providers { is_object_safe, object_safety_violations, ..*providers }; } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 18f6a78804b..a67ceb856ce 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -45,7 +45,6 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::traits; use rustc_infer::traits::error_reporting::report_object_safety_error; -use rustc_infer::traits::object_safety_violations; use rustc_span::Span; use syntax::ast; @@ -517,7 +516,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { } fn report_object_unsafe_cast(&self, fcx: &FnCtxt<'a, 'tcx>, did: DefId) { - let violations = object_safety_violations(fcx.tcx, did); + let violations = fcx.tcx.object_safety_violations(did); let mut err = report_object_safety_error(fcx.tcx, self.cast_span, did, violations); err.note(&format!("required by cast to type '{}'", fcx.ty_to_string(self.cast_ty))); err.emit(); diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index c327a7996b6..3720b74d92e 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -66,7 +66,6 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::object_safety_violations; use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; @@ -1404,7 +1403,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { // Are of this `impl Trait`'s traits object safe? is_object_safe = bounds.iter().all(|bound| { bound.trait_def_id().map_or(false, |def_id| { - object_safety_violations(fcx.tcx, def_id).is_empty() + fcx.tcx.object_safety_violations(def_id).is_empty() }) }) } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4ffc3bf8e78..12e6087dbaf 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -223,7 +223,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem _ => {} } if !trait_should_be_self.is_empty() { - if rustc_infer::traits::object_safety_violations(tcx, trait_def_id).is_empty() { + if tcx.object_safety_violations(trait_def_id).is_empty() { return; } let sugg = trait_should_be_self.iter().map(|span| (*span, "Self".to_string())).collect(); From 3a55e8875e1c5f4b12954fc939efa76bc9da0a8c Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 17 Feb 2020 11:01:52 -0800 Subject: [PATCH 0284/1250] configure: set LLVM flags with a value Rather than a boolean `--enable-cflags` etc., these options should reflect that they are for LLVM, and that they need a value. You would now use `./configure --llvm-cflags="..."`. --- src/bootstrap/configure.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 3d2eead6788..2a46c563d1f 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -62,9 +62,9 @@ def v(*args): o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") -o("cflags", "llvm.cflags", "build LLVM with these extra compiler flags") -o("cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") -o("ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") +v("llvm-cflags", "llvm.cflags", "build LLVM with these extra compiler flags") +v("llvm-cxxflags", "llvm.cxxflags", "build LLVM with these extra compiler flags") +v("llvm-ldflags", "llvm.ldflags", "build LLVM with these extra linker flags") o("llvm-libunwind", "rust.llvm-libunwind", "use LLVM libunwind") From d33b3562e5e888eaffd2f8f1af08ca2afdbe542c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Feb 2020 16:47:24 +0300 Subject: [PATCH 0285/1250] parser: Do not call `bump` recursively Token normalization is merged directly into `bump`. Special "unknown macro variable" diagnostic for unexpected `$`s is removed as preventing legal code from compiling. --- src/librustc_expand/mbe/macro_parser.rs | 2 - src/librustc_expand/mbe/macro_rules.rs | 1 - src/librustc_parse/parser/mod.rs | 75 +++++++++++-------------- src/test/ui/issues/issue-6596-1.rs | 2 +- src/test/ui/issues/issue-6596-1.stderr | 4 +- src/test/ui/issues/issue-6596-2.rs | 2 +- src/test/ui/issues/issue-6596-2.stderr | 4 +- 7 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 5bf7602ea6e..6599e92222c 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -856,8 +856,6 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal { if name == sym::tt { return token::NtTT(p.parse_token_tree()); } - // check at the beginning and the parser checks after each bump - p.process_potential_macro_variable(); match parse_nt_inner(p, sp, name) { Ok(nt) => nt, Err(mut err) => { diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index f3c827b1816..52e581e30f5 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -267,7 +267,6 @@ fn generic_extension<'cx>( cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; - p.process_potential_macro_variable(); // Let the context choose how to interpret the result. // Weird, but useful for X-macros. return Box::new(ParserAnyMacro { diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 79944dc35e5..4f96d33b83f 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -404,7 +404,8 @@ impl<'a> Parser<'a> { subparser_name, }; - parser.token = parser.next_tok(); + // Make parser point to the first token. + parser.bump(); if let Some(directory) = directory { parser.directory = directory; @@ -418,7 +419,6 @@ impl<'a> Parser<'a> { } } - parser.process_potential_macro_variable(); parser } @@ -430,7 +430,7 @@ impl<'a> Parser<'a> { self.unnormalized_prev_token.as_ref().unwrap_or(&self.prev_token) } - fn next_tok(&mut self) -> Token { + fn next_tok(&mut self, fallback_span: Span) -> Token { let mut next = if self.desugar_doc_comments { self.token_cursor.next_desugared() } else { @@ -438,7 +438,7 @@ impl<'a> Parser<'a> { }; if next.span.is_dummy() { // Tweak the location for better diagnostics, but keep syntactic context intact. - next.span = self.unnormalized_token().span.with_ctxt(next.span.ctxt()); + next.span = fallback_span.with_ctxt(next.span.ctxt()); } next } @@ -896,6 +896,24 @@ impl<'a> Parser<'a> { self.parse_delim_comma_seq(token::Paren, f) } + // Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`) + // tokens are replaced with usual identifier and lifetime tokens, + // so the former are never encountered during normal parsing. + fn normalize_token(token: &Token) -> Option { + match &token.kind { + token::Interpolated(nt) => match **nt { + token::NtIdent(ident, is_raw) => { + Some(Token::new(token::Ident(ident.name, is_raw), ident.span)) + } + token::NtLifetime(ident) => { + Some(Token::new(token::Lifetime(ident.name), ident.span)) + } + _ => None, + }, + _ => None, + } + } + /// Advance the parser by one token. pub fn bump(&mut self) { if self.prev_token.kind == TokenKind::Eof { @@ -905,16 +923,17 @@ impl<'a> Parser<'a> { } // Update the current and previous tokens. - let next_token = self.next_tok(); - self.prev_token = mem::replace(&mut self.token, next_token); + self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); + self.token = self.next_tok(self.unnormalized_prev_token().span); + if let Some(normalized_token) = Self::normalize_token(&self.token) { + self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); + } // Update fields derived from the previous token. self.prev_span = self.unnormalized_prev_token().span; self.expected_tokens.clear(); - // Check after each token. - self.process_potential_macro_variable(); } /// Advances the parser using provided token as a next one. Use this when @@ -924,9 +943,12 @@ impl<'a> Parser<'a> { /// Correct token kinds and spans need to be calculated instead. fn bump_with(&mut self, next: TokenKind, span: Span) { // Update the current and previous tokens. - let next_token = Token::new(next, span); - self.prev_token = mem::replace(&mut self.token, next_token); + self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); + self.token = Token::new(next, span); + if let Some(normalized_token) = Self::normalize_token(&self.token) { + self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); + } // Update fields derived from the previous token. self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo()); @@ -1066,39 +1088,6 @@ impl<'a> Parser<'a> { } } - pub fn process_potential_macro_variable(&mut self) { - let normalized_token = match self.token.kind { - token::Dollar - if self.token.span.from_expansion() && self.look_ahead(1, |t| t.is_ident()) => - { - self.bump(); - let name = match self.token.kind { - token::Ident(name, _) => name, - _ => unreachable!(), - }; - let span = self.prev_span.to(self.token.span); - self.struct_span_err(span, &format!("unknown macro variable `{}`", name)) - .span_label(span, "unknown macro variable") - .emit(); - self.bump(); - return; - } - token::Interpolated(ref nt) => { - // Interpolated identifier and lifetime tokens are replaced with usual identifier - // and lifetime tokens, so the former are never encountered during normal parsing. - match **nt { - token::NtIdent(ident, is_raw) => { - Token::new(token::Ident(ident.name, is_raw), ident.span) - } - token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span), - _ => return, - } - } - _ => return, - }; - self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); - } - /// Parses a single token tree from the input. pub fn parse_token_tree(&mut self) -> TokenTree { match self.token.kind { diff --git a/src/test/ui/issues/issue-6596-1.rs b/src/test/ui/issues/issue-6596-1.rs index 5da54451346..25f1d650072 100644 --- a/src/test/ui/issues/issue-6596-1.rs +++ b/src/test/ui/issues/issue-6596-1.rs @@ -1,7 +1,7 @@ macro_rules! e { ($inp:ident) => ( $nonexistent - //~^ ERROR unknown macro variable `nonexistent` + //~^ ERROR expected expression, found `$` ); } diff --git a/src/test/ui/issues/issue-6596-1.stderr b/src/test/ui/issues/issue-6596-1.stderr index 4f29d8a9274..216fe6472a5 100644 --- a/src/test/ui/issues/issue-6596-1.stderr +++ b/src/test/ui/issues/issue-6596-1.stderr @@ -1,8 +1,8 @@ -error: unknown macro variable `nonexistent` +error: expected expression, found `$` --> $DIR/issue-6596-1.rs:3:9 | LL | $nonexistent - | ^^^^^^^^^^^^ unknown macro variable + | ^^^^^^^^^^^^ expected expression ... LL | e!(foo); | -------- in this macro invocation diff --git a/src/test/ui/issues/issue-6596-2.rs b/src/test/ui/issues/issue-6596-2.rs index b19700efe5a..8f7c98d9a67 100644 --- a/src/test/ui/issues/issue-6596-2.rs +++ b/src/test/ui/issues/issue-6596-2.rs @@ -3,7 +3,7 @@ macro_rules! g { ($inp:ident) => ( { $inp $nonexistent } - //~^ ERROR unknown macro variable `nonexistent` + //~^ ERROR expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$` ); } diff --git a/src/test/ui/issues/issue-6596-2.stderr b/src/test/ui/issues/issue-6596-2.stderr index 4fcb0176faa..3d13c64f762 100644 --- a/src/test/ui/issues/issue-6596-2.stderr +++ b/src/test/ui/issues/issue-6596-2.stderr @@ -1,8 +1,8 @@ -error: unknown macro variable `nonexistent` +error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$` --> $DIR/issue-6596-2.rs:5:16 | LL | { $inp $nonexistent } - | ^^^^^^^^^^^^ unknown macro variable + | ^^^^^^^^^^^^ expected one of 8 possible tokens ... LL | g!(foo); | -------- in this macro invocation From ed2fd28d385c1cc9b2ab3e91513b4d2ffc612671 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Feb 2020 21:36:50 +0300 Subject: [PATCH 0286/1250] parser: Set previous and unnormalized tokens in couple more places --- src/librustc_parse/lib.rs | 1 + src/librustc_parse/parser/item.rs | 7 ++++--- src/librustc_parse/parser/mod.rs | 8 ++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 4aad2c0f68a..40d7a34a8b0 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -172,6 +172,7 @@ fn maybe_source_file_to_parser( parser.unclosed_delims = unclosed_delims; if parser.token == token::Eof && parser.token.span.is_dummy() { parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); + assert!(parser.unnormalized_token.is_none()); } Ok(parser) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d7b8d9778f0..5dc50a0cf2f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1400,8 +1400,9 @@ impl<'a> Parser<'a> { } fn report_invalid_macro_expansion_item(&self, args: &MacArgs) { + let span = args.span().expect("undelimited macro call"); let mut err = self.struct_span_err( - self.prev_span, + span, "macros that expand to items must be delimited with braces or followed by a semicolon", ); if self.unclosed_delims.is_empty() { @@ -1416,14 +1417,14 @@ impl<'a> Parser<'a> { ); } else { err.span_suggestion( - self.prev_span, + span, "change the delimiters to curly braces", " { /* items */ }".to_string(), Applicability::HasPlaceholders, ); } err.span_suggestion( - self.prev_span.shrink_to_hi(), + span.shrink_to_hi(), "add a semicolon", ';'.to_string(), Applicability::MaybeIncorrect, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 4f96d33b83f..e04cfa37468 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -95,7 +95,7 @@ pub struct Parser<'a> { /// The current non-normalized token if it's different from `token`. /// Preferable use is through the `unnormalized_token()` getter. /// Use span from this token if you need to concatenate it with some neighbouring spans. - unnormalized_token: Option, + pub unnormalized_token: Option, /// The previous normalized token. /// Use span from this token if you need an isolated span. prev_token: Token, @@ -1096,15 +1096,15 @@ impl<'a> Parser<'a> { &mut self.token_cursor.frame, self.token_cursor.stack.pop().unwrap(), ); - self.token.span = frame.span.entire(); + self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close); + self.unnormalized_token = None; self.bump(); TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream.into()) } token::CloseDelim(_) | token::Eof => unreachable!(), _ => { - let token = self.token.clone(); self.bump(); - TokenTree::Token(token) + TokenTree::Token(self.prev_token.clone()) } } } From 06fbb0b4faefeaf70f4616d6af9bc0c1ebc69bc2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 16 Feb 2020 23:19:51 +0300 Subject: [PATCH 0287/1250] parser: Remove `Option`s from unnormalized tokens They are always set synchronously with normalized tokens now --- src/librustc_parse/lib.rs | 8 ++--- src/librustc_parse/parser/expr.rs | 4 +-- src/librustc_parse/parser/mod.rs | 55 +++++++++++-------------------- src/librustc_parse/parser/path.rs | 2 +- 4 files changed, 26 insertions(+), 43 deletions(-) diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 40d7a34a8b0..a0b8415b3e1 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -9,7 +9,7 @@ use rustc_errors::{Diagnostic, FatalError, Level, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; use syntax::ast; -use syntax::token::{self, Nonterminal}; +use syntax::token::{self, Nonterminal, Token}; use syntax::tokenstream::{self, TokenStream, TokenTree}; use std::path::{Path, PathBuf}; @@ -170,9 +170,9 @@ fn maybe_source_file_to_parser( let (stream, unclosed_delims) = maybe_file_to_stream(sess, source_file, None)?; let mut parser = stream_to_parser(sess, stream, None); parser.unclosed_delims = unclosed_delims; - if parser.token == token::Eof && parser.token.span.is_dummy() { - parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); - assert!(parser.unnormalized_token.is_none()); + if parser.token == token::Eof { + let span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); + parser.set_token(Token::new(token::Eof, span)); } Ok(parser) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 51822ab2ea5..97daa91eed1 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -166,7 +166,7 @@ impl<'a> Parser<'a> { while let Some(op) = self.check_assoc_op() { // Adjust the span for interpolated LHS to point to the `$lhs` token // and not to what it refers to. - let lhs_span = match self.unnormalized_prev_token().kind { + let lhs_span = match self.unnormalized_prev_token.kind { TokenKind::Interpolated(..) => self.prev_span, _ => lhs.span, }; @@ -527,7 +527,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, (Span, P)> { expr.map(|e| { ( - match self.unnormalized_prev_token().kind { + match self.unnormalized_prev_token.kind { TokenKind::Interpolated(..) => self.prev_span, _ => e.span, }, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index e04cfa37468..937e5e3cd69 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -93,18 +93,16 @@ pub struct Parser<'a> { /// Use span from this token if you need an isolated span. pub token: Token, /// The current non-normalized token if it's different from `token`. - /// Preferable use is through the `unnormalized_token()` getter. /// Use span from this token if you need to concatenate it with some neighbouring spans. - pub unnormalized_token: Option, + unnormalized_token: Token, /// The previous normalized token. /// Use span from this token if you need an isolated span. prev_token: Token, /// The previous non-normalized token if it's different from `prev_token`. - /// Preferable use is through the `unnormalized_prev_token()` getter. /// Use span from this token if you need to concatenate it with some neighbouring spans. - unnormalized_prev_token: Option, - /// Equivalent to `unnormalized_prev_token().span`. - /// FIXME: Remove in favor of `(unnormalized_)prev_token().span`. + unnormalized_prev_token: Token, + /// Equivalent to `unnormalized_prev_token.span`. + /// FIXME: Remove in favor of `(unnormalized_)prev_token.span`. pub prev_span: Span, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. @@ -378,9 +376,9 @@ impl<'a> Parser<'a> { let mut parser = Parser { sess, token: Token::dummy(), - unnormalized_token: None, + unnormalized_token: Token::dummy(), prev_token: Token::dummy(), - unnormalized_prev_token: None, + unnormalized_prev_token: Token::dummy(), prev_span: DUMMY_SP, restrictions: Restrictions::empty(), recurse_into_file_modules, @@ -422,14 +420,6 @@ impl<'a> Parser<'a> { parser } - fn unnormalized_token(&self) -> &Token { - self.unnormalized_token.as_ref().unwrap_or(&self.token) - } - - fn unnormalized_prev_token(&self) -> &Token { - self.unnormalized_prev_token.as_ref().unwrap_or(&self.prev_token) - } - fn next_tok(&mut self, fallback_span: Span) -> Token { let mut next = if self.desugar_doc_comments { self.token_cursor.next_desugared() @@ -899,18 +889,17 @@ impl<'a> Parser<'a> { // Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`) // tokens are replaced with usual identifier and lifetime tokens, // so the former are never encountered during normal parsing. - fn normalize_token(token: &Token) -> Option { - match &token.kind { + crate fn set_token(&mut self, token: Token) { + self.unnormalized_token = token; + self.token = match &self.unnormalized_token.kind { token::Interpolated(nt) => match **nt { token::NtIdent(ident, is_raw) => { - Some(Token::new(token::Ident(ident.name, is_raw), ident.span)) + Token::new(token::Ident(ident.name, is_raw), ident.span) } - token::NtLifetime(ident) => { - Some(Token::new(token::Lifetime(ident.name), ident.span)) - } - _ => None, + token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span), + _ => self.unnormalized_token.clone(), }, - _ => None, + _ => self.unnormalized_token.clone(), } } @@ -925,13 +914,11 @@ impl<'a> Parser<'a> { // Update the current and previous tokens. self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); - self.token = self.next_tok(self.unnormalized_prev_token().span); - if let Some(normalized_token) = Self::normalize_token(&self.token) { - self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); - } + let next_token = self.next_tok(self.unnormalized_prev_token.span); + self.set_token(next_token); // Update fields derived from the previous token. - self.prev_span = self.unnormalized_prev_token().span; + self.prev_span = self.unnormalized_prev_token.span; self.expected_tokens.clear(); } @@ -945,13 +932,10 @@ impl<'a> Parser<'a> { // Update the current and previous tokens. self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); - self.token = Token::new(next, span); - if let Some(normalized_token) = Self::normalize_token(&self.token) { - self.unnormalized_token = Some(mem::replace(&mut self.token, normalized_token)); - } + self.set_token(Token::new(next, span)); // Update fields derived from the previous token. - self.prev_span = self.unnormalized_prev_token().span.with_hi(span.lo()); + self.prev_span = self.unnormalized_prev_token.span.with_hi(span.lo()); self.expected_tokens.clear(); } @@ -1096,8 +1080,7 @@ impl<'a> Parser<'a> { &mut self.token_cursor.frame, self.token_cursor.stack.pop().unwrap(), ); - self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close); - self.unnormalized_token = None; + self.set_token(Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close)); self.bump(); TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream.into()) } diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 761c06b70ee..18e57c6a5d4 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -134,7 +134,7 @@ impl<'a> Parser<'a> { path }); - let lo = self.unnormalized_token().span; + let lo = self.unnormalized_token.span; let mut segments = Vec::new(); let mod_sep_ctxt = self.token.span.ctxt(); if self.eat(&token::ModSep) { From 950845c5b1079c83e56db0ca2b4bb8fe050ee2f5 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 17 Feb 2020 22:47:40 +0300 Subject: [PATCH 0288/1250] Add a test for proc macro generating `$ IDENT` --- .../auxiliary/generate-dollar-ident.rs | 17 +++++++++++++++++ .../ui/proc-macro/generate-dollar-ident.rs | 18 ++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs create mode 100644 src/test/ui/proc-macro/generate-dollar-ident.rs diff --git a/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs b/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs new file mode 100644 index 00000000000..c9f0664c3a3 --- /dev/null +++ b/src/test/ui/proc-macro/auxiliary/generate-dollar-ident.rs @@ -0,0 +1,17 @@ +// force-host +// no-prefer-dynamic + +#![feature(proc_macro_hygiene)] +#![feature(proc_macro_quote)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::*; + +#[proc_macro] +pub fn dollar_ident(input: TokenStream) -> TokenStream { + let black_hole = input.into_iter().next().unwrap(); + quote! { + $black_hole!($$var); + } +} diff --git a/src/test/ui/proc-macro/generate-dollar-ident.rs b/src/test/ui/proc-macro/generate-dollar-ident.rs new file mode 100644 index 00000000000..b838be9fb9f --- /dev/null +++ b/src/test/ui/proc-macro/generate-dollar-ident.rs @@ -0,0 +1,18 @@ +// Proc macros can generate token sequence `$ IDENT` +// without it being recognized as an unknown macro variable. + +// check-pass +// aux-build:generate-dollar-ident.rs + +extern crate generate_dollar_ident; +use generate_dollar_ident::*; + +macro_rules! black_hole { + ($($tt:tt)*) => {}; +} + +black_hole!($var); + +dollar_ident!(black_hole); + +fn main() {} From c9b87ac4b306cf43ca6e46defb91267fe257e45b Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 17 Feb 2020 21:44:32 +0100 Subject: [PATCH 0289/1250] Don't eliminate frame pointers on thumb targets --- src/librustc_target/spec/thumb_base.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index 204f4723b70..6ab6fcb58bd 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -50,6 +50,9 @@ pub fn opts() -> TargetOptions { // until we figure a way to add the pretty printers without requiring a volatile load cf. // rust-lang/rust#44993. emit_debug_gdb_scripts: false, + // LLVM is eager to trash the link register when calling `nounwind` functions, which + // breaks debugging. Preserve LR by default to prevent that from happening. + eliminate_frame_pointer: false, ..Default::default() } } From 9d423950cc141e110242ff1973f2d7b84c719a86 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 17 Feb 2020 13:39:50 -0800 Subject: [PATCH 0290/1250] Use doc comment for explanation of `shared_borrow_allows_mutation` --- .../dataflow/impls/borrowed_locals.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 0ce37aea69d..44693c50eac 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -221,15 +221,15 @@ pub struct MutBorrow<'mir, 'tcx> { } impl MutBorrow<'mir, 'tcx> { - // `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`. - // - // This assumes that it is UB to take the address of a struct field whose type is - // `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of - // that same struct whose type is `!Freeze`. If we decide that this is not UB, we will - // have to check the type of the borrowed **local** instead of the borrowed **place** - // below. See [rust-lang/unsafe-code-guidelines#134]. - // - // [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 + /// `&` and `&raw` only allow mutation if the borrowed place is `!Freeze`. + /// + /// This assumes that it is UB to take the address of a struct field whose type is + /// `Freeze`, then use pointer arithmetic to derive a pointer to a *different* field of + /// that same struct whose type is `!Freeze`. If we decide that this is not UB, we will + /// have to check the type of the borrowed **local** instead of the borrowed **place** + /// below. See [rust-lang/unsafe-code-guidelines#134]. + /// + /// [rust-lang/unsafe-code-guidelines#134]: https://github.com/rust-lang/unsafe-code-guidelines/issues/134 fn shared_borrow_allows_mutation(&self, place: &Place<'tcx>) -> bool { !place.ty(self.body, self.tcx).ty.is_freeze(self.tcx, self.param_env, DUMMY_SP) } From 077a93c6a9b1c8ee0e541ea484f7e13c207d50d0 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 17 Feb 2020 13:43:13 -0800 Subject: [PATCH 0291/1250] Fix typo in comment --- src/librustc_mir/dataflow/impls/borrowed_locals.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/dataflow/impls/borrowed_locals.rs b/src/librustc_mir/dataflow/impls/borrowed_locals.rs index 44693c50eac..95a676c0892 100644 --- a/src/librustc_mir/dataflow/impls/borrowed_locals.rs +++ b/src/librustc_mir/dataflow/impls/borrowed_locals.rs @@ -62,7 +62,7 @@ impl MaybeBorrowedLocals { /// /// In some contexts, we know that this borrow will never occur. For example, during /// const-eval, custom drop glue cannot be run. Code that calls this should document the - /// assumptions that justify `Drop` terminators in this way. + /// assumptions that justify ignoring `Drop` terminators in this way. /// /// [#61069]: https://github.com/rust-lang/rust/pull/61069 pub fn unsound_ignore_borrow_on_drop(self) -> Self { From 27cfb2b9c2baacc7110cd73a96d0989b73e2a597 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 18 Feb 2020 00:00:06 +0100 Subject: [PATCH 0292/1250] Fix typo --- src/librustc_target/spec/thumb_base.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_target/spec/thumb_base.rs b/src/librustc_target/spec/thumb_base.rs index 6ab6fcb58bd..99ab996be95 100644 --- a/src/librustc_target/spec/thumb_base.rs +++ b/src/librustc_target/spec/thumb_base.rs @@ -50,7 +50,7 @@ pub fn opts() -> TargetOptions { // until we figure a way to add the pretty printers without requiring a volatile load cf. // rust-lang/rust#44993. emit_debug_gdb_scripts: false, - // LLVM is eager to trash the link register when calling `nounwind` functions, which + // LLVM is eager to trash the link register when calling `noreturn` functions, which // breaks debugging. Preserve LR by default to prevent that from happening. eliminate_frame_pointer: false, ..Default::default() From ab906179ccd6254f51f0d254479c9b211b0276b1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2020 15:42:11 +1100 Subject: [PATCH 0293/1250] Always inline `run_utf8_validation`. It only has two call sites, and the one within `from_utf8` is hot within rustc itself. --- src/libcore/str/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 734b3ba7c6b..a943e49c3e2 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1499,7 +1499,7 @@ fn contains_nonascii(x: usize) -> bool { /// Walks through `v` checking that it's a valid UTF-8 sequence, /// returning `Ok(())` in that case, or, if it is invalid, `Err(err)`. -#[inline] +#[inline(always)] fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> { let mut index = 0; let len = v.len(); From c02d689a626d44e82f3769d8be1a842f2d211005 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2020 16:00:58 +1100 Subject: [PATCH 0294/1250] Inline `Symbol::decode` and `Interner::intern`. --- src/librustc_span/symbol.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 1cc4a277880..b7285cc9492 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -993,6 +993,7 @@ impl Encodable for Symbol { } impl Decodable for Symbol { + #[inline] fn decode(d: &mut D) -> Result { Ok(Symbol::intern(&d.read_str()?)) } @@ -1031,6 +1032,7 @@ impl Interner { } } + #[inline] pub fn intern(&mut self, string: &str) -> Symbol { if let Some(&name) = self.names.get(string) { return name; From e761f3af904b3c275bdebc73bb29ffc45384945d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Feb 2020 16:12:24 +1100 Subject: [PATCH 0295/1250] Inline various simple `emit_*` and `read_*` methods in `Decoder`. Mostly, these are the ones whose body just contains `f(self)`. --- src/libserialize/serialize.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 19283ffc438..8c6548cd3c5 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -36,6 +36,7 @@ pub trait Encoder { fn emit_str(&mut self, v: &str) -> Result<(), Self::Error>; // Compound types: + #[inline] fn emit_enum(&mut self, _name: &str, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -57,6 +58,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -89,6 +91,7 @@ pub trait Encoder { self.emit_enum_variant_arg(f_idx, f) } + #[inline] fn emit_struct(&mut self, _name: &str, _len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -96,6 +99,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_struct_field( &mut self, _f_name: &str, @@ -108,6 +112,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_tuple(&mut self, _len: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -115,6 +120,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_tuple_arg(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -164,6 +170,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_seq_elt(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -179,6 +186,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_map_elt_key(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -186,6 +194,7 @@ pub trait Encoder { f(self) } + #[inline] fn emit_map_elt_val(&mut self, _idx: usize, f: F) -> Result<(), Self::Error> where F: FnOnce(&mut Self) -> Result<(), Self::Error>, @@ -218,6 +227,7 @@ pub trait Decoder { fn read_str(&mut self) -> Result, Self::Error>; // Compound types: + #[inline] fn read_enum(&mut self, _name: &str, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -225,6 +235,7 @@ pub trait Decoder { f(self) } + #[inline] fn read_enum_variant(&mut self, _names: &[&str], mut f: F) -> Result where F: FnMut(&mut Self, usize) -> Result, @@ -233,6 +244,7 @@ pub trait Decoder { f(self, disr) } + #[inline] fn read_enum_variant_arg(&mut self, _a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -259,6 +271,7 @@ pub trait Decoder { self.read_enum_variant_arg(f_idx, f) } + #[inline] fn read_struct(&mut self, _s_name: &str, _len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -266,6 +279,7 @@ pub trait Decoder { f(self) } + #[inline] fn read_struct_field( &mut self, _f_name: &str, @@ -278,6 +292,7 @@ pub trait Decoder { f(self) } + #[inline] fn read_tuple(&mut self, _len: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -285,6 +300,7 @@ pub trait Decoder { f(self) } + #[inline] fn read_tuple_arg(&mut self, _a_idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -328,6 +344,7 @@ pub trait Decoder { f(self, len) } + #[inline] fn read_seq_elt(&mut self, _idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -343,6 +360,7 @@ pub trait Decoder { f(self, len) } + #[inline] fn read_map_elt_key(&mut self, _idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, @@ -350,6 +368,7 @@ pub trait Decoder { f(self) } + #[inline] fn read_map_elt_val(&mut self, _idx: usize, f: F) -> Result where F: FnOnce(&mut Self) -> Result, From ee49e95e787b353c0697862ca2d703c7b9480d25 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Feb 2020 22:58:24 +0100 Subject: [PATCH 0296/1250] doc comments for layout components --- src/librustc_target/abi/mod.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 3f44339bf4c..447487e4fb2 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -871,8 +871,26 @@ impl Niche { #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct LayoutDetails { - pub variants: Variants, + /// Says where the fields are located. + /// Primitives and fieldless enums appear as unions without fields. pub fields: FieldPlacement, + + /// Encodes information about multi-variant layouts. + /// Even with `Multiple` variants, a layout can still have fields! Those are then + /// shared between all variants. One of them will be the discriminant, + /// but e.g. generators can have more. + /// + /// A layout-guided recursive descent must first look at all the fields, + /// and only then check if this is a multi-variant layout and if so, proceed + /// with the active variant. + pub variants: Variants, + + /// The `abi` defines how this data is passed between functions, and it defines + /// value restrictions via `valid_range`. + /// + /// Note that this is entirely orthogonal to the recursive structrue defined by + /// `variants` and `fields`; for example, `ManuallyDrop>` has + /// `Abi::ScalarPair`! So, having a non-`Aggregate` `abi` should not stop a recursive descent. pub abi: Abi, /// The leaf scalar with the largest number of invalid values From f8999fbdcf7bc924938d94eed1ecce337e315e93 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Feb 2020 22:59:16 +0100 Subject: [PATCH 0297/1250] miri value visitor: fix some wrong assumptions about layout; improve error messages --- src/librustc_mir/interpret/intern.rs | 7 +- src/librustc_mir/interpret/validity.rs | 181 +++++++++++------- src/librustc_mir/interpret/visitor.rs | 120 +++--------- .../consts/const-eval/transmute-const.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.stderr | 14 +- .../ui/consts/const-eval/ub-nonnull.stderr | 2 +- src/test/ui/consts/const-eval/ub-ref.stderr | 2 +- .../ui/consts/const-eval/ub-uninhabit.stderr | 6 +- .../ui/consts/const-eval/ub-upvars.stderr | 2 +- .../ui/consts/const-eval/ub-wide-ptr.stderr | 8 +- src/test/ui/consts/const-eval/union-ub.stderr | 2 +- .../validate_uninhabited_zsts.stderr | 2 +- .../ui/consts/validate_never_arrays.stderr | 6 +- 13 files changed, 174 insertions(+), 180 deletions(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 9fea82d78c9..13d5f5f6a37 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -187,7 +187,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx self.walk_aggregate(mplace, fields) } - fn visit_primitive(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> { + fn visit_value(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> { // Handle Reference types, as these are the only relocations supported by const eval. // Raw pointers (and boxes) are handled by the `leftover_relocations` logic. let ty = mplace.layout.ty; @@ -263,8 +263,11 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx None => self.ref_tracking.track((mplace, mutability, mode), || ()), } } + Ok(()) + } else { + // Not a reference -- proceed recursively. + self.walk_value(mplace) } - Ok(()) } } diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index aa2b3040a71..e90a5985677 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -201,13 +201,16 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // enums ty::Adt(def, ..) if def.is_enum() => { - // we might be projecting *to* a variant, or to a field *in*a variant. + // we might be projecting *to* a variant, or to a field *in* a variant. match layout.variants { layout::Variants::Single { index } => { // Inside a variant PathElem::Field(def.variants[index].fields[field].ident.name) } - _ => bug!(), + layout::Variants::Multiple { discr_index, .. } => { + assert_eq!(discr_index, field); + PathElem::Tag + } } } @@ -288,62 +291,6 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(()) } -} - -impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> - for ValidityVisitor<'rt, 'mir, 'tcx, M> -{ - type V = OpTy<'tcx, M::PointerTag>; - - #[inline(always)] - fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> { - &self.ecx - } - - #[inline] - fn visit_field( - &mut self, - old_op: OpTy<'tcx, M::PointerTag>, - field: usize, - new_op: OpTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - let elem = self.aggregate_field_path_elem(old_op.layout, field); - self.visit_elem(new_op, elem) - } - - #[inline] - fn visit_variant( - &mut self, - old_op: OpTy<'tcx, M::PointerTag>, - variant_id: VariantIdx, - new_op: OpTy<'tcx, M::PointerTag>, - ) -> InterpResult<'tcx> { - let name = match old_op.layout.ty.kind { - ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), - // Generators also have variants - ty::Generator(..) => PathElem::GeneratorState(variant_id), - _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), - }; - self.visit_elem(new_op, name) - } - - #[inline] - fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { - trace!("visit_value: {:?}, {:?}", *op, op.layout); - // Translate some possible errors to something nicer. - match self.walk_value(op) { - Ok(()) => Ok(()), - Err(err) => match err.kind { - err_ub!(InvalidDiscriminant(val)) => { - throw_validation_failure!(val, self.path, "a valid enum discriminant") - } - err_unsup!(ReadPointerAsBytes) => { - throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes") - } - _ => Err(err), - }, - } - } fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; @@ -421,7 +368,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> throw_validation_failure!( format_args!( "unaligned reference \ - (required {} byte alignment but found {})", + (required {} byte alignment but found {})", required.bytes(), has.bytes() ), @@ -485,16 +432,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ); // FIXME: Check if the signature matches } - // This should be all the primitive types + // This should be all the (inhabited) primitive types _ => bug!("Unexpected primitive type {}", value.layout.ty), } Ok(()) } - fn visit_uninhabited(&mut self) -> InterpResult<'tcx> { - throw_validation_failure!("a value of an uninhabited type", self.path) - } - fn visit_scalar( &mut self, op: OpTy<'tcx, M::PointerTag>, @@ -559,6 +502,116 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ) } } +} + +impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> + for ValidityVisitor<'rt, 'mir, 'tcx, M> +{ + type V = OpTy<'tcx, M::PointerTag>; + + #[inline(always)] + fn ecx(&self) -> &InterpCx<'mir, 'tcx, M> { + &self.ecx + } + + #[inline] + fn visit_field( + &mut self, + old_op: OpTy<'tcx, M::PointerTag>, + field: usize, + new_op: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + let elem = self.aggregate_field_path_elem(old_op.layout, field); + self.visit_elem(new_op, elem) + } + + #[inline] + fn visit_variant( + &mut self, + old_op: OpTy<'tcx, M::PointerTag>, + variant_id: VariantIdx, + new_op: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx> { + let name = match old_op.layout.ty.kind { + ty::Adt(adt, _) => PathElem::Variant(adt.variants[variant_id].ident.name), + // Generators also have variants + ty::Generator(..) => PathElem::GeneratorState(variant_id), + _ => bug!("Unexpected type with variant: {:?}", old_op.layout.ty), + }; + self.visit_elem(new_op, name) + } + + #[inline(always)] + fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> { + // Empty unions are not accepted by rustc. That's great, it means we can + // use that as a signal for detecting primitives. Make sure + // we did not miss any primitive. + assert!(fields > 0); + Ok(()) + } + + #[inline] + fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + trace!("visit_value: {:?}, {:?}", *op, op.layout); + + if op.layout.abi.is_uninhabited() { + // Uninhabited types do not have sensible layout, stop right here. + throw_validation_failure!( + format_args!("a value of uninhabited type {:?}", op.layout.ty), + self.path + ) + } + + // Check primitive types. We do this after checking for uninhabited types, + // to exclude fieldless enums (that also appear as fieldless unions here). + // Primitives can have varying layout, so we check them separately and before aggregate + // handling. + // It is CRITICAL that we get this check right, or we might be validating the wrong thing! + let primitive = match op.layout.fields { + // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. + // (Fieldless enums also appear here, but they are uninhabited and thus handled above.) + layout::FieldPlacement::Union(0) => true, + _ => op.layout.ty.builtin_deref(true).is_some(), + }; + if primitive { + // No need to recurse further or check scalar layout, this is a leaf type. + return self.visit_primitive(op); + } + + // Recursively walk the type. Translate some possible errors to something nicer. + match self.walk_value(op) { + Ok(()) => {} + Err(err) => match err.kind { + err_ub!(InvalidDiscriminant(val)) => { + throw_validation_failure!(val, self.path, "a valid enum discriminant") + } + err_unsup!(ReadPointerAsBytes) => { + throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes") + } + _ => return Err(err), + }, + } + + // *After* all of this, check the ABI. We need to check the ABI to handle + // types like `NonNull` where the `Scalar` info is more restrictive than what + // the fields say. But in most cases, this will just propagate what the fields say, + // and then we want the error to point at the field -- so, first recurse, + // then check ABI. + // + // FIXME: We could avoid some redundant checks here. For newtypes wrapping + // scalars, we do the same check on every "level" (e.g., first we check + // MyNewtype and then the scalar in there). + match op.layout.abi { + layout::Abi::Uninhabited => unreachable!(), // checked above + layout::Abi::Scalar(ref layout) => { + self.visit_scalar(op, layout)?; + } + // FIXME: Should we do something for ScalarPair? Vector? + _ => {} + } + + Ok(()) + } fn visit_aggregate( &mut self, diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index d2594e87071..8808fc70cf7 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -120,7 +120,7 @@ macro_rules! make_value_visitor { } /// Visits the given value as a union. No automatic recursion can happen here. #[inline(always)] - fn visit_union(&mut self, _v: Self::V) -> InterpResult<'tcx> + fn visit_union(&mut self, _v: Self::V, _fields: usize) -> InterpResult<'tcx> { Ok(()) } @@ -150,8 +150,9 @@ macro_rules! make_value_visitor { ) -> InterpResult<'tcx> { self.visit_value(new_val) } - /// Called when recursing into an enum variant. + /// This gives the visitor the chance to track the stack of nested fields that + /// we are descending through. #[inline(always)] fn visit_variant( &mut self, @@ -162,33 +163,6 @@ macro_rules! make_value_visitor { self.visit_value(new_val) } - /// Called whenever we reach a value with uninhabited layout. - /// Recursing to fields will *always* continue after this! This is not meant to control - /// whether and how we descend recursively/ into the scalar's fields if there are any, - /// it is meant to provide the chance for additional checks when a value of uninhabited - /// layout is detected. - #[inline(always)] - fn visit_uninhabited(&mut self) -> InterpResult<'tcx> - { Ok(()) } - /// Called whenever we reach a value with scalar layout. - /// We do NOT provide a `ScalarMaybeUndef` here to avoid accessing memory if the - /// visitor is not even interested in scalars. - /// Recursing to fields will *always* continue after this! This is not meant to control - /// whether and how we descend recursively/ into the scalar's fields if there are any, - /// it is meant to provide the chance for additional checks when a value of scalar - /// layout is detected. - #[inline(always)] - fn visit_scalar(&mut self, _v: Self::V, _layout: &layout::Scalar) -> InterpResult<'tcx> - { Ok(()) } - - /// Called whenever we reach a value of primitive type. There can be no recursion - /// below such a value. This is the leaf function. - /// We do *not* provide an `ImmTy` here because some implementations might want - /// to write to the place this primitive lives in. - #[inline(always)] - fn visit_primitive(&mut self, _v: Self::V) -> InterpResult<'tcx> - { Ok(()) } - // Default recursors. Not meant to be overloaded. fn walk_aggregate( &mut self, @@ -204,23 +178,10 @@ macro_rules! make_value_visitor { fn walk_value(&mut self, v: Self::V) -> InterpResult<'tcx> { trace!("walk_value: type: {}", v.layout().ty); - // If this is a multi-variant layout, we have to find the right one and proceed with - // that. - match v.layout().variants { - layout::Variants::Multiple { .. } => { - let op = v.to_op(self.ecx())?; - let idx = self.ecx().read_discriminant(op)?.1; - let inner = v.project_downcast(self.ecx(), idx)?; - trace!("walk_value: variant layout: {:#?}", inner.layout()); - // recurse with the inner type - return self.visit_variant(v, idx, inner); - } - layout::Variants::Single { .. } => {} - } - // Even for single variants, we might be able to get a more refined type: - // If it is a trait object, switch to the actual type that was used to create it. + // Special treatment for special types, where the (static) layout is not sufficient. match v.layout().ty.kind { + // If it is a trait object, switch to the real type that was used to create it. ty::Dynamic(..) => { // immediate trait objects are not a thing let dest = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); @@ -229,56 +190,16 @@ macro_rules! make_value_visitor { // recurse with the inner type return self.visit_field(v, 0, Value::from_mem_place(inner)); }, - ty::Generator(..) => { - // FIXME: Generator layout is lying: it claims a whole bunch of fields exist - // when really many of them can be uninitialized. - // Just treat them as a union for now, until hopefully the layout - // computation is fixed. - return self.visit_union(v); - } + // Slices do not need special handling here: they have `Array` field + // placement with length 0, so we enter the `Array` case below which + // indirectly uses the metadata to determine the actual length. _ => {}, }; - // If this is a scalar, visit it as such. - // Things can be aggregates and have scalar layout at the same time, and that - // is very relevant for `NonNull` and similar structs: We need to visit them - // at their scalar layout *before* descending into their fields. - // FIXME: We could avoid some redundant checks here. For newtypes wrapping - // scalars, we do the same check on every "level" (e.g., first we check - // MyNewtype and then the scalar in there). - match v.layout().abi { - layout::Abi::Uninhabited => { - self.visit_uninhabited()?; - } - layout::Abi::Scalar(ref layout) => { - self.visit_scalar(v, layout)?; - } - // FIXME: Should we do something for ScalarPair? Vector? - _ => {} - } - - // Check primitive types. We do this after checking the scalar layout, - // just to have that done as well. Primitives can have varying layout, - // so we check them separately and before aggregate handling. - // It is CRITICAL that we get this check right, or we might be - // validating the wrong thing! - let primitive = match v.layout().fields { - // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - layout::FieldPlacement::Union(0) => true, - _ => v.layout().ty.builtin_deref(true).is_some(), - }; - if primitive { - return self.visit_primitive(v); - } - - // Proceed into the fields. + // Visit the fields of this value. match v.layout().fields { layout::FieldPlacement::Union(fields) => { - // Empty unions are not accepted by rustc. That's great, it means we can - // use that as an unambiguous signal for detecting primitives. Make sure - // we did not miss any primitive. - assert!(fields > 0); - self.visit_union(v) + self.visit_union(v, fields)?; }, layout::FieldPlacement::Arbitrary { ref offsets, .. } => { // FIXME: We collect in a vec because otherwise there are lifetime @@ -288,18 +209,35 @@ macro_rules! make_value_visitor { v.project_field(self.ecx(), i as u64) }) .collect(); - self.visit_aggregate(v, fields.into_iter()) + self.visit_aggregate(v, fields.into_iter())?; }, layout::FieldPlacement::Array { .. } => { // Let's get an mplace first. let mplace = v.to_op(self.ecx())?.assert_mem_place(self.ecx()); // Now we can go over all the fields. + // This uses the *run-time length*, i.e., if we are a slice, + // the dynamic info from the metadata is used. let iter = self.ecx().mplace_array_fields(mplace)? .map(|f| f.and_then(|f| { Ok(Value::from_mem_place(f)) })); - self.visit_aggregate(v, iter) + self.visit_aggregate(v, iter)?; + } + } + + match v.layout().variants { + // If this is a multi-variant layout, find the right variant and proceed + // with *its* fields. + layout::Variants::Multiple { .. } => { + let op = v.to_op(self.ecx())?; + let idx = self.ecx().read_discriminant(op)?.1; + let inner = v.project_downcast(self.ecx(), idx)?; + trace!("walk_value: variant layout: {:#?}", inner.layout()); + // recurse with the inner type + self.visit_variant(v, idx, inner) } + // For single-variant layouts, we already did anything there is to do. + layout::Variants::Single { .. } => Ok(()) } } } diff --git a/src/test/ui/consts/const-eval/transmute-const.stderr b/src/test/ui/consts/const-eval/transmute-const.stderr index 47f89fccf7a..e93a6887ba8 100644 --- a/src/test/ui/consts/const-eval/transmute-const.stderr +++ b/src/test/ui/consts/const-eval/transmute-const.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/transmute-const.rs:5:1 | LL | static FOO: bool = unsafe { mem::transmute(3u8) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8ebc9dbec8a..3680f4f2ac2 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 0 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:50:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:52:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected something that cannot possibly fail to be equal to 2 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -50,7 +50,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected a valid enum discriminant + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:71:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index 4d9d258f808..ec056187057 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -44,7 +44,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:32:1 | LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 01bde413c0d..86d5d17c538 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected something greater or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered NULL reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 3877f3cab6d..4fef9aa84ea 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:18:1 | LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Bar; 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 rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr index ea6ab3ae5b5..c1df447cd85 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.stderr @@ -6,7 +6,7 @@ LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; LL | | let another_var = 13; LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; - | |__^ type validation failed: encountered 0 at ..., but expected something greater or equal to 1 + | |__^ type validation failed: encountered NULL reference at ... | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index ce57d680dc9..170037b44da 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:116:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -74,7 +74,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:122:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -82,7 +82,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:125:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -122,7 +122,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:147:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/union-ub.stderr b/src/test/ui/consts/const-eval/union-ub.stderr index fa67bc0d8e7..9d90d6e8548 100644 --- a/src/test/ui/consts/const-eval/union-ub.stderr +++ b/src/test/ui/consts/const-eval/union-ub.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/union-ub.rs:31:1 | LL | const BAD_BOOL: bool = unsafe { DummyUnion { u8: 42 }.bool}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected something less or equal to 1 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 42, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr index c98e206e88c..2a338e27640 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Empty; 3] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index cb995b8216f..203620a771b 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:3:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:6:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of an uninhabited type at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From bd979ed48cb94c271a953a32723aca73f4edb551 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 18 Feb 2020 09:28:04 +0100 Subject: [PATCH 0298/1250] more English grammar --- src/librustc_mir/interpret/validity.rs | 8 ++++---- src/test/ui/consts/const-eval/ub-ref.rs | 2 +- src/test/ui/consts/const-eval/ub-ref.stderr | 6 +++--- src/test/ui/consts/const-eval/ub-upvars.stderr | 2 +- src/test/ui/consts/const-eval/ub-wide-ptr.stderr | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index e90a5985677..f2c956c80f7 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -362,12 +362,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ); match err.kind { err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("NULL reference", self.path) + throw_validation_failure!("a NULL reference", self.path) } err_unsup!(AlignmentCheckFailed { required, has }) => { throw_validation_failure!( format_args!( - "unaligned reference \ + "an unaligned reference \ (required {} byte alignment but found {})", required.bytes(), has.bytes() @@ -376,11 +376,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ) } err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "dangling reference (created from integer)", + "a dangling reference (created from integer)", self.path ), _ => throw_validation_failure!( - "dangling reference (not entirely in bounds)", + "a dangling reference (not entirely in bounds)", self.path ), } diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 03ac12c8b1a..889579ca1ec 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -6,7 +6,7 @@ use std::mem; const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value -//~^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1) +//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 86d5d17c538..5cef0a488eb 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:7:1 | LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned reference (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 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 rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered NULL reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:23:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-upvars.stderr b/src/test/ui/consts/const-eval/ub-upvars.stderr index c1df447cd85..7e4633b0908 100644 --- a/src/test/ui/consts/const-eval/ub-upvars.stderr +++ b/src/test/ui/consts/const-eval/ub-upvars.stderr @@ -6,7 +6,7 @@ LL | | let bad_ref: &'static u16 = unsafe { mem::transmute(0usize) }; LL | | let another_var = 13; LL | | move || { let _ = bad_ref; let _ = another_var; } LL | | }; - | |__^ type validation failed: encountered NULL reference at ... + | |__^ type validation failed: encountered a NULL reference at ... | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 170037b44da..4da9ad6c332 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:86:1 | LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -50,7 +50,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:109:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling reference (not entirely in bounds) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From c992ab23fa14a38c5565889d52ba3a3fb6e1e831 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 17 Feb 2020 19:39:38 -0500 Subject: [PATCH 0299/1250] Clean out some default-installed directories This helps us have enough disk space for our builders to be able to complete successfully. For now, the choices are ad-hoc and 'definitely not needed'. This should never fail the build, as everything our build needs should be inside Docker. --- src/ci/azure-pipelines/steps/run.yml | 3 +++ src/ci/scripts/clean-disk.sh | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100755 src/ci/scripts/clean-disk.sh diff --git a/src/ci/azure-pipelines/steps/run.yml b/src/ci/azure-pipelines/steps/run.yml index f536388b25b..c39f75aba89 100644 --- a/src/ci/azure-pipelines/steps/run.yml +++ b/src/ci/azure-pipelines/steps/run.yml @@ -31,6 +31,9 @@ steps: - bash: src/ci/scripts/setup-environment.sh displayName: Setup environment +- bash: src/ci/scripts/clean-disk.sh + displayName: Clean disk + - bash: src/ci/scripts/should-skip-this.sh displayName: Decide whether to run this job diff --git a/src/ci/scripts/clean-disk.sh b/src/ci/scripts/clean-disk.sh new file mode 100755 index 00000000000..c50de37c492 --- /dev/null +++ b/src/ci/scripts/clean-disk.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# This script deletes some of the Azure-provided artifacts. We don't use these, +# and disk space is at a premium on our builders. + +set -euo pipefail +IFS=$'\n\t' + +source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" + +# All the Linux builds happen inside Docker. +if isLinux; then + # 6.7GB + sudo rm -rf /opt/ghc + # 16GB + sudo rm -rf /usr/share/dotnet +fi From 73283f1b32f2c607be6ba5d51d867f8862eca95e Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Feb 2020 14:16:45 +0100 Subject: [PATCH 0300/1250] Clean up E0310 explanation --- src/librustc_error_codes/error_codes/E0310.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0310.md b/src/librustc_error_codes/error_codes/E0310.md index be87ccb114a..8d4311d018b 100644 --- a/src/librustc_error_codes/error_codes/E0310.md +++ b/src/librustc_error_codes/error_codes/E0310.md @@ -1,7 +1,7 @@ -Types in type definitions have lifetimes associated with them that represent -how long the data stored within them is guaranteed to be live. This lifetime -must be as long as the data needs to be alive, and missing the constraint that -denotes this will cause this error. +A parameter type is missing a lifetime constraint or has a lifetime that +does not live long enough. + +Erroneous code example: ```compile_fail,E0310 // This won't compile because T is not constrained to the static lifetime @@ -11,6 +11,11 @@ struct Foo { } ``` +Type parameters in type definitions have lifetimes associated with them that +represent how long the data stored within them is guaranteed to live. This +lifetime must be as long as the data needs to be alive, and missing the +constraint that denotes this will cause this error. + This will compile, because it has the constraint on the type parameter: ``` From b0302806680da26e686ce6f0432044fcbdb4b373 Mon Sep 17 00:00:00 2001 From: Ana-Maria Date: Tue, 18 Feb 2020 15:36:05 +0000 Subject: [PATCH 0301/1250] Blacklist powerpc-unknown-linux-gnu as having non-ignored GNU C ZSTs. --- src/librustc/ty/layout.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e8bf2eb9a12..753808bc254 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2547,6 +2547,8 @@ where target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu"; let linux_sparc64 = target.target_os == "linux" && target.arch == "sparc64" && target.target_env == "gnu"; + let linux_powerpc = + target.target_os == "linux" && target.arch == "powerpc" && target.target_env == "gnu"; let rust_abi = match sig.abi { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, _ => false, @@ -2617,9 +2619,12 @@ where if arg.layout.is_zst() { // For some forsaken reason, x86_64-pc-windows-gnu // doesn't ignore zero-sized struct arguments. - // The same is true for s390x-unknown-linux-gnu - // and sparc64-unknown-linux-gnu. - if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) { + // The same is true for s390x-unknown-linux-gnu, + // sparc64-unknown-linux-gnu and powerpc-unknown-linux-gnu. + if is_return + || rust_abi + || (!win_x64_gnu && !linux_s390x && !linux_sparc64 && !linux_powerpc) + { arg.mode = PassMode::Ignore; } } From 597b4f743e55a8c4653af7db1796fb3eb4b11d00 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 18 Feb 2020 09:21:34 -0800 Subject: [PATCH 0302/1250] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3c53211c3d7..e02974078a6 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3c53211c3d7fee4f430f170115af5baad17a3da9 +Subproject commit e02974078a692d7484f510eaec0e88d1b6cc0203 From 437f56edf43182955bb099a0d95970d63492196c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 18 Feb 2020 18:24:36 +0100 Subject: [PATCH 0303/1250] Fix race condition when allocating source files in SourceMap --- src/librustc_span/lib.rs | 10 +++--- src/librustc_span/source_map.rs | 56 +++++++++++++++++++++++++-------- 2 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 8f00b76001f..f9f3a900311 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -1075,7 +1075,7 @@ impl SourceFile { unmapped_path: FileName, mut src: String, start_pos: BytePos, - ) -> Result { + ) -> Self { let normalized_pos = normalize_src(&mut src, start_pos); let src_hash = { @@ -1089,14 +1089,12 @@ impl SourceFile { hasher.finish::() }; let end_pos = start_pos.to_usize() + src.len(); - if end_pos > u32::max_value() as usize { - return Err(OffsetOverflowError); - } + assert!(end_pos <= u32::max_value() as usize); let (lines, multibyte_chars, non_narrow_chars) = analyze_source_file::analyze_source_file(&src[..], start_pos); - Ok(SourceFile { + SourceFile { name, name_was_remapped, unmapped_path: Some(unmapped_path), @@ -1111,7 +1109,7 @@ impl SourceFile { non_narrow_chars, normalized_pos, name_hash, - }) + } } /// Returns the `BytePos` of the beginning of the current line. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 45c4d6dbc6c..31d397f040c 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -12,10 +12,12 @@ pub use crate::*; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::{Lock, LockGuard, Lrc, MappedLockGuard}; +use rustc_data_structures::sync::{AtomicU32, Lock, LockGuard, Lrc, MappedLockGuard}; use std::cmp; +use std::convert::TryFrom; use std::hash::Hash; use std::path::{Path, PathBuf}; +use std::sync::atomic::Ordering; use log::debug; use std::env; @@ -131,6 +133,9 @@ pub(super) struct SourceMapFiles { } pub struct SourceMap { + /// The address space below this value is currently used by the files in the source map. + used_address_space: AtomicU32, + files: Lock, file_loader: Box, // This is used to apply the file path remapping as specified via @@ -140,14 +145,24 @@ pub struct SourceMap { impl SourceMap { pub fn new(path_mapping: FilePathMapping) -> SourceMap { - SourceMap { files: Default::default(), file_loader: Box::new(RealFileLoader), path_mapping } + SourceMap { + used_address_space: AtomicU32::new(0), + files: Default::default(), + file_loader: Box::new(RealFileLoader), + path_mapping, + } } pub fn with_file_loader( file_loader: Box, path_mapping: FilePathMapping, ) -> SourceMap { - SourceMap { files: Default::default(), file_loader, path_mapping } + SourceMap { + used_address_space: AtomicU32::new(0), + files: Default::default(), + file_loader, + path_mapping, + } } pub fn path_mapping(&self) -> &FilePathMapping { @@ -194,12 +209,25 @@ impl SourceMap { self.files.borrow().stable_id_to_source_file.get(&stable_id).map(|sf| sf.clone()) } - fn next_start_pos(&self) -> usize { - match self.files.borrow().source_files.last() { - None => 0, - // Add one so there is some space between files. This lets us distinguish - // positions in the `SourceMap`, even in the presence of zero-length files. - Some(last) => last.end_pos.to_usize() + 1, + fn allocate_address_space(&self, size: usize) -> Result { + let size = u32::try_from(size).map_err(|_| OffsetOverflowError)?; + + loop { + let current = self.used_address_space.load(Ordering::Relaxed); + let next = current + .checked_add(size) + // Add one so there is some space between files. This lets us distinguish + // positions in the `SourceMap`, even in the presence of zero-length files. + .and_then(|next| next.checked_add(1)) + .ok_or(OffsetOverflowError)?; + + if self + .used_address_space + .compare_exchange(current, next, Ordering::Relaxed, Ordering::Relaxed) + .is_ok() + { + return Ok(usize::try_from(current).unwrap()); + } } } @@ -218,8 +246,6 @@ impl SourceMap { filename: FileName, src: String, ) -> Result, OffsetOverflowError> { - let start_pos = self.next_start_pos(); - // The path is used to determine the directory for loading submodules and // include files, so it must be before remapping. // Note that filename may not be a valid path, eg it may be `` etc, @@ -241,13 +267,15 @@ impl SourceMap { let lrc_sf = match self.source_file_by_stable_id(file_id) { Some(lrc_sf) => lrc_sf, None => { + let start_pos = self.allocate_address_space(src.len())?; + let source_file = Lrc::new(SourceFile::new( filename, was_remapped, unmapped_path, src, Pos::from_usize(start_pos), - )?); + )); let mut files = self.files.borrow_mut(); @@ -277,7 +305,9 @@ impl SourceMap { mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, ) -> Lrc { - let start_pos = self.next_start_pos(); + let start_pos = self + .allocate_address_space(source_len) + .expect("not enough address space for imported source file"); let end_pos = Pos::from_usize(start_pos + source_len); let start_pos = Pos::from_usize(start_pos); From 5e19350a4c858bd98b0864d55e8ce1efc370e33d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 18 Feb 2020 22:49:47 +0100 Subject: [PATCH 0304/1250] better lint names --- src/librustc_lint/lib.rs | 1 + src/librustc_mir/transform/const_prop.rs | 8 ++++---- src/librustc_session/lint/builtin.rs | 15 ++++----------- src/test/codegen/issue-56927.rs | 2 +- src/test/incremental/warnings-reemitted.rs | 2 +- src/test/run-fail/mir_indexing_oob_1.rs | 2 +- src/test/run-fail/mir_indexing_oob_2.rs | 2 +- src/test/run-fail/mir_indexing_oob_3.rs | 2 +- src/test/run-fail/overflowing-add.rs | 2 +- src/test/run-fail/overflowing-lsh-1.rs | 2 +- src/test/run-fail/overflowing-lsh-2.rs | 2 +- src/test/run-fail/overflowing-lsh-3.rs | 2 +- src/test/run-fail/overflowing-lsh-4.rs | 2 +- src/test/run-fail/overflowing-mul.rs | 2 +- src/test/run-fail/overflowing-neg.rs | 2 +- src/test/run-fail/overflowing-rsh-1.rs | 2 +- src/test/run-fail/overflowing-rsh-2.rs | 2 +- src/test/run-fail/overflowing-rsh-3.rs | 2 +- src/test/run-fail/overflowing-rsh-4.rs | 2 +- src/test/run-fail/overflowing-rsh-5.rs | 2 +- src/test/run-fail/overflowing-rsh-6.rs | 2 +- src/test/run-fail/overflowing-sub.rs | 2 +- src/test/run-fail/promoted_div_by_zero.rs | 2 +- src/test/run-fail/promoted_overflow.rs | 2 +- src/test/ui/consts/array-literal-index-oob.rs | 2 +- src/test/ui/consts/array-literal-index-oob.stderr | 6 +++--- src/test/ui/consts/const-err.rs | 2 +- src/test/ui/consts/const-err2.default.stderr | 4 ++-- src/test/ui/consts/const-err2.noopt.stderr | 4 ++-- src/test/ui/consts/const-err2.opt.stderr | 4 ++-- .../const-err2.opt_with_overflow_checks.stderr | 4 ++-- .../index_out_of_bounds_propagated.stderr | 2 +- .../const-eval/promoted_errors.default.stderr | 12 ++++++------ .../const-eval/promoted_errors.noopt.stderr | 12 ++++++------ .../consts/const-eval/promoted_errors.opt.stderr | 12 ++++++------ ...romoted_errors.opt_with_overflow_checks.stderr | 12 ++++++------ src/test/ui/consts/const-eval/promoted_errors.rs | 14 +++++++------- src/test/ui/consts/const-prop-ice.stderr | 2 +- src/test/ui/consts/const-prop-ice2.stderr | 2 +- src/test/ui/consts/issue-69020.default.stderr | 4 ++-- src/test/ui/consts/issue-69020.noopt.stderr | 4 ++-- src/test/ui/consts/issue-69020.opt.stderr | 4 ++-- .../issue-69020.opt_with_overflow_checks.stderr | 4 ++-- src/test/ui/huge-array-simple-64.rs | 2 +- src/test/ui/issues/issue-54348.stderr | 2 +- .../ui/issues/issue-8460-const.default.stderr | 4 ++-- src/test/ui/issues/issue-8460-const.noopt.stderr | 4 ++-- src/test/ui/issues/issue-8460-const.opt.stderr | 4 ++-- ...sue-8460-const.opt_with_overflow_checks.stderr | 4 ++-- .../lint/lint-exceeding-bitshifts.default.stderr | 2 +- .../ui/lint/lint-exceeding-bitshifts.noopt.stderr | 2 +- .../ui/lint/lint-exceeding-bitshifts.opt.stderr | 2 +- ...ding-bitshifts.opt_with_overflow_checks.stderr | 2 +- src/test/ui/lint/lint-exceeding-bitshifts.rs | 2 +- 54 files changed, 100 insertions(+), 106 deletions(-) diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 2204e104803..0e7625da30a 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -305,6 +305,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { store.register_renamed("unstable_name_collision", "unstable_name_collisions"); store.register_renamed("unused_doc_comment", "unused_doc_comments"); store.register_renamed("async_idents", "keyword_idents"); + store.register_renamed("exceeding_bitshifts", "arithmetic_overflow"); store.register_removed("unknown_features", "replaced by an error"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index eec4bbc720d..8ccfcecdbe3 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -531,7 +531,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // appropriate to use. assert_eq!(op, UnOp::Neg, "Neg is the only UnOp that can overflow"); self.report_assert_as_lint( - lint::builtin::OVERFLOW, + lint::builtin::ARITHMETIC_OVERFLOW, source_info, "this arithmetic operation will overflow", AssertKind::OverflowNeg, @@ -560,7 +560,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); if r_bits.map_or(false, |b| b >= left_size_bits as u128) { self.report_assert_as_lint( - lint::builtin::EXCEEDING_BITSHIFTS, + lint::builtin::ARITHMETIC_OVERFLOW, source_info, "this arithmetic operation will overflow", AssertKind::Overflow(op), @@ -575,7 +575,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { Ok(overflow) })? { self.report_assert_as_lint( - lint::builtin::OVERFLOW, + lint::builtin::ARITHMETIC_OVERFLOW, source_info, "this arithmetic operation will overflow", AssertKind::Overflow(op), @@ -937,7 +937,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { _ => return, }; self.report_assert_as_lint( - lint::builtin::PANIC, + lint::builtin::UNCONDITIONAL_PANIC, source_info, "this operation will panic at runtime", msg, diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs index 992f8ab2617..603ed4640a0 100644 --- a/src/librustc_session/lint/builtin.rs +++ b/src/librustc_session/lint/builtin.rs @@ -41,19 +41,13 @@ declare_lint! { } declare_lint! { - pub EXCEEDING_BITSHIFTS, - Deny, - "shift exceeds the type's number of bits" -} - -declare_lint! { - pub OVERFLOW, + pub ARITHMETIC_OVERFLOW, Deny, "arithmetic operation overflows" } declare_lint! { - pub PANIC, + pub UNCONDITIONAL_PANIC, Deny, "operation will cause a panic at runtime" } @@ -507,9 +501,8 @@ declare_lint_pass! { /// that are used by other parts of the compiler. HardwiredLints => [ ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, - EXCEEDING_BITSHIFTS, - OVERFLOW, - PANIC, + ARITHMETIC_OVERFLOW, + UNCONDITIONAL_PANIC, UNUSED_IMPORTS, UNUSED_EXTERN_CRATES, UNUSED_QUALIFICATIONS, diff --git a/src/test/codegen/issue-56927.rs b/src/test/codegen/issue-56927.rs index 5ba17d3499b..d502673e2f8 100644 --- a/src/test/codegen/issue-56927.rs +++ b/src/test/codegen/issue-56927.rs @@ -23,7 +23,7 @@ pub fn test1(s: &mut S) { // CHECK-LABEL: @test2 // CHECK: store i32 4, i32* %{{.+}}, align 4 -#[allow(panic)] +#[allow(unconditional_panic)] #[no_mangle] pub fn test2(s: &mut S) { s.arr[usize::MAX / 4 + 1] = 4; diff --git a/src/test/incremental/warnings-reemitted.rs b/src/test/incremental/warnings-reemitted.rs index 657bc30c088..0eac2a1d57f 100644 --- a/src/test/incremental/warnings-reemitted.rs +++ b/src/test/incremental/warnings-reemitted.rs @@ -2,7 +2,7 @@ // compile-flags: -Coverflow-checks=on // build-pass (FIXME(62277): could be check-pass?) -#![warn(overflow)] +#![warn(arithmetic_overflow)] fn main() { let _ = 255u8 + 1; //~ WARNING operation will overflow diff --git a/src/test/run-fail/mir_indexing_oob_1.rs b/src/test/run-fail/mir_indexing_oob_1.rs index 6aaf46cfb1b..1cd53e309eb 100644 --- a/src/test/run-fail/mir_indexing_oob_1.rs +++ b/src/test/run-fail/mir_indexing_oob_1.rs @@ -2,7 +2,7 @@ const C: [u32; 5] = [0; 5]; -#[allow(panic, const_err)] +#[allow(unconditional_panic)] fn test() -> u32 { C[10] } diff --git a/src/test/run-fail/mir_indexing_oob_2.rs b/src/test/run-fail/mir_indexing_oob_2.rs index 1bf8459a068..64b260993c9 100644 --- a/src/test/run-fail/mir_indexing_oob_2.rs +++ b/src/test/run-fail/mir_indexing_oob_2.rs @@ -2,7 +2,7 @@ const C: &'static [u8; 5] = b"hello"; -#[allow(panic, const_err)] +#[allow(unconditional_panic)] fn test() -> u8 { C[10] } diff --git a/src/test/run-fail/mir_indexing_oob_3.rs b/src/test/run-fail/mir_indexing_oob_3.rs index c13ca721ea8..3688088439b 100644 --- a/src/test/run-fail/mir_indexing_oob_3.rs +++ b/src/test/run-fail/mir_indexing_oob_3.rs @@ -2,7 +2,7 @@ const C: &'static [u8; 5] = b"hello"; -#[allow(panic, const_err)] +#[allow(unconditional_panic)] fn mir() -> u8 { C[10] } diff --git a/src/test/run-fail/overflowing-add.rs b/src/test/run-fail/overflowing-add.rs index 69d7779e13e..5ca91314d95 100644 --- a/src/test/run-fail/overflowing-add.rs +++ b/src/test/run-fail/overflowing-add.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to add with overflow' // compile-flags: -C debug-assertions -#![allow(overflow)] +#![allow(arithmetic_overflow)] fn main() { let _x = 200u8 + 200u8 + 200u8; diff --git a/src/test/run-fail/overflowing-lsh-1.rs b/src/test/run-fail/overflowing-lsh-1.rs index 37fbf01e487..977cfea0fe0 100644 --- a/src/test/run-fail/overflowing-lsh-1.rs +++ b/src/test/run-fail/overflowing-lsh-1.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-lsh-2.rs b/src/test/run-fail/overflowing-lsh-2.rs index 7b0b37dfed0..3517dacde3a 100644 --- a/src/test/run-fail/overflowing-lsh-2.rs +++ b/src/test/run-fail/overflowing-lsh-2.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-lsh-3.rs b/src/test/run-fail/overflowing-lsh-3.rs index 1768a8e6d31..4a575c3fa7f 100644 --- a/src/test/run-fail/overflowing-lsh-3.rs +++ b/src/test/run-fail/overflowing-lsh-3.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift left with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-lsh-4.rs b/src/test/run-fail/overflowing-lsh-4.rs index ec304b4144e..0d3912ce13f 100644 --- a/src/test/run-fail/overflowing-lsh-4.rs +++ b/src/test/run-fail/overflowing-lsh-4.rs @@ -4,7 +4,7 @@ // This function is checking that our automatic truncation does not // sidestep the overflow checking. -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-mul.rs b/src/test/run-fail/overflowing-mul.rs index ef191c01586..2dfc9bb5ae4 100644 --- a/src/test/run-fail/overflowing-mul.rs +++ b/src/test/run-fail/overflowing-mul.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to multiply with overflow' // compile-flags: -C debug-assertions -#![allow(overflow)] +#![allow(arithmetic_overflow)] fn main() { let x = 200u8 * 4; diff --git a/src/test/run-fail/overflowing-neg.rs b/src/test/run-fail/overflowing-neg.rs index 443cddf53fb..f512aa35bed 100644 --- a/src/test/run-fail/overflowing-neg.rs +++ b/src/test/run-fail/overflowing-neg.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to negate with overflow' // compile-flags: -C debug-assertions -#![allow(overflow)] +#![allow(arithmetic_overflow)] fn main() { let _x = -std::i8::MIN; diff --git a/src/test/run-fail/overflowing-rsh-1.rs b/src/test/run-fail/overflowing-rsh-1.rs index 14514540c06..4592b2b6260 100644 --- a/src/test/run-fail/overflowing-rsh-1.rs +++ b/src/test/run-fail/overflowing-rsh-1.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-rsh-2.rs b/src/test/run-fail/overflowing-rsh-2.rs index 83dcbd13d2a..066267b770d 100644 --- a/src/test/run-fail/overflowing-rsh-2.rs +++ b/src/test/run-fail/overflowing-rsh-2.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-rsh-3.rs b/src/test/run-fail/overflowing-rsh-3.rs index 3521c050659..67e78482866 100644 --- a/src/test/run-fail/overflowing-rsh-3.rs +++ b/src/test/run-fail/overflowing-rsh-3.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-rsh-4.rs b/src/test/run-fail/overflowing-rsh-4.rs index ed1191849e5..1877d5c9685 100644 --- a/src/test/run-fail/overflowing-rsh-4.rs +++ b/src/test/run-fail/overflowing-rsh-4.rs @@ -4,7 +4,7 @@ // This function is checking that our (type-based) automatic // truncation does not sidestep the overflow checking. -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-rsh-5.rs b/src/test/run-fail/overflowing-rsh-5.rs index 58dfc5710ae..20ef324a82a 100644 --- a/src/test/run-fail/overflowing-rsh-5.rs +++ b/src/test/run-fail/overflowing-rsh-5.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] fn main() { diff --git a/src/test/run-fail/overflowing-rsh-6.rs b/src/test/run-fail/overflowing-rsh-6.rs index c2fec5e4860..589a98bab04 100644 --- a/src/test/run-fail/overflowing-rsh-6.rs +++ b/src/test/run-fail/overflowing-rsh-6.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to shift right with overflow' // compile-flags: -C debug-assertions -#![warn(exceeding_bitshifts)] +#![warn(arithmetic_overflow)] #![warn(const_err)] #![feature(const_indexing)] diff --git a/src/test/run-fail/overflowing-sub.rs b/src/test/run-fail/overflowing-sub.rs index 4f4a3eed8cc..fb096c31957 100644 --- a/src/test/run-fail/overflowing-sub.rs +++ b/src/test/run-fail/overflowing-sub.rs @@ -1,7 +1,7 @@ // error-pattern:thread 'main' panicked at 'attempt to subtract with overflow' // compile-flags: -C debug-assertions -#![allow(overflow)] +#![allow(arithmetic_overflow)] fn main() { let _x = 42u8 - (42u8 + 1); diff --git a/src/test/run-fail/promoted_div_by_zero.rs b/src/test/run-fail/promoted_div_by_zero.rs index 0ad081f0314..dc6719ce025 100644 --- a/src/test/run-fail/promoted_div_by_zero.rs +++ b/src/test/run-fail/promoted_div_by_zero.rs @@ -1,4 +1,4 @@ -#![allow(panic, const_err)] +#![allow(unconditional_panic, const_err)] // error-pattern: attempt to divide by zero diff --git a/src/test/run-fail/promoted_overflow.rs b/src/test/run-fail/promoted_overflow.rs index a90f832ddd0..3c42da4b1d8 100644 --- a/src/test/run-fail/promoted_overflow.rs +++ b/src/test/run-fail/promoted_overflow.rs @@ -1,4 +1,4 @@ -#![allow(overflow)] +#![allow(arithmetic_overflow)] // error-pattern: overflow // compile-flags: -C overflow-checks=yes diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 978f2333101..492afa9372c 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -1,7 +1,7 @@ // build-pass // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) -#![warn(const_err, panic)] +#![warn(const_err, unconditional_panic)] fn main() { &{ [1, 2, 3][4] }; diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 605cd73db1f..6e0e7fedb7b 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -7,8 +7,8 @@ LL | &{ [1, 2, 3][4] }; note: the lint level is defined here --> $DIR/array-literal-index-oob.rs:4:20 | -LL | #![warn(const_err, panic)] - | ^^^^^ +LL | #![warn(const_err, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/array-literal-index-oob.rs:7:8 @@ -21,7 +21,7 @@ LL | &{ [1, 2, 3][4] }; note: the lint level is defined here --> $DIR/array-literal-index-oob.rs:4:9 | -LL | #![warn(const_err, panic)] +LL | #![warn(const_err, unconditional_panic)] | ^^^^^^^^^ warning: erroneous constant used diff --git a/src/test/ui/consts/const-err.rs b/src/test/ui/consts/const-err.rs index b204f705a96..d1c5f4f3f32 100644 --- a/src/test/ui/consts/const-err.rs +++ b/src/test/ui/consts/const-err.rs @@ -1,7 +1,7 @@ // build-fail // compile-flags: -Zforce-overflow-checks=on -#![allow(exceeding_bitshifts)] +#![allow(arithmetic_overflow)] #![warn(const_err)] fn black_box(_: T) { diff --git a/src/test/ui/consts/const-err2.default.stderr b/src/test/ui/consts/const-err2.default.stderr index 226874c29da..5aeeec4bd14 100644 --- a/src/test/ui/consts/const-err2.default.stderr +++ b/src/test/ui/consts/const-err2.default.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/const-err2.rs:21:18 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | let _e = [5u8][1]; | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-err2.noopt.stderr b/src/test/ui/consts/const-err2.noopt.stderr index 226874c29da..5aeeec4bd14 100644 --- a/src/test/ui/consts/const-err2.noopt.stderr +++ b/src/test/ui/consts/const-err2.noopt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/const-err2.rs:21:18 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | let _e = [5u8][1]; | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-err2.opt.stderr b/src/test/ui/consts/const-err2.opt.stderr index 226874c29da..5aeeec4bd14 100644 --- a/src/test/ui/consts/const-err2.opt.stderr +++ b/src/test/ui/consts/const-err2.opt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/const-err2.rs:21:18 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | let _e = [5u8][1]; | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr index 226874c29da..5aeeec4bd14 100644 --- a/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr +++ b/src/test/ui/consts/const-err2.opt_with_overflow_checks.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | let a = -std::i8::MIN; | ^^^^^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/const-err2.rs:21:18 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | let _e = [5u8][1]; | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to 7 previous errors diff --git a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr index 5da802d30f5..4188efd021d 100644 --- a/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr +++ b/src/test/ui/consts/const-eval/index_out_of_bounds_propagated.stderr @@ -4,7 +4,7 @@ error: this operation will panic at runtime LL | array[1]; | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/consts/const-eval/promoted_errors.default.stderr b/src/test/ui/consts/const-eval/promoted_errors.default.stderr index 8f21ce53715..034dea06568 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.default.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.default.stderr @@ -7,8 +7,8 @@ LL | let _x = 0u32 - 1; note: the lint level is defined here --> $DIR/promoted_errors.rs:9:20 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: this operation will panic at runtime --> $DIR/promoted_errors.rs:16:20 @@ -17,10 +17,10 @@ LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ attempt to divide by zero | note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:30 + --> $DIR/promoted_errors.rs:9:41 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:16:20 @@ -31,7 +31,7 @@ LL | println!("{}", 1 / (1 - 1)); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:9 | -LL | #![warn(const_err, overflow, panic)] +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] | ^^^^^^^^^ warning: erroneous constant used diff --git a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr index 1ed60c1f96e..94c1593240b 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.noopt.stderr @@ -7,8 +7,8 @@ LL | println!("{}", 0u32 - 1); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:20 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: this arithmetic operation will overflow --> $DIR/promoted_errors.rs:14:14 @@ -23,10 +23,10 @@ LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ attempt to divide by zero | note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:30 + --> $DIR/promoted_errors.rs:9:41 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:16:20 @@ -37,7 +37,7 @@ LL | println!("{}", 1 / (1 - 1)); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:9 | -LL | #![warn(const_err, overflow, panic)] +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] | ^^^^^^^^^ warning: erroneous constant used diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr index 8f21ce53715..034dea06568 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.opt.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.opt.stderr @@ -7,8 +7,8 @@ LL | let _x = 0u32 - 1; note: the lint level is defined here --> $DIR/promoted_errors.rs:9:20 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: this operation will panic at runtime --> $DIR/promoted_errors.rs:16:20 @@ -17,10 +17,10 @@ LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ attempt to divide by zero | note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:30 + --> $DIR/promoted_errors.rs:9:41 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:16:20 @@ -31,7 +31,7 @@ LL | println!("{}", 1 / (1 - 1)); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:9 | -LL | #![warn(const_err, overflow, panic)] +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] | ^^^^^^^^^ warning: erroneous constant used diff --git a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr index 1ed60c1f96e..94c1593240b 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.opt_with_overflow_checks.stderr @@ -7,8 +7,8 @@ LL | println!("{}", 0u32 - 1); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:20 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: this arithmetic operation will overflow --> $DIR/promoted_errors.rs:14:14 @@ -23,10 +23,10 @@ LL | println!("{}", 1 / (1 - 1)); | ^^^^^^^^^^^ attempt to divide by zero | note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:30 + --> $DIR/promoted_errors.rs:9:41 | -LL | #![warn(const_err, overflow, panic)] - | ^^^^^ +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] + | ^^^^^^^^^^^^^^^^^^^ warning: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:16:20 @@ -37,7 +37,7 @@ LL | println!("{}", 1 / (1 - 1)); note: the lint level is defined here --> $DIR/promoted_errors.rs:9:9 | -LL | #![warn(const_err, overflow, panic)] +LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] | ^^^^^^^^^ warning: erroneous constant used diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index 3133e9b380b..b734f70f9f0 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -6,23 +6,23 @@ // build-pass // ignore-pass (emit codegen-time warnings and verify that they are indeed warnings and not errors) -#![warn(const_err, overflow, panic)] +#![warn(const_err, arithmetic_overflow, unconditional_panic)] fn main() { println!("{}", 0u32 - 1); - //[opt_with_overflow_checks,noopt]~^ WARN [overflow] + //[opt_with_overflow_checks,noopt]~^ WARN [arithmetic_overflow] let _x = 0u32 - 1; - //~^ WARN [overflow] + //~^ WARN [arithmetic_overflow] println!("{}", 1 / (1 - 1)); - //~^ WARN [panic] + //~^ WARN [unconditional_panic] //~| WARN panic or abort [const_err] //~| WARN erroneous constant used [const_err] let _x = 1 / (1 - 1); - //~^ WARN [panic] + //~^ WARN [unconditional_panic] println!("{}", 1 / (false as u32)); - //~^ WARN [panic] + //~^ WARN [unconditional_panic] //~| WARN panic or abort [const_err] //~| WARN erroneous constant used [const_err] let _x = 1 / (false as u32); - //~^ WARN [panic] + //~^ WARN [unconditional_panic] } diff --git a/src/test/ui/consts/const-prop-ice.stderr b/src/test/ui/consts/const-prop-ice.stderr index 855b9e6b64b..7bb4acb235a 100644 --- a/src/test/ui/consts/const-prop-ice.stderr +++ b/src/test/ui/consts/const-prop-ice.stderr @@ -4,7 +4,7 @@ error: this operation will panic at runtime LL | [0; 3][3u64 as usize]; | ^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 3 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/consts/const-prop-ice2.stderr b/src/test/ui/consts/const-prop-ice2.stderr index 07faa39edc2..73405eca340 100644 --- a/src/test/ui/consts/const-prop-ice2.stderr +++ b/src/test/ui/consts/const-prop-ice2.stderr @@ -4,7 +4,7 @@ error: this operation will panic at runtime LL | println!("{}", xs[Enum::One as usize]); | ^^^^^^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: aborting due to previous error diff --git a/src/test/ui/consts/issue-69020.default.stderr b/src/test/ui/consts/issue-69020.default.stderr index 1b1987f4dc3..c48a106ef46 100644 --- a/src/test/ui/consts/issue-69020.default.stderr +++ b/src/test/ui/consts/issue-69020.default.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | const NEG: i32 = -i32::MIN + T::NEG; | ^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-69020.rs:23:22 @@ -18,7 +18,7 @@ error: this operation will panic at runtime LL | const DIV: i32 = (1/0) + T::DIV; | ^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-69020.rs:27:22 diff --git a/src/test/ui/consts/issue-69020.noopt.stderr b/src/test/ui/consts/issue-69020.noopt.stderr index 1b1987f4dc3..c48a106ef46 100644 --- a/src/test/ui/consts/issue-69020.noopt.stderr +++ b/src/test/ui/consts/issue-69020.noopt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | const NEG: i32 = -i32::MIN + T::NEG; | ^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-69020.rs:23:22 @@ -18,7 +18,7 @@ error: this operation will panic at runtime LL | const DIV: i32 = (1/0) + T::DIV; | ^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-69020.rs:27:22 diff --git a/src/test/ui/consts/issue-69020.opt.stderr b/src/test/ui/consts/issue-69020.opt.stderr index 1b1987f4dc3..c48a106ef46 100644 --- a/src/test/ui/consts/issue-69020.opt.stderr +++ b/src/test/ui/consts/issue-69020.opt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | const NEG: i32 = -i32::MIN + T::NEG; | ^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-69020.rs:23:22 @@ -18,7 +18,7 @@ error: this operation will panic at runtime LL | const DIV: i32 = (1/0) + T::DIV; | ^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-69020.rs:27:22 diff --git a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr index 1b1987f4dc3..c48a106ef46 100644 --- a/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr +++ b/src/test/ui/consts/issue-69020.opt_with_overflow_checks.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | const NEG: i32 = -i32::MIN + T::NEG; | ^^^^^^^^^ attempt to negate with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-69020.rs:23:22 @@ -18,7 +18,7 @@ error: this operation will panic at runtime LL | const DIV: i32 = (1/0) + T::DIV; | ^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-69020.rs:27:22 diff --git a/src/test/ui/huge-array-simple-64.rs b/src/test/ui/huge-array-simple-64.rs index d4c93301283..02c961fc5fa 100644 --- a/src/test/ui/huge-array-simple-64.rs +++ b/src/test/ui/huge-array-simple-64.rs @@ -4,7 +4,7 @@ // FIXME https://github.com/rust-lang/rust/issues/59774 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" -#![allow(exceeding_bitshifts)] +#![allow(arithmetic_overflow)] fn main() { let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture diff --git a/src/test/ui/issues/issue-54348.stderr b/src/test/ui/issues/issue-54348.stderr index f2156a35f2a..6b67125e36c 100644 --- a/src/test/ui/issues/issue-54348.stderr +++ b/src/test/ui/issues/issue-54348.stderr @@ -4,7 +4,7 @@ error: this operation will panic at runtime LL | [1][1.5 as usize]; | ^^^^^^^^^^^^^^^^^ index out of bounds: the len is 1 but the index is 1 | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-54348.rs:6:5 diff --git a/src/test/ui/issues/issue-8460-const.default.stderr b/src/test/ui/issues/issue-8460-const.default.stderr index 33d846e3e91..3556ec08247 100644 --- a/src/test/ui/issues/issue-8460-const.default.stderr +++ b/src/test/ui/issues/issue-8460-const.default.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-8460-const.rs:16:36 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:28:36 diff --git a/src/test/ui/issues/issue-8460-const.noopt.stderr b/src/test/ui/issues/issue-8460-const.noopt.stderr index 33d846e3e91..3556ec08247 100644 --- a/src/test/ui/issues/issue-8460-const.noopt.stderr +++ b/src/test/ui/issues/issue-8460-const.noopt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-8460-const.rs:16:36 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:28:36 diff --git a/src/test/ui/issues/issue-8460-const.opt.stderr b/src/test/ui/issues/issue-8460-const.opt.stderr index 33d846e3e91..3556ec08247 100644 --- a/src/test/ui/issues/issue-8460-const.opt.stderr +++ b/src/test/ui/issues/issue-8460-const.opt.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-8460-const.rs:16:36 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:28:36 diff --git a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr index 33d846e3e91..3556ec08247 100644 --- a/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr +++ b/src/test/ui/issues/issue-8460-const.opt_with_overflow_checks.stderr @@ -4,7 +4,7 @@ error: this arithmetic operation will overflow LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); | ^^^^^^^^^^^^^^^ attempt to divide with overflow | - = note: `#[deny(overflow)]` on by default + = note: `#[deny(arithmetic_overflow)]` on by default error: this arithmetic operation will overflow --> $DIR/issue-8460-const.rs:16:36 @@ -42,7 +42,7 @@ error: this operation will panic at runtime LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); | ^^^^^^^^^^ attempt to divide by zero | - = note: `#[deny(panic)]` on by default + = note: `#[deny(unconditional_panic)]` on by default error: this operation will panic at runtime --> $DIR/issue-8460-const.rs:28:36 diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr index 5e32466c4e0..ce9b02b6d82 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr @@ -7,7 +7,7 @@ LL | let _ = x << 42; note: the lint level is defined here --> $DIR/lint-exceeding-bitshifts.rs:9:9 | -LL | #![deny(exceeding_bitshifts, const_err)] +LL | #![deny(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ error: this arithmetic operation will overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr index 5e32466c4e0..ce9b02b6d82 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.noopt.stderr @@ -7,7 +7,7 @@ LL | let _ = x << 42; note: the lint level is defined here --> $DIR/lint-exceeding-bitshifts.rs:9:9 | -LL | #![deny(exceeding_bitshifts, const_err)] +LL | #![deny(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ error: this arithmetic operation will overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr index 5e32466c4e0..ce9b02b6d82 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt.stderr @@ -7,7 +7,7 @@ LL | let _ = x << 42; note: the lint level is defined here --> $DIR/lint-exceeding-bitshifts.rs:9:9 | -LL | #![deny(exceeding_bitshifts, const_err)] +LL | #![deny(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ error: this arithmetic operation will overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr index 5e32466c4e0..ce9b02b6d82 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr +++ b/src/test/ui/lint/lint-exceeding-bitshifts.opt_with_overflow_checks.stderr @@ -7,7 +7,7 @@ LL | let _ = x << 42; note: the lint level is defined here --> $DIR/lint-exceeding-bitshifts.rs:9:9 | -LL | #![deny(exceeding_bitshifts, const_err)] +LL | #![deny(arithmetic_overflow, const_err)] | ^^^^^^^^^^^^^^^^^^^ error: this arithmetic operation will overflow diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs index 3c6d70e7a6f..04996e41bb3 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs @@ -6,7 +6,7 @@ // build-fail #![crate_type="lib"] -#![deny(exceeding_bitshifts, const_err)] +#![deny(arithmetic_overflow, const_err)] #![allow(unused_variables)] #![allow(dead_code)] From 3e17d191fa47b9ab262d0efa3a39e500e9fb1667 Mon Sep 17 00:00:00 2001 From: Sebastian Hahn Date: Mon, 17 Feb 2020 18:55:41 +0100 Subject: [PATCH 0305/1250] Revert "Remove `checked_add` in `Layout::repeat`" This fixes a a segfault in safe code, a stable regression. Reported in \#69225. This reverts commit a983e0590a43ed8b0f60417828efd4e79b51f494. Also adds a test for the expected behaviour. --- src/libcore/alloc.rs | 12 ++++--- ...issue-69225-layout-repeated-checked-add.rs | 31 +++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 71f7f971eab..a04e75bc7ce 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -241,11 +241,13 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> { - // This cannot overflow. Quoting from the invariant of Layout: - // > `size`, when rounded up to the nearest multiple of `align`, - // > must not overflow (i.e., the rounded value must be less than - // > `usize::MAX`) - let padded_size = self.size() + self.padding_needed_for(self.align()); + // Warning, removing the checked_add here led to segfaults in #67174. Further + // analysis in #69225 seems to indicate that this is an LTO-related + // miscompilation, so #67174 might be able to be reapplied in the future. + let padded_size = self + .size() + .checked_add(self.padding_needed_for(self.align())) + .ok_or(LayoutErr { private: () })?; let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?; unsafe { diff --git a/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs b/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs new file mode 100644 index 00000000000..7f43e4d1a51 --- /dev/null +++ b/src/test/ui/issues/issue-69225-layout-repeated-checked-add.rs @@ -0,0 +1,31 @@ +// Ensure we appropriately error instead of overflowing a calculation when creating a new Alloc +// Layout + +// run-fail +// compile-flags: -C opt-level=3 +// error-pattern: index out of bounds: the len is 0 but the index is 16777216 +// ignore-wasm no panic or subprocess support +// ignore-emscripten no panic or subprocess support + +fn do_test(x: usize) { + let arr = vec![vec![0u8; 3]]; + + let mut z = Vec::new(); + for arr_ref in arr { + for y in 0..x { + for _ in 0..1 { + z.extend(std::iter::repeat(0).take(x)); + let a = y * x; + let b = (y + 1) * x - 1; + let slice = &arr_ref[a..b]; + eprintln!("{} {} {} {}", a, b, arr_ref.len(), slice.len()); + eprintln!("{:?}", slice[1 << 24]); + } + } + } +} + +fn main() { + do_test(1); + do_test(2); +} From 076cd9eabdfbbd68b00d1fb5ccc35c9a2f8c0d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 19 Feb 2020 03:45:10 +0100 Subject: [PATCH 0306/1250] submodules: update clippy from b91ae16e to 2855b214 Changes: ```` Rustup to rust-lang/rust#69194 Rustup to rust-lang/rust#69181 Add `LOG2_10` and `LOG10_2` to `approx_const` lint Clean up imports Use `Vec::with_capacity()` as possible needless_doctest_main: False positive for async fn Remove use of `TyKind`. Use `if_chain`. Fix ICE. Add tests and improve checks. Add `Future` detection for `missing_errors_doc`. ```` Fixes #69269 --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index b91ae16eb1a..2855b214397 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit b91ae16eb1ab03b996de5ffc44db054244c1d2f6 +Subproject commit 2855b2143972df7102333193aa3c83ddce227e36 From 62ff11f1a4d27a61ea60d309ed8fe738c07ce2ef Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 12:21:27 -0800 Subject: [PATCH 0307/1250] Add `is_const_impl_raw` query --- src/librustc/query/mod.rs | 8 ++++++++ src/librustc_mir/const_eval/fn_queries.rs | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 45ab3fc0b85..3cee10f1356 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -279,6 +279,14 @@ rustc_queries! { desc { |tcx| "checking if item is const fn: `{}`", tcx.def_path_str(key) } } + /// Returns `true` if this is a const `impl`. **Do not call this function manually.** + /// + /// This query caches the base data for the `is_const_impl` helper function, which also + /// takes into account stability attributes (e.g., `#[rustc_const_unstable]`). + query is_const_impl_raw(key: DefId) -> bool { + desc { |tcx| "checking if item is const impl: `{}`", tcx.def_path_str(key) } + } + query asyncness(key: DefId) -> hir::IsAsync { desc { |tcx| "checking if the function is async: `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index 4144bbc41d2..5706d435f7e 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -3,7 +3,7 @@ use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_attr as attr; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_span::symbol::Symbol; use rustc_target::spec::abi::Abi; @@ -119,6 +119,19 @@ pub fn provide(providers: &mut Providers<'_>) { } } + /// Checks whether the given item is an `impl` that has a `const` modifier. + fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let node = tcx.hir().get(hir_id); + matches!( + node, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. }, + .. + }) + ) + } + fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { is_const_fn(tcx, def_id) && match tcx.lookup_const_stability(def_id) { @@ -148,6 +161,7 @@ pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { is_const_fn_raw, + is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)), is_promotable_const_fn, const_fn_is_allowed_fn_ptr, ..*providers From 3e0b0605a04d029ff812147f3d54f95a211769b1 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 14:57:45 -0800 Subject: [PATCH 0308/1250] Const-check functions in a `const` impl --- src/librustc_mir/const_eval/fn_queries.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index 5706d435f7e..b4bbcd1ca4f 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -26,6 +26,8 @@ pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + // FIXME: check for `rustc_const_unstable` on the containing impl. This should be done by + // propagating it down so it is return by the `lookup_const_stability` query. if tcx.is_const_fn_raw(def_id) { let const_stab = tcx.lookup_const_stability(def_id)?; if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None } @@ -111,7 +113,18 @@ pub fn provide(providers: &mut Providers<'_>) { if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) { whitelisted } else if let Some(fn_like) = FnLikeNode::from_node(node) { - fn_like.constness() == hir::Constness::Const + if fn_like.constness() == hir::Constness::Const { + return true; + } + + // If the function itself is not annotated with `const`, it may still be a `const fn` + // if it resides in a const trait impl. + let parent_id = tcx.hir().get_parent_did(hir_id); + if def_id != parent_id && !parent_id.is_top_level_module() { + is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id)) + } else { + false + } } else if let hir::Node::Ctor(_) = node { true } else { From 5e422efba1be879633c7be7ad178915f2ace7f04 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 3 Feb 2020 15:02:30 -0800 Subject: [PATCH 0309/1250] Remove "not yet implemented" warning --- src/librustc_ast_lowering/item.rs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index e0db8606bc2..ad7221b16b2 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -66,15 +66,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> { if let Some(hir_id) = item_hir_id { self.lctx.with_parent_item_lifetime_defs(hir_id, |this| { let this = &mut ItemLowerer { lctx: this }; - if let ItemKind::Impl { constness, ref of_trait, .. } = item.kind { - if let Const::Yes(span) = constness { - this.lctx - .diagnostic() - .struct_span_err(item.span, "const trait impls are not yet implemented") - .span_label(span, "const because of this") - .emit(); - } - + if let ItemKind::Impl { ref of_trait, .. } = item.kind { this.with_trait_impl_ref(of_trait, |this| visit::walk_item(this, item)); } else { visit::walk_item(this, item); From 7a019b1bd2b13993bb2039053d815df02504083e Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Feb 2020 14:03:16 -0800 Subject: [PATCH 0310/1250] Check for trait methods on concrete types in const checking --- .../transform/check_consts/validation.rs | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 167d8145c03..1a1c34e1c67 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -4,7 +4,7 @@ use rustc::middle::lang_items; use rustc::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; use rustc::ty::cast::CastTy; -use rustc::ty::{self, TyCtxt}; +use rustc::ty::{self, Instance, InstanceDef, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir::{def_id::DefId, HirId}; use rustc_index::bit_set::BitSet; @@ -501,8 +501,8 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { TerminatorKind::Call { func, .. } => { let fn_ty = func.ty(*self.body, self.tcx); - let def_id = match fn_ty.kind { - ty::FnDef(def_id, _) => def_id, + let (def_id, substs) = match fn_ty.kind { + ty::FnDef(def_id, substs) => (def_id, substs), ty::FnPtr(_) => { self.check_op(ops::FnCallIndirect); @@ -519,6 +519,20 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { return; } + // See if this is a trait method for a concrete type whose impl of that trait is + // `const`. + if self.tcx.features().const_trait_impl { + let instance = Instance::resolve(self.tcx, self.param_env, def_id, substs); + debug!("Resolving ({:?}) -> {:?}", def_id, instance); + if let Some(func) = instance { + if let InstanceDef::Item(def_id) = func.def { + if is_const_fn(self.tcx, def_id) { + return; + } + } + } + } + if is_lang_panic_fn(self.tcx, def_id) { self.check_op(ops::Panic); } else if let Some(feature) = is_unstable_const_fn(self.tcx, def_id) { From 323ff193b8eda1c89eada54a1b3ac5c20d9e24c7 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 4 Feb 2020 14:03:37 -0800 Subject: [PATCH 0311/1250] Add tests for calling trait methods on concrete types --- .../call-const-trait-method.rs | 30 +++++++++++++++++++ .../call-const-trait-method.stderr | 9 ++++++ .../const-check-fns-in-const-impl.rs | 16 ++++++++++ .../const-check-fns-in-const-impl.stderr | 12 ++++++++ .../feature-gate.gated.stderr | 10 +++---- .../rfc-2632-const-trait-impl/feature-gate.rs | 5 ++-- .../feature-gate.stock.stderr | 12 ++------ .../inherent-impl.rs | 2 -- .../inherent-impl.stderr | 20 ++----------- 9 files changed, 78 insertions(+), 38 deletions(-) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs new file mode 100644 index 00000000000..ed6c07e4653 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs @@ -0,0 +1,30 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl)] +#![feature(const_fn)] + +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +impl Plus for u32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) +} + +pub const fn add_u32(a: u32, b: u32) -> u32 { + a.plus(b) + //~^ ERROR calls in constant functions are limited to constant functions +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr new file mode 100644 index 00000000000..7216876c83a --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr @@ -0,0 +1,9 @@ +error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants + --> $DIR/call-const-trait-method.rs:26:5 + | +LL | a.plus(b) + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0015`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs new file mode 100644 index 00000000000..cad4f69033b --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -0,0 +1,16 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl)] + +struct S; +trait T { + fn foo(); +} + +fn non_const() {} + +impl const T for S { + fn foo() { non_const() } + //~^ ERROR +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr new file mode 100644 index 00000000000..8c220dc44ab --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -0,0 +1,12 @@ +error[E0723]: can only call other `const fn` within a `const fn`, but `const non_const` is not stable as `const fn` + --> $DIR/const-check-fns-in-const-impl.rs:12:16 + | +LL | fn foo() { non_const() } + | ^^^^^^^^^^^ + | + = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0723`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr index 061af3c94b4..d1ab99e33e9 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.gated.stderr @@ -1,10 +1,8 @@ -error: const trait impls are not yet implemented - --> $DIR/feature-gate.rs:9:1 +error: fatal error triggered by #[rustc_error] + --> $DIR/feature-gate.rs:14:1 | -LL | impl const T for S {} - | ^^^^^-----^^^^^^^^^^^ - | | - | const because of this +LL | fn main() {} + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs index 49b6c0926c5..d9772431941 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.rs @@ -3,11 +3,12 @@ #![cfg_attr(gated, feature(const_trait_impl))] #![allow(incomplete_features)] +#![feature(rustc_attrs)] struct S; trait T {} impl const T for S {} //[stock]~^ ERROR const trait impls are experimental -//[stock,gated]~^^ ERROR const trait impls are not yet implemented -fn main() {} +#[rustc_error] +fn main() {} //[gated]~ ERROR fatal error triggered by #[rustc_error] diff --git a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr index cfe226ea7a7..724090e49cd 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/feature-gate.stock.stderr @@ -1,5 +1,5 @@ error[E0658]: const trait impls are experimental - --> $DIR/feature-gate.rs:9:6 + --> $DIR/feature-gate.rs:10:6 | LL | impl const T for S {} | ^^^^^ @@ -7,14 +7,6 @@ LL | impl const T for S {} = note: see issue #67792 for more information = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable -error: const trait impls are not yet implemented - --> $DIR/feature-gate.rs:9:1 - | -LL | impl const T for S {} - | ^^^^^-----^^^^^^^^^^^ - | | - | const because of this - -error: aborting due to 2 previous errors +error: aborting due to previous error For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs index 7f064c0c53a..04123a532bd 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.rs @@ -8,10 +8,8 @@ trait T {} impl const S {} //~^ ERROR inherent impls cannot be `const` -//~| ERROR const trait impls are not yet implemented impl const T {} //~^ ERROR inherent impls cannot be `const` -//~| ERROR const trait impls are not yet implemented fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr index bdc95ff2a57..3ea58a3728a 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -9,7 +9,7 @@ LL | impl const S {} = note: only trait implementations may be annotated with `const` error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:13:1 + --> $DIR/inherent-impl.rs:12:1 | LL | impl const T {} | ^^^^^-----^^^^^ @@ -18,21 +18,5 @@ LL | impl const T {} | = note: only trait implementations may be annotated with `const` -error: const trait impls are not yet implemented - --> $DIR/inherent-impl.rs:9:1 - | -LL | impl const S {} - | ^^^^^-----^^^^^ - | | - | const because of this - -error: const trait impls are not yet implemented - --> $DIR/inherent-impl.rs:13:1 - | -LL | impl const T {} - | ^^^^^-----^^^^^ - | | - | const because of this - -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors From d6d6d25c343fb4fdf6c853bd23524a77efc4c53b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 5 Feb 2020 09:35:32 -0800 Subject: [PATCH 0312/1250] Split const trait method test and impl `ops::Add` --- ...hod.rs => call-const-trait-method-fail.rs} | 2 +- ...rr => call-const-trait-method-fail.stderr} | 2 +- .../call-const-trait-method-pass.rs | 41 +++++++++++++++++++ 3 files changed, 43 insertions(+), 2 deletions(-) rename src/test/ui/rfc-2632-const-trait-impl/{call-const-trait-method.rs => call-const-trait-method-fail.rs} (96%) rename src/test/ui/rfc-2632-const-trait-impl/{call-const-trait-method.stderr => call-const-trait-method-fail.stderr} (84%) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs similarity index 96% rename from src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs rename to src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs index ed6c07e4653..8e6ef12810c 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.rs @@ -19,7 +19,7 @@ impl Plus for u32 { } pub const fn add_i32(a: i32, b: i32) -> i32 { - a.plus(b) + a.plus(b) // ok } pub const fn add_u32(a: u32, b: u32) -> u32 { diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr similarity index 84% rename from src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr rename to src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr index 7216876c83a..0c320d54c76 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr @@ -1,5 +1,5 @@ error[E0015]: calls in constant functions are limited to constant functions, tuple structs and tuple variants - --> $DIR/call-const-trait-method.rs:26:5 + --> $DIR/call-const-trait-method-fail.rs:26:5 | LL | a.plus(b) | ^^^^^^^^^ diff --git a/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs new file mode 100644 index 00000000000..6a2112ea554 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/call-const-trait-method-pass.rs @@ -0,0 +1,41 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(const_trait_impl)] +#![feature(const_fn)] + +struct Int(i32); + +impl const std::ops::Add for Int { + type Output = Int; + + fn add(self, rhs: Self) -> Self { + Int(self.0.plus(rhs.0)) + } +} + +impl const PartialEq for Int { + fn eq(&self, rhs: &Self) -> bool { + self.0 == rhs.0 + } +} + +pub trait Plus { + fn plus(self, rhs: Self) -> Self; +} + +impl const Plus for i32 { + fn plus(self, rhs: Self) -> Self { + self + rhs + } +} + +pub const fn add_i32(a: i32, b: i32) -> i32 { + a.plus(b) +} + +const ADD_INT: Int = Int(1i32) + Int(2i32); + +fn main() { + assert!(ADD_INT == Int(3i32)); +} From 70f78797d5f3e4ea7fb4ae853dc0f368007c56a2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 5 Feb 2020 09:40:47 -0800 Subject: [PATCH 0313/1250] Ensure const impl cannot coexist with non-const impl --- .../const-and-non-const-impl.rs | 33 ++++++++++++++++++ .../const-and-non-const-impl.stderr | 34 +++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs new file mode 100644 index 00000000000..e148ad9a0ee --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.rs @@ -0,0 +1,33 @@ +#![allow(incomplete_features)] +#![feature(const_trait_impl)] + +pub struct Int(i32); + +impl const std::ops::Add for i32 { + //~^ ERROR conflicting implementations of trait + //~| ERROR only traits defined in the current crate can be implemented for arbitrary types + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + +impl std::ops::Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +impl const std::ops::Add for Int { + //~^ ERROR conflicting implementations of trait + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr new file mode 100644 index 00000000000..b57472d9595 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/const-and-non-const-impl.stderr @@ -0,0 +1,34 @@ +error[E0119]: conflicting implementations of trait `std::ops::Add` for type `i32`: + --> $DIR/const-and-non-const-impl.rs:6:1 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl std::ops::Add for i32; + +error[E0119]: conflicting implementations of trait `std::ops::Add` for type `Int`: + --> $DIR/const-and-non-const-impl.rs:24:1 + | +LL | impl std::ops::Add for Int { + | -------------------------- first implementation here +... +LL | impl const std::ops::Add for Int { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Int` + +error[E0117]: only traits defined in the current crate can be implemented for arbitrary types + --> $DIR/const-and-non-const-impl.rs:6:1 + | +LL | impl const std::ops::Add for i32 { + | ^^^^^^^^^^^-------------^^^^^--- + | | | | + | | | `i32` is not defined in the current crate + | | `i32` is not defined in the current crate + | impl doesn't use only types from inside the current crate + | + = note: define and implement a trait or new type instead + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0117, E0119. +For more information about an error, try `rustc --explain E0117`. From 0a5abcac7f43dde694ae202678b8271e8b57279f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 7 Feb 2020 09:56:56 -0800 Subject: [PATCH 0314/1250] Use early return when forbidding unstable attrs --- src/librustc_passes/stability.rs | 246 ++++++++++++++++--------------- 1 file changed, 129 insertions(+), 117 deletions(-) diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 99f005c29e8..7d93666b1a6 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -58,144 +58,156 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { ) where F: FnOnce(&mut Self), { - if self.tcx.features().staged_api { - // This crate explicitly wants staged API. - debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); - if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { - self.tcx.sess.span_err( - item_sp, - "`#[deprecated]` cannot be used in staged API; \ - use `#[rustc_deprecated]` instead", - ); - } - let (stab, const_stab) = - attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); - if let Some(const_stab) = const_stab { - let const_stab = self.tcx.intern_const_stability(const_stab); - self.index.const_stab_map.insert(hir_id, const_stab); + if !self.tcx.features().staged_api { + self.forbid_staged_api_attrs(hir_id, attrs, item_sp, kind, visit_children); + return; + } + + // This crate explicitly wants staged API. + debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); + if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { + self.tcx.sess.span_err( + item_sp, + "`#[deprecated]` cannot be used in staged API; \ + use `#[rustc_deprecated]` instead", + ); + } + let (stab, const_stab) = + attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); + if let Some(const_stab) = const_stab { + let const_stab = self.tcx.intern_const_stability(const_stab); + self.index.const_stab_map.insert(hir_id, const_stab); + } + if let Some(mut stab) = stab { + // Error if prohibited, or can't inherit anything from a container. + if kind == AnnotationKind::Prohibited + || (kind == AnnotationKind::Container + && stab.level.is_stable() + && stab.rustc_depr.is_none()) + { + self.tcx.sess.span_err(item_sp, "This stability annotation is useless"); } - if let Some(mut stab) = stab { - // Error if prohibited, or can't inherit anything from a container. - if kind == AnnotationKind::Prohibited - || (kind == AnnotationKind::Container - && stab.level.is_stable() - && stab.rustc_depr.is_none()) - { - self.tcx.sess.span_err(item_sp, "This stability annotation is useless"); - } - debug!("annotate: found {:?}", stab); - // If parent is deprecated and we're not, inherit this by merging - // deprecated_since and its reason. - if let Some(parent_stab) = self.parent_stab { - if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() { - stab.rustc_depr = parent_stab.rustc_depr - } + debug!("annotate: found {:?}", stab); + // If parent is deprecated and we're not, inherit this by merging + // deprecated_since and its reason. + if let Some(parent_stab) = self.parent_stab { + if parent_stab.rustc_depr.is_some() && stab.rustc_depr.is_none() { + stab.rustc_depr = parent_stab.rustc_depr } + } - let stab = self.tcx.intern_stability(stab); - - // Check if deprecated_since < stable_since. If it is, - // this is *almost surely* an accident. - if let ( - &Some(attr::RustcDeprecation { since: dep_since, .. }), - &attr::Stable { since: stab_since }, - ) = (&stab.rustc_depr, &stab.level) + let stab = self.tcx.intern_stability(stab); + + // Check if deprecated_since < stable_since. If it is, + // this is *almost surely* an accident. + if let ( + &Some(attr::RustcDeprecation { since: dep_since, .. }), + &attr::Stable { since: stab_since }, + ) = (&stab.rustc_depr, &stab.level) + { + // Explicit version of iter::order::lt to handle parse errors properly + for (dep_v, stab_v) in + dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) { - // Explicit version of iter::order::lt to handle parse errors properly - for (dep_v, stab_v) in - dep_since.as_str().split('.').zip(stab_since.as_str().split('.')) - { - if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), stab_v.parse()) { - match dep_v.cmp(&stab_v) { - Ordering::Less => { - self.tcx.sess.span_err( - item_sp, - "An API can't be stabilized \ - after it is deprecated", - ); - break; - } - Ordering::Equal => continue, - Ordering::Greater => break, + if let (Ok(dep_v), Ok(stab_v)) = (dep_v.parse::(), stab_v.parse()) { + match dep_v.cmp(&stab_v) { + Ordering::Less => { + self.tcx.sess.span_err( + item_sp, + "An API can't be stabilized \ + after it is deprecated", + ); + break; } - } else { - // Act like it isn't less because the question is now nonsensical, - // and this makes us not do anything else interesting. - self.tcx.sess.span_err( - item_sp, - "Invalid stability or deprecation \ - version found", - ); - break; + Ordering::Equal => continue, + Ordering::Greater => break, } + } else { + // Act like it isn't less because the question is now nonsensical, + // and this makes us not do anything else interesting. + self.tcx.sess.span_err( + item_sp, + "Invalid stability or deprecation \ + version found", + ); + break; } } + } - self.index.stab_map.insert(hir_id, stab); + self.index.stab_map.insert(hir_id, stab); - let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); - visit_children(self); - self.parent_stab = orig_parent_stab; - } else { - debug!("annotate: not found, parent = {:?}", self.parent_stab); - if let Some(stab) = self.parent_stab { - if stab.level.is_unstable() { - self.index.stab_map.insert(hir_id, stab); - } - } - visit_children(self); - } + let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); + visit_children(self); + self.parent_stab = orig_parent_stab; } else { - // Emit errors for non-staged-api crates. - let unstable_attrs = [ - sym::unstable, - sym::stable, - sym::rustc_deprecated, - sym::rustc_const_unstable, - sym::rustc_const_stable, - ]; - for attr in attrs { - let name = attr.name_or_empty(); - if unstable_attrs.contains(&name) { - attr::mark_used(attr); - struct_span_err!( - self.tcx.sess, - attr.span, - E0734, - "stability attributes may not be used outside of the standard library", - ) - .emit(); - } - } - - // Propagate unstability. This can happen even for non-staged-api crates in case - // -Zforce-unstable-if-unmarked is set. + debug!("annotate: not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } + visit_children(self); + } + } - if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { - if kind == AnnotationKind::Prohibited { - self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); - } + fn forbid_staged_api_attrs( + &mut self, + hir_id: HirId, + attrs: &[Attribute], + item_sp: Span, + kind: AnnotationKind, + visit_children: impl FnOnce(&mut Self), + ) { + // Emit errors for non-staged-api crates. + let unstable_attrs = [ + sym::unstable, + sym::stable, + sym::rustc_deprecated, + sym::rustc_const_unstable, + sym::rustc_const_stable, + ]; + for attr in attrs { + let name = attr.name_or_empty(); + if unstable_attrs.contains(&name) { + attr::mark_used(attr); + struct_span_err!( + self.tcx.sess, + attr.span, + E0734, + "stability attributes may not be used outside of the standard library", + ) + .emit(); + } + } - // `Deprecation` is just two pointers, no need to intern it - let depr_entry = DeprecationEntry::local(depr, hir_id); - self.index.depr_map.insert(hir_id, depr_entry.clone()); - - let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry)); - visit_children(self); - self.parent_depr = orig_parent_depr; - } else if let Some(parent_depr) = self.parent_depr.clone() { - self.index.depr_map.insert(hir_id, parent_depr); - visit_children(self); - } else { - visit_children(self); + // Propagate unstability. This can happen even for non-staged-api crates in case + // -Zforce-unstable-if-unmarked is set. + if let Some(stab) = self.parent_stab { + if stab.level.is_unstable() { + self.index.stab_map.insert(hir_id, stab); } } + + if let Some(depr) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { + if kind == AnnotationKind::Prohibited { + self.tcx.sess.span_err(item_sp, "This deprecation annotation is useless"); + } + + // `Deprecation` is just two pointers, no need to intern it + let depr_entry = DeprecationEntry::local(depr, hir_id); + self.index.depr_map.insert(hir_id, depr_entry.clone()); + + let orig_parent_depr = replace(&mut self.parent_depr, Some(depr_entry)); + visit_children(self); + self.parent_depr = orig_parent_depr; + } else if let Some(parent_depr) = self.parent_depr.clone() { + self.index.depr_map.insert(hir_id, parent_depr); + visit_children(self); + } else { + visit_children(self); + } } } From 8e7609b9fe12f4a972a55afb75b1a0098ada1378 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 7 Feb 2020 10:24:22 -0800 Subject: [PATCH 0315/1250] Propagate `rustc_const_unstable` to children --- src/librustc_passes/stability.rs | 65 ++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 11 deletions(-) diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 7d93666b1a6..d9296deb1d9 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -9,7 +9,7 @@ use rustc::session::parse::feature_err; use rustc::session::Session; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; -use rustc_attr::{self as attr, Stability}; +use rustc_attr::{self as attr, ConstStability, Stability}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; @@ -41,6 +41,7 @@ struct Annotator<'a, 'tcx> { tcx: TyCtxt<'tcx>, index: &'a mut Index<'tcx>, parent_stab: Option<&'tcx Stability>, + parent_const_stab: Option<&'tcx ConstStability>, parent_depr: Option, in_trait_impl: bool, } @@ -64,6 +65,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } // This crate explicitly wants staged API. + debug!("annotate(id = {:?}, attrs = {:?})", hir_id, attrs); if let Some(..) = attr::find_deprecation(&self.tcx.sess.parse_sess, attrs, item_sp) { self.tcx.sess.span_err( @@ -72,13 +74,25 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { use `#[rustc_deprecated]` instead", ); } - let (stab, const_stab) = - attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); - if let Some(const_stab) = const_stab { + + let (stab, const_stab) = attr::find_stability(&self.tcx.sess.parse_sess, attrs, item_sp); + + let const_stab = const_stab.map(|const_stab| { let const_stab = self.tcx.intern_const_stability(const_stab); self.index.const_stab_map.insert(hir_id, const_stab); + const_stab + }); + + if const_stab.is_none() { + debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab); + if let Some(parent) = self.parent_const_stab { + if parent.level.is_unstable() { + self.index.const_stab_map.insert(hir_id, parent); + } + } } - if let Some(mut stab) = stab { + + let stab = stab.map(|mut stab| { // Error if prohibited, or can't inherit anything from a container. if kind == AnnotationKind::Prohibited || (kind == AnnotationKind::Container @@ -137,18 +151,46 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } self.index.stab_map.insert(hir_id, stab); + stab + }); - let orig_parent_stab = replace(&mut self.parent_stab, Some(stab)); - visit_children(self); - self.parent_stab = orig_parent_stab; - } else { - debug!("annotate: not found, parent = {:?}", self.parent_stab); + if stab.is_none() { + debug!("annotate: stab not found, parent = {:?}", self.parent_stab); if let Some(stab) = self.parent_stab { if stab.level.is_unstable() { self.index.stab_map.insert(hir_id, stab); } } - visit_children(self); + } + + self.recurse_with_stability_attrs(stab, const_stab, visit_children); + } + + fn recurse_with_stability_attrs( + &mut self, + stab: Option<&'tcx Stability>, + const_stab: Option<&'tcx ConstStability>, + f: impl FnOnce(&mut Self), + ) { + // These will be `Some` if this item changes the corresponding stability attribute. + let mut replaced_parent_stab = None; + let mut replaced_parent_const_stab = None; + + if let Some(stab) = stab { + replaced_parent_stab = Some(replace(&mut self.parent_stab, Some(stab))); + } + if let Some(const_stab) = const_stab { + replaced_parent_const_stab = + Some(replace(&mut self.parent_const_stab, Some(const_stab))); + } + + f(self); + + if let Some(orig_parent_stab) = replaced_parent_stab { + self.parent_stab = orig_parent_stab; + } + if let Some(orig_parent_const_stab) = replaced_parent_const_stab { + self.parent_const_stab = orig_parent_const_stab; } } @@ -388,6 +430,7 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { tcx, index: &mut index, parent_stab: None, + parent_const_stab: None, parent_depr: None, in_trait_impl: false, }; From 4992eb2c6fab0c7eb4a841385607723620a38cf6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 7 Feb 2020 11:06:12 -0800 Subject: [PATCH 0316/1250] Test `rustc_const_unstable` on trait fns --- .../ui/rfc-2632-const-trait-impl/stability.rs | 33 +++++++++++++++++++ .../stability.stderr | 12 +++++++ 2 files changed, 45 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/stability.rs create mode 100644 src/test/ui/rfc-2632-const-trait-impl/stability.stderr diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs new file mode 100644 index 00000000000..36cfaff2ffa --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.rs @@ -0,0 +1,33 @@ +#![allow(incomplete_features)] +#![feature(allow_internal_unstable)] +#![feature(const_add)] +#![feature(const_trait_impl)] +#![feature(staged_api)] + +pub struct Int(i32); + +#[rustc_const_unstable(feature = "const_add", issue = "none")] +impl const std::ops::Add for Int { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + Int(self.0 + rhs.0) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +pub const fn foo() -> Int { + Int(1i32) + Int(2i32) + //~^ ERROR can only call other `const fn` within a `const fn` +} + +// ok +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_unstable(feature = "bar", issue = "none")] +pub const fn bar() -> Int { + Int(1i32) + Int(2i32) +} + + +fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr new file mode 100644 index 00000000000..ce3bada01e8 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -0,0 +1,12 @@ +error[E0723]: can only call other `const fn` within a `const fn`, but `const ::add` is not stable as `const fn` + --> $DIR/stability.rs:21:5 + | +LL | Int(1i32) + Int(2i32) + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = help: add `#![feature(const_fn)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0723`. From c8f0abb51c59ee4c704eda1bb2a7e9e70173b074 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 7 Feb 2020 11:06:44 -0800 Subject: [PATCH 0317/1250] Add ignored test for associated types in const impl --- .../rfc-2632-const-trait-impl/assoc-type.rs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs new file mode 100644 index 00000000000..194929fa287 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/assoc-type.rs @@ -0,0 +1,28 @@ +// ignore-test + +// FIXME: This test should fail since, within a const impl of `Foo`, the bound on `Foo::Bar` should +// require a const impl of `Add` for the associated type. + +#![allow(incomplete_features)] +#![feature(const_trait_impl)] +#![feature(const_fn)] + +struct NonConstAdd(i32); + +impl std::ops::Add for NonConstAdd { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + NonConstAdd(self.0 + rhs.0) + } +} + +trait Foo { + type Bar: std::ops::Add; +} + +impl const Foo for NonConstAdd { + type Bar = NonConstAdd; +} + +fn main() {} From 9a3682438d3104529d080050c6fd3744b2b4d3b6 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 7 Feb 2020 12:32:49 -0800 Subject: [PATCH 0318/1250] Remove outdated FIXME --- src/librustc_mir/const_eval/fn_queries.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index b4bbcd1ca4f..1f7eb976902 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -26,8 +26,6 @@ pub fn is_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - // FIXME: check for `rustc_const_unstable` on the containing impl. This should be done by - // propagating it down so it is return by the `lookup_const_stability` query. if tcx.is_const_fn_raw(def_id) { let const_stab = tcx.lookup_const_stability(def_id)?; if const_stab.level.is_unstable() { Some(const_stab.feature) } else { None } From 160e6304e8e7971d38787e8ca81f154e31f5b772 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 10 Feb 2020 11:26:40 -0800 Subject: [PATCH 0319/1250] Add passing test for `Add` on generic struct --- .../generic-bound.rs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs diff --git a/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs new file mode 100644 index 00000000000..7829ffe2a38 --- /dev/null +++ b/src/test/ui/rfc-2632-const-trait-impl/generic-bound.rs @@ -0,0 +1,32 @@ +// run-pass + +#![allow(incomplete_features)] +#![feature(const_trait_impl)] +#![feature(const_fn)] + +use std::marker::PhantomData; + +struct S(PhantomData); + +impl Copy for S {} +impl Clone for S { + fn clone(&self) -> Self { + S(PhantomData) + } +} + +impl const std::ops::Add for S { + type Output = Self; + + fn add(self, _: Self) -> Self { + S(std::marker::PhantomData) + } +} + +const fn twice(arg: S) -> S { + arg + arg +} + +fn main() { + let _ = twice(S(PhantomData::)); +} From cb81712d10f4af3a55dd2368d9714daa425fcf22 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 15:45:14 -0800 Subject: [PATCH 0320/1250] Make `fn_queries` helpers module-private --- src/librustc_mir/const_eval/fn_queries.rs | 149 +++++++++++----------- 1 file changed, 74 insertions(+), 75 deletions(-) diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index 1f7eb976902..27efcd50841 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -82,94 +82,93 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { } } -pub fn provide(providers: &mut Providers<'_>) { - /// Const evaluability whitelist is here to check evaluability at the - /// top level beforehand. - fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if tcx.is_closure(def_id) { - return None; - } - - match tcx.fn_sig(def_id).abi() { - Abi::RustIntrinsic | Abi::PlatformIntrinsic => { - Some(tcx.lookup_const_stability(def_id).is_some()) - } - _ => None, - } +pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { + let parent_id = tcx.hir().get_parent_did(hir_id); + if !parent_id.is_top_level_module() { + is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id)) + } else { + false } +} - /// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether - /// said intrinsic is on the whitelist for being const callable. - fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - let hir_id = tcx - .hir() - .as_local_hir_id(def_id) - .expect("Non-local call to local provider is_const_fn"); - - let node = tcx.hir().get(hir_id); +/// Checks whether the function has a `const` modifier or, in case it is an intrinsic, whether +/// said intrinsic is on the whitelist for being const callable. +fn is_const_fn_raw(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + let hir_id = + tcx.hir().as_local_hir_id(def_id).expect("Non-local call to local provider is_const_fn"); - if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) { - whitelisted - } else if let Some(fn_like) = FnLikeNode::from_node(node) { - if fn_like.constness() == hir::Constness::Const { - return true; - } + let node = tcx.hir().get(hir_id); - // If the function itself is not annotated with `const`, it may still be a `const fn` - // if it resides in a const trait impl. - let parent_id = tcx.hir().get_parent_did(hir_id); - if def_id != parent_id && !parent_id.is_top_level_module() { - is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id)) - } else { - false - } - } else if let hir::Node::Ctor(_) = node { - true - } else { - false + if let Some(whitelisted) = is_const_intrinsic(tcx, def_id) { + whitelisted + } else if let Some(fn_like) = FnLikeNode::from_node(node) { + if fn_like.constness() == hir::Constness::Const { + return true; } + + // If the function itself is not annotated with `const`, it may still be a `const fn` + // if it resides in a const trait impl. + is_parent_const_impl_raw(tcx, hir_id) + } else if let hir::Node::Ctor(_) = node { + true + } else { + false } +} - /// Checks whether the given item is an `impl` that has a `const` modifier. - fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); - let node = tcx.hir().get(hir_id); - matches!( - node, - hir::Node::Item(hir::Item { - kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. }, - .. - }) - ) +/// Const evaluability whitelist is here to check evaluability at the +/// top level beforehand. +fn is_const_intrinsic(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + if tcx.is_closure(def_id) { + return None; } - fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - is_const_fn(tcx, def_id) - && match tcx.lookup_const_stability(def_id) { - Some(stab) => { - if cfg!(debug_assertions) && stab.promotable { - let sig = tcx.fn_sig(def_id); - assert_eq!( - sig.unsafety(), - hir::Unsafety::Normal, - "don't mark const unsafe fns as promotable", - // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682 - ); - } - stab.promotable + match tcx.fn_sig(def_id).abi() { + Abi::RustIntrinsic | Abi::PlatformIntrinsic => { + Some(tcx.lookup_const_stability(def_id).is_some()) + } + _ => None, + } +} + +/// Checks whether the given item is an `impl` that has a `const` modifier. +fn is_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); + let node = tcx.hir().get(hir_id); + matches!( + node, + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl { constness: hir::Constness::Const, .. }, + .. + }) + ) +} + +fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + is_const_fn(tcx, def_id) + && match tcx.lookup_const_stability(def_id) { + Some(stab) => { + if cfg!(debug_assertions) && stab.promotable { + let sig = tcx.fn_sig(def_id); + assert_eq!( + sig.unsafety(), + hir::Unsafety::Normal, + "don't mark const unsafe fns as promotable", + // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682 + ); } - None => false, + stab.promotable } - } + None => false, + } +} - fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - is_const_fn(tcx, def_id) - && tcx - .lookup_const_stability(def_id) - .map(|stab| stab.allow_const_fn_ptr) - .unwrap_or(false) - } +fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { + is_const_fn(tcx, def_id) + && tcx.lookup_const_stability(def_id).map(|stab| stab.allow_const_fn_ptr).unwrap_or(false) +} +pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { is_const_fn_raw, is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)), From 5f06ce2c0f3938dd69a0676c7abe2243046c2f09 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 15:45:39 -0800 Subject: [PATCH 0321/1250] Prevent const trait methods from being marked stable --- src/librustc_mir/transform/qualify_min_const_fn.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index b12f4ce3269..5a99ee27301 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -10,6 +10,14 @@ use std::borrow::Cow; type McfResult = Result<(), (Span, Cow<'static, str>)>; pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -> McfResult { + // Prevent const trait methods from being annotated as `stable`. + if tcx.features().staged_api { + let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); + if crate::const_eval::is_parent_const_impl_raw(tcx, hir_id) { + return Err((body.span, "trait methods cannot be stable const fn".into())); + } + } + let mut current = def_id; loop { let predicates = tcx.predicates_of(current); From d194676667f256e08dfb9fbc536d53d92bf8910f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 21:28:56 -0800 Subject: [PATCH 0322/1250] Remove special case for `simd_shuffle` arg promotion After rust-lang/stdarch#825, these intrinsics are now defined with `#[rustc_args_required_const(2)]`, so the special-case is no longer necessary. --- src/librustc_mir/transform/promote_consts.rs | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index a5d59860c3d..9db9ab0de0b 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -24,7 +24,6 @@ use rustc_span::{Span, DUMMY_SP}; use syntax::ast::LitKind; use rustc_index::vec::{Idx, IndexVec}; -use rustc_target::spec::abi::Abi; use std::cell::Cell; use std::{cmp, iter, mem, usize}; @@ -218,17 +217,6 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { if let TerminatorKind::Call { ref func, .. } = *kind { if let ty::FnDef(def_id, _) = func.ty(self.body, self.tcx).kind { - let fn_sig = self.tcx.fn_sig(def_id); - if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { - let name = self.tcx.item_name(def_id); - // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. - if name.as_str().starts_with("simd_shuffle") { - self.candidates.push(Candidate::Argument { bb: location.block, index: 2 }); - - return; // Don't double count `simd_shuffle` candidates - } - } - if let Some(constant_args) = args_required_const(self.tcx, def_id) { for index in constant_args { self.candidates.push(Candidate::Argument { bb: location.block, index }); From f581b559a3c9f0c33df09312678dad836334ae22 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 21:32:38 -0800 Subject: [PATCH 0323/1250] Remove mention of `simd_shuffle` promotion from comments --- src/librustc_mir/const_eval/eval_queries.rs | 4 ++-- src/librustc_mir/transform/promote_consts.rs | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 4d5464f774f..1cec5d30e9b 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -72,8 +72,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( Ok(ret) } -/// The `InterpCx` is only meant to be used to do field and index projections into constants for -/// `simd_shuffle` and const patterns in match arms. +/// The `InterpCx` is only meant to be used to do field and index projections into promoteds +/// and const patterns in match arms. /// /// The function containing the `match` that is currently being analyzed may have generic bounds /// that inform us about the generic bounds of the constant. E.g., using an associated constant diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 9db9ab0de0b..a11ee57f465 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -105,11 +105,10 @@ pub enum Candidate { /// Promotion of the `x` in `[x; 32]`. Repeat(Location), - /// Currently applied to function calls where the callee has the unstable - /// `#[rustc_args_required_const]` attribute as well as the SIMD shuffle - /// intrinsic. The intrinsic requires the arguments are indeed constant and - /// the attribute currently provides the semantic requirement that arguments - /// must be constant. + /// Function calls where the callee has the unstable + /// `#[rustc_args_required_const]` attribute. The attribute requires that + /// the arguments be constant, usually because they are encoded as an + /// immediate operand in a platform intrinsic. Argument { bb: BasicBlock, index: usize }, } @@ -718,8 +717,7 @@ pub fn validate_candidates( .filter(|&candidate| { validator.explicit = candidate.forces_explicit_promotion(); - // FIXME(eddyb) also emit the errors for shuffle indices - // and `#[rustc_args_required_const]` arguments here. + // FIXME(eddyb) also emit the errors for `#[rustc_args_required_const]` arguments here. let is_promotable = validator.validate_candidate(candidate).is_ok(); match candidate { From 139c3cab28ce19f91364aca693a3c091b37a3ef8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 19 Feb 2020 16:54:36 +1100 Subject: [PATCH 0324/1250] Inline some encoding and decoding methods. This is a small performance win. --- src/librustc/ty/codec.rs | 1 + src/librustc/ty/query/on_disk_cache.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/librustc/ty/codec.rs b/src/librustc/ty/codec.rs index df1602b2ac4..c305999a64b 100644 --- a/src/librustc/ty/codec.rs +++ b/src/librustc/ty/codec.rs @@ -301,6 +301,7 @@ where macro_rules! __impl_decoder_methods { ($($name:ident -> $ty:ty;)*) => { $( + #[inline] fn $name(&mut self) -> Result<$ty, Self::Error> { self.opaque.$name() } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 45d95e97a9c..2f0f8e609c6 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -943,6 +943,7 @@ where macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { + #[inline] $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { self.encoder.$name(value) })* From b43dc806ae3d5fd11ff0bdea288cf16f4b1e4c13 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 23:17:21 -0800 Subject: [PATCH 0325/1250] Add `#[rustc_args_required_const]` to `simd_shuffle` tests --- src/test/incremental/issue-61530.rs | 3 +- src/test/ui/issues/issue-38074.rs | 3 +- .../simd-intrinsic-generic-elements.rs | 4 +++ .../simd-intrinsic-generic-elements.stderr | 30 +++++++++---------- .../simd-intrinsic-inlining-issue67557-ice.rs | 3 +- .../simd-intrinsic-inlining-issue67557.rs | 3 +- .../simd/simd-intrinsic-generic-elements.rs | 6 +++- 7 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/test/incremental/issue-61530.rs b/src/test/incremental/issue-61530.rs index 06b2957ac62..c9c600efed8 100644 --- a/src/test/incremental/issue-61530.rs +++ b/src/test/incremental/issue-61530.rs @@ -1,4 +1,4 @@ -#![feature(repr_simd, platform_intrinsics)] +#![feature(repr_simd, platform_intrinsics, rustc_attrs)] // revisions:rpass1 rpass2 @@ -6,6 +6,7 @@ struct I32x2(i32, i32); extern "platform-intrinsic" { + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/issues/issue-38074.rs b/src/test/ui/issues/issue-38074.rs index 214d6752cef..8f7905b31ec 100644 --- a/src/test/ui/issues/issue-38074.rs +++ b/src/test/ui/issues/issue-38074.rs @@ -1,9 +1,10 @@ // run-pass // ignore-emscripten FIXME(#45351) -#![feature(platform_intrinsics, repr_simd)] +#![feature(platform_intrinsics, repr_simd, rustc_attrs)] extern "platform-intrinsic" { + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs index 5929d05f4de..c9c9ab879f2 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs @@ -42,9 +42,13 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle3(x: T, y: T, idx: [u32; 3]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr index 78022c0c8bd..29916f85902 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr @@ -1,89 +1,89 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:55:9 + --> $DIR/simd-intrinsic-generic-elements.rs:59:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/simd-intrinsic-generic-elements.rs:57:9 + --> $DIR/simd-intrinsic-generic-elements.rs:61:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:59:9 + --> $DIR/simd-intrinsic-generic-elements.rs:63:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:62:9 + --> $DIR/simd-intrinsic-generic-elements.rs:66:9 | LL | simd_shuffle2::(0, 0, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:64:9 + --> $DIR/simd-intrinsic-generic-elements.rs:68:9 | LL | simd_shuffle3::(0, 0, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:66:9 + --> $DIR/simd-intrinsic-generic-elements.rs:70:9 | LL | simd_shuffle4::(0, 0, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:68:9 + --> $DIR/simd-intrinsic-generic-elements.rs:72:9 | LL | simd_shuffle8::(0, 0, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:71:9 + --> $DIR/simd-intrinsic-generic-elements.rs:75:9 | LL | simd_shuffle2::<_, f32x2>(x, x, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:73:9 + --> $DIR/simd-intrinsic-generic-elements.rs:77:9 | LL | simd_shuffle3::<_, f32x3>(x, x, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:75:9 + --> $DIR/simd-intrinsic-generic-elements.rs:79:9 | LL | simd_shuffle4::<_, f32x4>(x, x, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:77:9 + --> $DIR/simd-intrinsic-generic-elements.rs:81:9 | LL | simd_shuffle8::<_, f32x8>(x, x, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:80:9 + --> $DIR/simd-intrinsic-generic-elements.rs:84:9 | LL | simd_shuffle2::<_, i32x8>(x, x, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return type of length 3, found `i32x4` with length 4 - --> $DIR/simd-intrinsic-generic-elements.rs:82:9 + --> $DIR/simd-intrinsic-generic-elements.rs:86:9 | LL | simd_shuffle3::<_, i32x4>(x, x, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x3` with length 3 - --> $DIR/simd-intrinsic-generic-elements.rs:84:9 + --> $DIR/simd-intrinsic-generic-elements.rs:88:9 | LL | simd_shuffle4::<_, i32x3>(x, x, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/simd-intrinsic-generic-elements.rs:86:9 + --> $DIR/simd-intrinsic-generic-elements.rs:90:9 | LL | simd_shuffle8::<_, i32x2>(x, x, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs index 4c09ae25c5f..b03b0ef5089 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs @@ -3,9 +3,10 @@ // // run-pass // compile-flags: -Zmir-opt-level=3 -#![feature(platform_intrinsics, repr_simd)] +#![feature(platform_intrinsics, repr_simd, rustc_attrs)] extern "platform-intrinsic" { + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs index 7a0d955686b..2741dc13336 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs @@ -3,9 +3,10 @@ // // run-pass // compile-flags: -Zmir-opt-level=3 -#![feature(platform_intrinsics, repr_simd)] +#![feature(platform_intrinsics, repr_simd, rustc_attrs)] extern "platform-intrinsic" { + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/simd-intrinsic-generic-elements.rs index ea3d4b18944..abff59fea78 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-elements.rs @@ -1,7 +1,7 @@ // run-pass // ignore-emscripten FIXME(#45351) hits an LLVM assert -#![feature(repr_simd, platform_intrinsics)] +#![feature(repr_simd, platform_intrinsics, rustc_attrs)] #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] @@ -25,9 +25,13 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; + #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle3(x: T, y: T, idx: [u32; 3]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; + #[rustc_args_required_const(2)] fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; } From c899dc14011a67b127bf59622cb13b7ff4a11e9a Mon Sep 17 00:00:00 2001 From: jumbatm Date: Wed, 19 Feb 2020 19:57:32 +1000 Subject: [PATCH 0326/1250] Reword OpenOptions::{create, create_new} doc. --- src/libstd/fs.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index cff7bbe5ef1..09be3f13050 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -844,10 +844,7 @@ impl OpenOptions { self } - /// Sets the option for creating a new file. - /// - /// This option indicates whether a new file will be created if the file - /// does not yet already exist. + /// Sets the option to create a new file, or open it if it already exists. /// /// In order for the file to be created, [`write`] or [`append`] access must /// be used. @@ -868,11 +865,10 @@ impl OpenOptions { self } - /// Sets the option to always create a new file. + /// Sets the option to create a new file, failing if it already exists. /// - /// This option indicates whether a new file will be created. - /// No file is allowed to exist at the target location, also no (dangling) - /// symlink. + /// No file is allowed to exist at the target location, also no (dangling) symlink. In this + /// way, if the call succeeds, the file returned is guaranteed to be new. /// /// This option is useful because it is atomic. Otherwise between checking /// whether a file exists and creating a new one, the file may have been From 58bb47ebe5db54f54f5a45134110f73ff216bb36 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Feb 2020 11:25:41 +0100 Subject: [PATCH 0327/1250] avoid excessive number of revisions --- src/test/ui/consts/const-err2.default.stderr | 48 ------ src/test/ui/consts/const-err2.rs | 2 +- .../const-eval/promoted_errors.default.stderr | 72 --------- .../ui/consts/const-eval/promoted_errors.rs | 2 +- src/test/ui/consts/issue-64059.rs | 2 +- src/test/ui/consts/issue-69020.default.stderr | 30 ---- src/test/ui/consts/issue-69020.rs | 2 +- .../ui/issues/issue-8460-const.default.stderr | 150 ------------------ src/test/ui/issues/issue-8460-const.rs | 2 +- .../lint-exceeding-bitshifts.default.stderr | 146 ----------------- src/test/ui/lint/lint-exceeding-bitshifts.rs | 2 +- 11 files changed, 6 insertions(+), 452 deletions(-) delete mode 100644 src/test/ui/consts/const-err2.default.stderr delete mode 100644 src/test/ui/consts/const-eval/promoted_errors.default.stderr delete mode 100644 src/test/ui/consts/issue-69020.default.stderr delete mode 100644 src/test/ui/issues/issue-8460-const.default.stderr delete mode 100644 src/test/ui/lint/lint-exceeding-bitshifts.default.stderr diff --git a/src/test/ui/consts/const-err2.default.stderr b/src/test/ui/consts/const-err2.default.stderr deleted file mode 100644 index 5aeeec4bd14..00000000000 --- a/src/test/ui/consts/const-err2.default.stderr +++ /dev/null @@ -1,48 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:19:13 - | -LL | let a = -std::i8::MIN; - | ^^^^^^^^^^^^^ attempt to negate with overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:21:18 - | -LL | let a_i128 = -std::i128::MIN; - | ^^^^^^^^^^^^^^^ attempt to negate with overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:23:13 - | -LL | let b = 200u8 + 200u8 + 200u8; - | ^^^^^^^^^^^^^ attempt to add with overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:25:18 - | -LL | let b_i128 = std::i128::MIN - std::i128::MAX; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to subtract with overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:27:13 - | -LL | let c = 200u8 * 4; - | ^^^^^^^^^ attempt to multiply with overflow - -error: this arithmetic operation will overflow - --> $DIR/const-err2.rs:29:13 - | -LL | let d = 42u8 - (42u8 + 1); - | ^^^^^^^^^^^^^^^^^ attempt to subtract with overflow - -error: this operation will panic at runtime - --> $DIR/const-err2.rs:31:14 - | -LL | let _e = [5u8][1]; - | ^^^^^^^^ index out of bounds: the len is 1 but the index is 1 - | - = note: `#[deny(unconditional_panic)]` on by default - -error: aborting due to 7 previous errors - diff --git a/src/test/ui/consts/const-err2.rs b/src/test/ui/consts/const-err2.rs index 2c0cae0e451..2c6a987180b 100644 --- a/src/test/ui/consts/const-err2.rs +++ b/src/test/ui/consts/const-err2.rs @@ -2,7 +2,7 @@ // optimized compilation and unoptimized compilation and thus would // lead to different lints being emitted -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/consts/const-eval/promoted_errors.default.stderr b/src/test/ui/consts/const-eval/promoted_errors.default.stderr deleted file mode 100644 index 034dea06568..00000000000 --- a/src/test/ui/consts/const-eval/promoted_errors.default.stderr +++ /dev/null @@ -1,72 +0,0 @@ -warning: this arithmetic operation will overflow - --> $DIR/promoted_errors.rs:14:14 - | -LL | let _x = 0u32 - 1; - | ^^^^^^^^ attempt to subtract with overflow - | -note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:20 - | -LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] - | ^^^^^^^^^^^^^^^^^^^ - -warning: this operation will panic at runtime - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ attempt to divide by zero - | -note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:41 - | -LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] - | ^^^^^^^^^^^^^^^^^^^ - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ dividing by zero - | -note: the lint level is defined here - --> $DIR/promoted_errors.rs:9:9 - | -LL | #![warn(const_err, arithmetic_overflow, unconditional_panic)] - | ^^^^^^^^^ - -warning: erroneous constant used - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1 / (1 - 1)); - | ^^^^^^^^^^^ referenced constant has errors - -warning: this operation will panic at runtime - --> $DIR/promoted_errors.rs:20:14 - | -LL | let _x = 1 / (1 - 1); - | ^^^^^^^^^^^ attempt to divide by zero - -warning: this operation will panic at runtime - --> $DIR/promoted_errors.rs:22:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero - -warning: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:22:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ dividing by zero - -warning: erroneous constant used - --> $DIR/promoted_errors.rs:22:20 - | -LL | println!("{}", 1 / (false as u32)); - | ^^^^^^^^^^^^^^^^^^ referenced constant has errors - -warning: this operation will panic at runtime - --> $DIR/promoted_errors.rs:26:14 - | -LL | let _x = 1 / (false as u32); - | ^^^^^^^^^^^^^^^^^^ attempt to divide by zero - diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index b734f70f9f0..3ab6ce28478 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -1,4 +1,4 @@ -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/consts/issue-64059.rs b/src/test/ui/consts/issue-64059.rs index 16bfda3b961..02c8b725032 100644 --- a/src/test/ui/consts/issue-64059.rs +++ b/src/test/ui/consts/issue-64059.rs @@ -1,4 +1,4 @@ -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/consts/issue-69020.default.stderr b/src/test/ui/consts/issue-69020.default.stderr deleted file mode 100644 index c48a106ef46..00000000000 --- a/src/test/ui/consts/issue-69020.default.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:21:22 - | -LL | const NEG: i32 = -i32::MIN + T::NEG; - | ^^^^^^^^^ attempt to negate with overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/issue-69020.rs:23:22 - | -LL | const ADD: i32 = (i32::MAX+1) + T::ADD; - | ^^^^^^^^^^^^ attempt to add with overflow - -error: this operation will panic at runtime - --> $DIR/issue-69020.rs:25:22 - | -LL | const DIV: i32 = (1/0) + T::DIV; - | ^^^^^ attempt to divide by zero - | - = note: `#[deny(unconditional_panic)]` on by default - -error: this operation will panic at runtime - --> $DIR/issue-69020.rs:27:22 - | -LL | const OOB: i32 = [1][1] + T::OOB; - | ^^^^^^ index out of bounds: the len is 1 but the index is 1 - -error: aborting due to 4 previous errors - diff --git a/src/test/ui/consts/issue-69020.rs b/src/test/ui/consts/issue-69020.rs index 963ab01a33c..e079feb04d4 100644 --- a/src/test/ui/consts/issue-69020.rs +++ b/src/test/ui/consts/issue-69020.rs @@ -1,4 +1,4 @@ -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/issues/issue-8460-const.default.stderr b/src/test/ui/issues/issue-8460-const.default.stderr deleted file mode 100644 index 3556ec08247..00000000000 --- a/src/test/ui/issues/issue-8460-const.default.stderr +++ /dev/null @@ -1,150 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:14:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to divide with overflow - | - = note: `#[deny(arithmetic_overflow)]` on by default - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:16:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to divide with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:18:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:20:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:22:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to divide with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:24:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN / -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ attempt to divide with overflow - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:26:36 - | -LL | assert!(thread::spawn(move|| { 1isize / 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to divide by zero - | - = note: `#[deny(unconditional_panic)]` on by default - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:28:36 - | -LL | assert!(thread::spawn(move|| { 1i8 / 0; }).join().is_err()); - | ^^^^^^^ attempt to divide by zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:30:36 - | -LL | assert!(thread::spawn(move|| { 1i16 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:32:36 - | -LL | assert!(thread::spawn(move|| { 1i32 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:34:36 - | -LL | assert!(thread::spawn(move|| { 1i64 / 0; }).join().is_err()); - | ^^^^^^^^ attempt to divide by zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:36:36 - | -LL | assert!(thread::spawn(move|| { 1i128 / 0; }).join().is_err()); - | ^^^^^^^^^ attempt to divide by zero - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:38:36 - | -LL | assert!(thread::spawn(move|| { isize::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:40:36 - | -LL | assert!(thread::spawn(move|| { i8::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:42:36 - | -LL | assert!(thread::spawn(move|| { i16::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:44:36 - | -LL | assert!(thread::spawn(move|| { i32::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:46:36 - | -LL | assert!(thread::spawn(move|| { i64::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this arithmetic operation will overflow - --> $DIR/issue-8460-const.rs:48:36 - | -LL | assert!(thread::spawn(move|| { i128::MIN % -1; }).join().is_err()); - | ^^^^^^^^^^^^^^ attempt to calculate the remainder with overflow - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:50:36 - | -LL | assert!(thread::spawn(move|| { 1isize % 0; }).join().is_err()); - | ^^^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:52:36 - | -LL | assert!(thread::spawn(move|| { 1i8 % 0; }).join().is_err()); - | ^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:54:36 - | -LL | assert!(thread::spawn(move|| { 1i16 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:56:36 - | -LL | assert!(thread::spawn(move|| { 1i32 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:58:36 - | -LL | assert!(thread::spawn(move|| { 1i64 % 0; }).join().is_err()); - | ^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: this operation will panic at runtime - --> $DIR/issue-8460-const.rs:60:36 - | -LL | assert!(thread::spawn(move|| { 1i128 % 0; }).join().is_err()); - | ^^^^^^^^^ attempt to calculate the remainder with a divisor of zero - -error: aborting due to 24 previous errors - diff --git a/src/test/ui/issues/issue-8460-const.rs b/src/test/ui/issues/issue-8460-const.rs index d7276af40a7..53005e46d2f 100644 --- a/src/test/ui/issues/issue-8460-const.rs +++ b/src/test/ui/issues/issue-8460-const.rs @@ -1,4 +1,4 @@ -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr b/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr deleted file mode 100644 index ce9b02b6d82..00000000000 --- a/src/test/ui/lint/lint-exceeding-bitshifts.default.stderr +++ /dev/null @@ -1,146 +0,0 @@ -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:22:13 - | -LL | let _ = x << 42; - | ^^^^^^^ attempt to shift left with overflow - | -note: the lint level is defined here - --> $DIR/lint-exceeding-bitshifts.rs:9:9 - | -LL | #![deny(arithmetic_overflow, const_err)] - | ^^^^^^^^^^^^^^^^^^^ - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:27:15 - | -LL | let n = 1u8 << 8; - | ^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:29:15 - | -LL | let n = 1u16 << 16; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:31:15 - | -LL | let n = 1u32 << 32; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:33:15 - | -LL | let n = 1u64 << 64; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:35:15 - | -LL | let n = 1i8 << 8; - | ^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:37:15 - | -LL | let n = 1i16 << 16; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:39:15 - | -LL | let n = 1i32 << 32; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:41:15 - | -LL | let n = 1i64 << 64; - | ^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:44:15 - | -LL | let n = 1u8 >> 8; - | ^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:46:15 - | -LL | let n = 1u16 >> 16; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:48:15 - | -LL | let n = 1u32 >> 32; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:50:15 - | -LL | let n = 1u64 >> 64; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:52:15 - | -LL | let n = 1i8 >> 8; - | ^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:54:15 - | -LL | let n = 1i16 >> 16; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:56:15 - | -LL | let n = 1i32 >> 32; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:58:15 - | -LL | let n = 1i64 >> 64; - | ^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:62:15 - | -LL | let n = n << 8; - | ^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:64:15 - | -LL | let n = 1u8 << -8; - | ^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:69:15 - | -LL | let n = 1u8 << (4+4); - | ^^^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:71:15 - | -LL | let n = 1i64 >> [64][0]; - | ^^^^^^^^^^^^^^^ attempt to shift right with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:77:15 - | -LL | let n = 1_isize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left with overflow - -error: this arithmetic operation will overflow - --> $DIR/lint-exceeding-bitshifts.rs:78:15 - | -LL | let n = 1_usize << BITS; - | ^^^^^^^^^^^^^^^ attempt to shift left with overflow - -error: aborting due to 23 previous errors - diff --git a/src/test/ui/lint/lint-exceeding-bitshifts.rs b/src/test/ui/lint/lint-exceeding-bitshifts.rs index 04996e41bb3..7deee5320a8 100644 --- a/src/test/ui/lint/lint-exceeding-bitshifts.rs +++ b/src/test/ui/lint/lint-exceeding-bitshifts.rs @@ -1,4 +1,4 @@ -// revisions: default noopt opt opt_with_overflow_checks +// revisions: noopt opt opt_with_overflow_checks //[noopt]compile-flags: -C opt-level=0 //[opt]compile-flags: -O //[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O From 545e290a93b3c51a60c33ccb4c0d9576f797cf29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 21:04:36 +0100 Subject: [PATCH 0328/1250] Split query execution into hot and cold paths --- src/librustc/dep_graph/graph.rs | 1 + src/librustc/ty/context.rs | 1 + src/librustc/ty/query/plumbing.rs | 256 ++++++++++++++++++------------ 3 files changed, 155 insertions(+), 103 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 258723bb39d..ae2fde96617 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1122,6 +1122,7 @@ impl CurrentDepGraph { } impl DepGraphData { + #[inline] fn read_index(&self, source: DepNodeIndex) { ty::tls::with_context_opt(|icx| { let icx = if let Some(icx) = icx { icx } else { return }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 5a415fa954f..68c9ccc455f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1688,6 +1688,7 @@ pub mod tls { /// Gets the pointer to the current `ImplicitCtxt`. #[cfg(not(parallel_compiler))] + #[inline] fn get_tlv() -> usize { TLV.with(|tlv| tlv.get()) } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 8b787915de6..5ed5c2776a8 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -12,10 +12,8 @@ use crate::ty::{self, TyCtxt}; #[cfg(not(parallel_compiler))] use rustc_data_structures::cold_path; use rustc_data_structures::fx::{FxHashMap, FxHasher}; -#[cfg(parallel_compiler)] -use rustc_data_structures::profiling::TimingGuard; use rustc_data_structures::sharded::Sharded; -use rustc_data_structures::sync::Lock; +use rustc_data_structures::sync::{Lock, LockGuard}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{struct_span_err, Diagnostic, DiagnosticBuilder, FatalError, Handler, Level}; use rustc_span::source_map::DUMMY_SP; @@ -70,6 +68,12 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } } +/// Values used when checking a query cache which can be reused on a cache-miss to execute the query. +pub(super) struct QueryLookup<'tcx, Q: QueryDescription<'tcx>> { + shard: usize, + lock: LockGuard<'tcx, QueryCache<'tcx, Q>>, +} + /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { @@ -81,119 +85,87 @@ pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. - /// If the query is executing elsewhere, this will wait for it. + /// This function assumes that `try_get_cached` is already called and returned `lookup`. + /// If the query is executing elsewhere, this will wait for it and return the result. /// If the query panicked, this will silently panic. /// /// This function is inlined because that results in a noticeable speed-up /// for some compile-time benchmarks. #[inline(always)] - pub(super) fn try_get(tcx: TyCtxt<'tcx>, span: Span, key: &Q::Key) -> TryGetJob<'a, 'tcx, Q> { - // Handling the `query_blocked_prof_timer` is a bit weird because of the - // control flow in this function: Blocking is implemented by - // awaiting a running job and, once that is done, entering the loop below - // again from the top. In that second iteration we will hit the - // cache which provides us with the information we need for - // finishing the "query-blocked" event. - // - // We thus allocate `query_blocked_prof_timer` outside the loop, - // initialize it during the first iteration and finish it during the - // second iteration. - #[cfg(parallel_compiler)] - let mut query_blocked_prof_timer: Option> = None; - - let cache = Q::query_cache(tcx); - loop { - // We compute the key's hash once and then use it for both the - // shard lookup and the hashmap lookup. This relies on the fact - // that both of them use `FxHasher`. - let mut state = FxHasher::default(); - key.hash(&mut state); - let key_hash = state.finish(); - - let shard = cache.get_shard_index_by_hash(key_hash); - let mut lock_guard = cache.get_shard_by_index(shard).lock(); - let lock = &mut *lock_guard; - - if let Some((_, value)) = - lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key) - { - if unlikely!(tcx.prof.enabled()) { - tcx.prof.query_cache_hit(value.index.into()); - - #[cfg(parallel_compiler)] - { - if let Some(prof_timer) = query_blocked_prof_timer.take() { - prof_timer.finish_with_query_invocation_id(value.index.into()); - } - } - } + pub(super) fn try_start( + tcx: TyCtxt<'tcx>, + span: Span, + key: &Q::Key, + mut lookup: QueryLookup<'tcx, Q>, + ) -> TryGetJob<'a, 'tcx, Q> { + let lock = &mut *lookup.lock; + + let (latch, mut _query_blocked_prof_timer) = match lock.active.entry((*key).clone()) { + Entry::Occupied(mut entry) => { + match entry.get_mut() { + QueryResult::Started(job) => { + // For parallel queries, we'll block and wait until the query running + // in another thread has completed. Record how long we wait in the + // self-profiler. + let _query_blocked_prof_timer = if cfg!(parallel_compiler) { + Some(tcx.prof.query_blocked()) + } else { + None + }; + + // Create the id of the job we're waiting for + let id = QueryJobId::new(job.id, lookup.shard, Q::dep_kind()); - let result = (value.value.clone(), value.index); - #[cfg(debug_assertions)] - { - lock.cache_hits += 1; + (job.latch(id), _query_blocked_prof_timer) + } + QueryResult::Poisoned => FatalError.raise(), } - return TryGetJob::JobCompleted(result); } + Entry::Vacant(entry) => { + // No job entry for this query. Return a new one to be started later. - let latch = match lock.active.entry((*key).clone()) { - Entry::Occupied(mut entry) => { - match entry.get_mut() { - QueryResult::Started(job) => { - // For parallel queries, we'll block and wait until the query running - // in another thread has completed. Record how long we wait in the - // self-profiler. - #[cfg(parallel_compiler)] - { - query_blocked_prof_timer = Some(tcx.prof.query_blocked()); - } + // Generate an id unique within this shard. + let id = lock.jobs.checked_add(1).unwrap(); + lock.jobs = id; + let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); - // Create the id of the job we're waiting for - let id = QueryJobId::new(job.id, shard, Q::dep_kind()); + let global_id = QueryJobId::new(id, lookup.shard, Q::dep_kind()); - job.latch(id) - } - QueryResult::Poisoned => FatalError.raise(), - } - } - Entry::Vacant(entry) => { - // No job entry for this query. Return a new one to be started later. + let job = tls::with_related_context(tcx, |icx| QueryJob::new(id, span, icx.query)); - // Generate an id unique within this shard. - let id = lock.jobs.checked_add(1).unwrap(); - lock.jobs = id; - let id = QueryShardJobId(NonZeroU32::new(id).unwrap()); + entry.insert(QueryResult::Started(job)); - let global_id = QueryJobId::new(id, shard, Q::dep_kind()); - - let job = - tls::with_related_context(tcx, |icx| QueryJob::new(id, span, icx.query)); + let owner = + JobOwner { cache: Q::query_cache(tcx), id: global_id, key: (*key).clone() }; + return TryGetJob::NotYetStarted(owner); + } + }; + mem::drop(lookup.lock); - entry.insert(QueryResult::Started(job)); + // If we are single-threaded we know that we have cycle error, + // so we just return the error. + #[cfg(not(parallel_compiler))] + return TryGetJob::Cycle(cold_path(|| { + Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span)) + })); - let owner = JobOwner { cache, id: global_id, key: (*key).clone() }; - return TryGetJob::NotYetStarted(owner); - } - }; - mem::drop(lock_guard); + // With parallel queries we might just have to wait on some other + // thread. + #[cfg(parallel_compiler)] + { + let result = latch.wait_on(tcx, span); - // If we are single-threaded we know that we have cycle error, - // so we just return the error. - #[cfg(not(parallel_compiler))] - return TryGetJob::Cycle(cold_path(|| { - Q::handle_cycle_error(tcx, latch.find_cycle_in_stack(tcx, span)) - })); + if let Err(cycle) = result { + return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); + } - // With parallel queries we might just have to wait on some other - // thread. - #[cfg(parallel_compiler)] - { - let result = latch.wait_on(tcx, span); + let cached = tcx.try_get_cached::(key).0.unwrap(); - if let Err(cycle) = result { - return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); - } + if let Some(prof_timer) = _query_blocked_prof_timer.take() { + prof_timer.finish_with_query_invocation_id(cached.1.into()); } + + return TryGetJob::JobCompleted(cached); } } @@ -269,6 +241,7 @@ pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { /// The query was already completed. /// Returns the result of the query and its dep-node index /// if it succeeded or a cycle error if it failed. + #[cfg(parallel_compiler)] JobCompleted((D::Value, DepNodeIndex)), /// Trying to execute the query resulted in a cycle. @@ -396,13 +369,76 @@ impl<'tcx> TyCtxt<'tcx> { eprintln!("end of query stack"); } + /// Checks if the query is already computed and in the cache. + /// It returns the shard index and a lock guard to the shard, + /// which will be used if the query is not in the cache and we need + /// to compute it. + #[inline(always)] + fn try_get_cached>( + self, + key: &Q::Key, + ) -> (Option<(Q::Value, DepNodeIndex)>, QueryLookup<'tcx, Q>) { + let cache = Q::query_cache(self); + + // We compute the key's hash once and then use it for both the + // shard lookup and the hashmap lookup. This relies on the fact + // that both of them use `FxHasher`. + let mut state = FxHasher::default(); + key.hash(&mut state); + let key_hash = state.finish(); + + let shard = cache.get_shard_index_by_hash(key_hash); + let mut lock_guard = cache.get_shard_by_index(shard).lock(); + let lock = &mut *lock_guard; + + let result = + lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key).map(|(_, value)| { + if unlikely!(self.prof.enabled()) { + self.prof.query_cache_hit(value.index.into()); + } + + (value.value.clone(), value.index) + }); + + #[cfg(debug_assertions)] + { + if result.is_some() { + lock.cache_hits += 1; + } + } + + (result, QueryLookup { lock: lock_guard, shard }) + } + #[inline(never)] - pub(super) fn get_query>(self, span: Span, key: Q::Key) -> Q::Value { + pub(super) fn get_query + 'tcx>( + self, + span: Span, + key: Q::Key, + ) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - let job = match JobOwner::try_get(self, span, &key) { + let (cached, lookup) = self.try_get_cached::(&key); + + if let Some((v, index)) = cached { + self.dep_graph.read_index(index); + return v; + } + + self.try_execute_query(span, key, lookup) + } + + #[inline(always)] + pub(super) fn try_execute_query>( + self, + span: Span, + key: Q::Key, + lookup: QueryLookup<'tcx, Q>, + ) -> Q::Value { + let job = match JobOwner::try_start(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, TryGetJob::Cycle(result) => return result, + #[cfg(parallel_compiler)] TryGetJob::JobCompleted((v, index)) => { self.dep_graph.read_index(index); return v; @@ -615,7 +651,7 @@ impl<'tcx> TyCtxt<'tcx> { /// side-effects -- e.g., in order to report errors for erroneous programs. /// /// Note: The optimization is only available during incr. comp. - pub(super) fn ensure_query>(self, key: Q::Key) -> () { + pub(super) fn ensure_query + 'tcx>(self, key: Q::Key) -> () { if Q::EVAL_ALWAYS { let _ = self.get_query::(DUMMY_SP, key); return; @@ -643,12 +679,26 @@ impl<'tcx> TyCtxt<'tcx> { } #[allow(dead_code)] - fn force_query>(self, key: Q::Key, span: Span, dep_node: DepNode) { + fn force_query + 'tcx>( + self, + key: Q::Key, + span: Span, + dep_node: DepNode, + ) { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let job = match JobOwner::try_get(self, span, &key) { + + let (cached, lookup) = self.try_get_cached::(&key); + + if cached.is_some() { + return; + } + + let job = match JobOwner::try_start(self, span, &key, lookup) { TryGetJob::NotYetStarted(job) => job, - TryGetJob::Cycle(_) | TryGetJob::JobCompleted(_) => return, + TryGetJob::Cycle(_) => return, + #[cfg(parallel_compiler)] + TryGetJob::JobCompleted(_) => return, }; self.force_query_with_job::(key, job, dep_node); } From 6bf014ec99e40145ad5f046199f58c9c9d7f60e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 13 Feb 2020 12:18:57 +0100 Subject: [PATCH 0329/1250] Make `try_get_cached` take closures --- src/librustc/ty/query/plumbing.rs | 86 +++++++++++++++++-------------- 1 file changed, 47 insertions(+), 39 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 5ed5c2776a8..ba2d1e0361c 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -159,7 +159,11 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { return TryGetJob::Cycle(Q::handle_cycle_error(tcx, cycle)); } - let cached = tcx.try_get_cached::(key).0.unwrap(); + let cached = tcx.try_get_cached::( + (*key).clone(), + |value, index| (value.clone(), index), + |_, _| panic!("value must be in cache after waiting"), + ); if let Some(prof_timer) = _query_blocked_prof_timer.take() { prof_timer.finish_with_query_invocation_id(cached.1.into()); @@ -374,10 +378,18 @@ impl<'tcx> TyCtxt<'tcx> { /// which will be used if the query is not in the cache and we need /// to compute it. #[inline(always)] - fn try_get_cached>( + fn try_get_cached( self, - key: &Q::Key, - ) -> (Option<(Q::Value, DepNodeIndex)>, QueryLookup<'tcx, Q>) { + key: Q::Key, + // `on_hit` can be called while holding a lock to the query cache + on_hit: OnHit, + on_miss: OnMiss, + ) -> R + where + Q: QueryDescription<'tcx> + 'tcx, + OnHit: FnOnce(&Q::Value, DepNodeIndex) -> R, + OnMiss: FnOnce(Q::Key, QueryLookup<'tcx, Q>) -> R, + { let cache = Q::query_cache(self); // We compute the key's hash once and then use it for both the @@ -391,23 +403,17 @@ impl<'tcx> TyCtxt<'tcx> { let mut lock_guard = cache.get_shard_by_index(shard).lock(); let lock = &mut *lock_guard; - let result = - lock.results.raw_entry().from_key_hashed_nocheck(key_hash, key).map(|(_, value)| { - if unlikely!(self.prof.enabled()) { - self.prof.query_cache_hit(value.index.into()); - } + let result = lock.results.raw_entry().from_key_hashed_nocheck(key_hash, &key); - (value.value.clone(), value.index) - }); - - #[cfg(debug_assertions)] - { - if result.is_some() { - lock.cache_hits += 1; + if let Some((_, value)) = result { + if unlikely!(self.prof.enabled()) { + self.prof.query_cache_hit(value.index.into()); } - } - (result, QueryLookup { lock: lock_guard, shard }) + on_hit(&value.value, value.index) + } else { + on_miss(key, QueryLookup { lock: lock_guard, shard }) + } } #[inline(never)] @@ -418,14 +424,14 @@ impl<'tcx> TyCtxt<'tcx> { ) -> Q::Value { debug!("ty::query::get_query<{}>(key={:?}, span={:?})", Q::NAME, key, span); - let (cached, lookup) = self.try_get_cached::(&key); - - if let Some((v, index)) = cached { - self.dep_graph.read_index(index); - return v; - } - - self.try_execute_query(span, key, lookup) + self.try_get_cached::( + key, + |value, index| { + self.dep_graph.read_index(index); + value.clone() + }, + |key, lookup| self.try_execute_query(span, key, lookup), + ) } #[inline(always)] @@ -688,19 +694,21 @@ impl<'tcx> TyCtxt<'tcx> { // We may be concurrently trying both execute and force a query. // Ensure that only one of them runs the query. - let (cached, lookup) = self.try_get_cached::(&key); - - if cached.is_some() { - return; - } - - let job = match JobOwner::try_start(self, span, &key, lookup) { - TryGetJob::NotYetStarted(job) => job, - TryGetJob::Cycle(_) => return, - #[cfg(parallel_compiler)] - TryGetJob::JobCompleted(_) => return, - }; - self.force_query_with_job::(key, job, dep_node); + self.try_get_cached::( + key, + |_, _| { + // Cache hit, do nothing + }, + |key, lookup| { + let job = match JobOwner::try_start(self, span, &key, lookup) { + TryGetJob::NotYetStarted(job) => job, + TryGetJob::Cycle(_) => return, + #[cfg(parallel_compiler)] + TryGetJob::JobCompleted(_) => return, + }; + self.force_query_with_job::(key, job, dep_node); + }, + ); } } From e2a8589e018a8a119b628206d0f8990b44a2e4c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 07:38:00 +0100 Subject: [PATCH 0330/1250] Add an abstraction for custom query caches --- src/librustc/ty/query/caches.rs | 112 +++++++++++++ src/librustc/ty/query/config.rs | 13 +- src/librustc/ty/query/keys.rs | 51 +++++- src/librustc/ty/query/mod.rs | 3 + src/librustc/ty/query/on_disk_cache.rs | 32 ++-- src/librustc/ty/query/plumbing.rs | 174 ++++++++++++--------- src/librustc/ty/query/profiling_support.rs | 43 ++--- 7 files changed, 305 insertions(+), 123 deletions(-) create mode 100644 src/librustc/ty/query/caches.rs diff --git a/src/librustc/ty/query/caches.rs b/src/librustc/ty/query/caches.rs new file mode 100644 index 00000000000..efc2804bd4d --- /dev/null +++ b/src/librustc/ty/query/caches.rs @@ -0,0 +1,112 @@ +use crate::dep_graph::DepNodeIndex; +use crate::ty::query::config::QueryAccessors; +use crate::ty::query::plumbing::{QueryLookup, QueryState, QueryStateShard}; +use crate::ty::TyCtxt; + +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sharded::Sharded; +use std::default::Default; +use std::hash::Hash; + +pub(crate) trait CacheSelector { + type Cache: QueryCache; +} + +pub(crate) trait QueryCache: Default { + type Sharded: Default; + + /// Checks if the query is already computed and in the cache. + /// It returns the shard index and a lock guard to the shard, + /// which will be used if the query is not in the cache and we need + /// to compute it. + fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + &self, + state: &'tcx QueryState<'tcx, Q>, + get_cache: GetCache, + key: K, + // `on_hit` can be called while holding a lock to the query state shard. + on_hit: OnHit, + on_miss: OnMiss, + ) -> R + where + Q: QueryAccessors<'tcx>, + GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, + OnHit: FnOnce(&V, DepNodeIndex) -> R, + OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R; + + fn complete( + &self, + tcx: TyCtxt<'tcx>, + lock_sharded_storage: &mut Self::Sharded, + key: K, + value: V, + index: DepNodeIndex, + ); + + fn iter( + &self, + shards: &Sharded, + get_shard: impl Fn(&mut L) -> &mut Self::Sharded, + f: impl for<'a> FnOnce(Box + 'a>) -> R, + ) -> R; +} + +pub struct DefaultCacheSelector; + +impl CacheSelector for DefaultCacheSelector { + type Cache = DefaultCache; +} + +#[derive(Default)] +pub struct DefaultCache; + +impl QueryCache for DefaultCache { + type Sharded = FxHashMap; + + #[inline(always)] + fn lookup<'tcx, R, GetCache, OnHit, OnMiss, Q>( + &self, + state: &'tcx QueryState<'tcx, Q>, + get_cache: GetCache, + key: K, + on_hit: OnHit, + on_miss: OnMiss, + ) -> R + where + Q: QueryAccessors<'tcx>, + GetCache: for<'a> Fn(&'a mut QueryStateShard<'tcx, Q>) -> &'a mut Self::Sharded, + OnHit: FnOnce(&V, DepNodeIndex) -> R, + OnMiss: FnOnce(K, QueryLookup<'tcx, Q>) -> R, + { + let mut lookup = state.get_lookup(&key); + let lock = &mut *lookup.lock; + + let result = get_cache(lock).raw_entry().from_key_hashed_nocheck(lookup.key_hash, &key); + + if let Some((_, value)) = result { on_hit(&value.0, value.1) } else { on_miss(key, lookup) } + } + + #[inline] + fn complete( + &self, + _: TyCtxt<'tcx>, + lock_sharded_storage: &mut Self::Sharded, + key: K, + value: V, + index: DepNodeIndex, + ) { + lock_sharded_storage.insert(key, (value, index)); + } + + fn iter( + &self, + shards: &Sharded, + get_shard: impl Fn(&mut L) -> &mut Self::Sharded, + f: impl for<'a> FnOnce(Box + 'a>) -> R, + ) -> R { + let mut shards = shards.lock_shards(); + let mut shards: Vec<_> = shards.iter_mut().map(|shard| get_shard(shard)).collect(); + let results = shards.iter_mut().flat_map(|shard| shard.iter()).map(|(k, v)| (k, &v.0, v.1)); + f(Box::new(results)) + } +} diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index dbb6a1080e6..e0e1ca374d9 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -1,15 +1,15 @@ use crate::dep_graph::SerializedDepNodeIndex; use crate::dep_graph::{DepKind, DepNode}; +use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::CycleError; use crate::ty::query::queries; -use crate::ty::query::{Query, QueryCache}; +use crate::ty::query::{Query, QueryState}; use crate::ty::TyCtxt; use rustc_data_structures::profiling::ProfileCategory; use rustc_hir::def_id::{CrateNum, DefId}; use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::Fingerprint; -use rustc_data_structures::sharded::Sharded; use std::borrow::Cow; use std::fmt::Debug; use std::hash::Hash; @@ -30,10 +30,12 @@ pub(crate) trait QueryAccessors<'tcx>: QueryConfig<'tcx> { const ANON: bool; const EVAL_ALWAYS: bool; + type Cache: QueryCache; + fn query(key: Self::Key) -> Query<'tcx>; // Don't use this method to access query results, instead use the methods on TyCtxt - fn query_cache<'a>(tcx: TyCtxt<'tcx>) -> &'a Sharded>; + fn query_state<'a>(tcx: TyCtxt<'tcx>) -> &'a QueryState<'tcx, Self>; fn to_dep_node(tcx: TyCtxt<'tcx>, key: &Self::Key) -> DepNode; @@ -61,7 +63,10 @@ pub(crate) trait QueryDescription<'tcx>: QueryAccessors<'tcx> { } } -impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M { +impl<'tcx, M: QueryAccessors<'tcx, Key = DefId>> QueryDescription<'tcx> for M +where + >::Cache: QueryCache>::Value>, +{ default fn describe(tcx: TyCtxt<'_>, def_id: DefId) -> Cow<'static, str> { if !tcx.sess.verbose() { format!("processing `{}`", tcx.def_path_str(def_id)).into() diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index c1c88e96f94..09fb307a1ce 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -4,6 +4,7 @@ use crate::infer::canonical::Canonical; use crate::mir; use crate::traits; use crate::ty::fast_reject::SimplifiedType; +use crate::ty::query::caches::DefaultCacheSelector; use crate::ty::subst::SubstsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; @@ -12,7 +13,9 @@ use rustc_span::{Span, DUMMY_SP}; /// The `Key` trait controls what types can legally be used as the key /// for a query. -pub(super) trait Key { +pub trait Key { + type CacheSelector; + /// Given an instance of this key, what crate is it referring to? /// This is used to find the provider. fn query_crate(&self) -> CrateNum; @@ -23,6 +26,8 @@ pub(super) trait Key { } impl<'tcx> Key for ty::InstanceDef<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -33,6 +38,8 @@ impl<'tcx> Key for ty::InstanceDef<'tcx> { } impl<'tcx> Key for ty::Instance<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -43,6 +50,8 @@ impl<'tcx> Key for ty::Instance<'tcx> { } impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.instance.query_crate() } @@ -53,6 +62,8 @@ impl<'tcx> Key for mir::interpret::GlobalId<'tcx> { } impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -63,6 +74,8 @@ impl<'tcx> Key for mir::interpret::LitToConstInput<'tcx> { } impl Key for CrateNum { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { *self } @@ -72,6 +85,8 @@ impl Key for CrateNum { } impl Key for DefIndex { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -81,6 +96,8 @@ impl Key for DefIndex { } impl Key for DefId { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.krate } @@ -90,6 +107,8 @@ impl Key for DefId { } impl Key for (DefId, DefId) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.0.krate } @@ -99,6 +118,8 @@ impl Key for (DefId, DefId) { } impl Key for (CrateNum, DefId) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.0 } @@ -108,6 +129,8 @@ impl Key for (CrateNum, DefId) { } impl Key for (DefId, SimplifiedType) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.0.krate } @@ -117,6 +140,8 @@ impl Key for (DefId, SimplifiedType) { } impl<'tcx> Key for SubstsRef<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -126,6 +151,8 @@ impl<'tcx> Key for SubstsRef<'tcx> { } impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.0.krate } @@ -135,6 +162,8 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.1.def_id().krate } @@ -144,6 +173,8 @@ impl<'tcx> Key for (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) { } impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -153,6 +184,8 @@ impl<'tcx> Key for (&'tcx ty::Const<'tcx>, mir::Field) { } impl<'tcx> Key for ty::PolyTraitRef<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.def_id().krate } @@ -162,6 +195,8 @@ impl<'tcx> Key for ty::PolyTraitRef<'tcx> { } impl<'tcx> Key for &'tcx ty::Const<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -171,6 +206,8 @@ impl<'tcx> Key for &'tcx ty::Const<'tcx> { } impl<'tcx> Key for Ty<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -180,6 +217,8 @@ impl<'tcx> Key for Ty<'tcx> { } impl<'tcx> Key for ty::ParamEnv<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -189,6 +228,8 @@ impl<'tcx> Key for ty::ParamEnv<'tcx> { } impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { self.value.query_crate() } @@ -198,6 +239,8 @@ impl<'tcx, T: Key> Key for ty::ParamEnvAnd<'tcx, T> { } impl<'tcx> Key for traits::Environment<'tcx> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -207,6 +250,8 @@ impl<'tcx> Key for traits::Environment<'tcx> { } impl Key for Symbol { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -218,6 +263,8 @@ impl Key for Symbol { /// Canonical query goals correspond to abstract trait operations that /// are not tied to any crate in particular. impl<'tcx, T> Key for Canonical<'tcx, T> { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } @@ -228,6 +275,8 @@ impl<'tcx, T> Key for Canonical<'tcx, T> { } impl Key for (Symbol, u32, u32) { + type CacheSelector = DefaultCacheSelector; + fn query_crate(&self) -> CrateNum { LOCAL_CRATE } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 21698cd7374..91ae11b327e 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -76,6 +76,9 @@ use self::keys::Key; mod values; use self::values::Value; +mod caches; +use self::caches::CacheSelector; + mod config; use self::config::QueryAccessors; pub use self::config::QueryConfig; diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 45d95e97a9c..b92081ff7c0 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -1035,20 +1035,22 @@ where .prof .extra_verbose_generic_activity("encode_query_results_for", ::std::any::type_name::()); - let shards = Q::query_cache(tcx).lock_shards(); - assert!(shards.iter().all(|shard| shard.active.is_empty())); - for (key, entry) in shards.iter().flat_map(|shard| shard.results.iter()) { - if Q::cache_on_disk(tcx, key.clone(), Some(&entry.value)) { - let dep_node = SerializedDepNodeIndex::new(entry.index.index()); - - // Record position of the cache entry. - query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position()))); - - // Encode the type check tables with the `SerializedDepNodeIndex` - // as tag. - encoder.encode_tagged(dep_node, &entry.value)?; - } - } + let state = Q::query_state(tcx); + assert!(state.all_inactive()); + + state.iter_results(|results| { + for (key, value, dep_node) in results { + if Q::cache_on_disk(tcx, key.clone(), Some(&value)) { + let dep_node = SerializedDepNodeIndex::new(dep_node.index()); + + // Record position of the cache entry. + query_result_index.push((dep_node, AbsoluteBytePos::new(encoder.position()))); - Ok(()) + // Encode the type check tables with the `SerializedDepNodeIndex` + // as tag. + encoder.encode_tagged(dep_node, &value)?; + } + } + Ok(()) + }) } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index ba2d1e0361c..3eaf4e36f39 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -3,7 +3,8 @@ //! manage the caches, and so forth. use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; -use crate::ty::query::config::{QueryConfig, QueryDescription}; +use crate::ty::query::caches::QueryCache; +use crate::ty::query::config::{QueryAccessors, QueryDescription}; use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId}; use crate::ty::query::Query; use crate::ty::tls; @@ -24,25 +25,47 @@ use std::mem; use std::num::NonZeroU32; use std::ptr; -pub struct QueryCache<'tcx, D: QueryConfig<'tcx> + ?Sized> { - pub(super) results: FxHashMap>, +pub(crate) struct QueryStateShard<'tcx, D: QueryAccessors<'tcx> + ?Sized> { + pub(super) cache: <>::Cache as QueryCache>::Sharded, pub(super) active: FxHashMap>, /// Used to generate unique ids for active jobs. pub(super) jobs: u32, +} +impl<'tcx, Q: QueryAccessors<'tcx>> QueryStateShard<'tcx, Q> { + fn get_cache( + &mut self, + ) -> &mut <>::Cache as QueryCache>::Sharded { + &mut self.cache + } +} + +impl<'tcx, Q: QueryAccessors<'tcx>> Default for QueryStateShard<'tcx, Q> { + fn default() -> QueryStateShard<'tcx, Q> { + QueryStateShard { cache: Default::default(), active: Default::default(), jobs: 0 } + } +} + +pub(crate) struct QueryState<'tcx, D: QueryAccessors<'tcx> + ?Sized> { + pub(super) cache: D::Cache, + pub(super) shards: Sharded>, #[cfg(debug_assertions)] pub(super) cache_hits: usize, } -pub(super) struct QueryValue { - pub(super) value: T, - pub(super) index: DepNodeIndex, -} +impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { + pub(super) fn get_lookup(&'tcx self, key: &K) -> QueryLookup<'tcx, Q> { + // We compute the key's hash once and then use it for both the + // shard lookup and the hashmap lookup. This relies on the fact + // that both of them use `FxHasher`. + let mut hasher = FxHasher::default(); + key.hash(&mut hasher); + let key_hash = hasher.finish(); -impl QueryValue { - pub(super) fn new(value: T, dep_node_index: DepNodeIndex) -> QueryValue { - QueryValue { value, index: dep_node_index } + let shard = self.shards.get_shard_index_by_hash(key_hash); + let lock = self.shards.get_shard_by_index(shard).lock(); + QueryLookup { key_hash, shard, lock } } } @@ -56,12 +79,26 @@ pub(super) enum QueryResult<'tcx> { Poisoned, } -impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { - fn default() -> QueryCache<'tcx, M> { - QueryCache { - results: FxHashMap::default(), - active: FxHashMap::default(), - jobs: 0, +impl<'tcx, M: QueryAccessors<'tcx>> QueryState<'tcx, M> { + pub fn iter_results( + &self, + f: impl for<'a> FnOnce( + Box + 'a>, + ) -> R, + ) -> R { + self.cache.iter(&self.shards, |shard| &mut shard.cache, f) + } + pub fn all_inactive(&self) -> bool { + let shards = self.shards.lock_shards(); + shards.iter().all(|shard| shard.active.is_empty()) + } +} + +impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { + fn default() -> QueryState<'tcx, M> { + QueryState { + cache: M::Cache::default(), + shards: Default::default(), #[cfg(debug_assertions)] cache_hits: 0, } @@ -69,20 +106,21 @@ impl<'tcx, M: QueryConfig<'tcx>> Default for QueryCache<'tcx, M> { } /// Values used when checking a query cache which can be reused on a cache-miss to execute the query. -pub(super) struct QueryLookup<'tcx, Q: QueryDescription<'tcx>> { - shard: usize, - lock: LockGuard<'tcx, QueryCache<'tcx, Q>>, +pub(crate) struct QueryLookup<'tcx, Q: QueryAccessors<'tcx>> { + pub(super) key_hash: u64, + pub(super) shard: usize, + pub(super) lock: LockGuard<'tcx, QueryStateShard<'tcx, Q>>, } /// A type representing the responsibility to execute the job in the `job` field. /// This will poison the relevant query if dropped. -pub(super) struct JobOwner<'a, 'tcx, Q: QueryDescription<'tcx>> { - cache: &'a Sharded>, +pub(super) struct JobOwner<'tcx, Q: QueryDescription<'tcx>> { + tcx: TyCtxt<'tcx>, key: Q::Key, id: QueryJobId, } -impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { +impl<'tcx, Q: QueryDescription<'tcx>> JobOwner<'tcx, Q> { /// Either gets a `JobOwner` corresponding the query, allowing us to /// start executing the query, or returns with the result of the query. /// This function assumes that `try_get_cached` is already called and returned `lookup`. @@ -97,7 +135,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { span: Span, key: &Q::Key, mut lookup: QueryLookup<'tcx, Q>, - ) -> TryGetJob<'a, 'tcx, Q> { + ) -> TryGetJob<'tcx, Q> { let lock = &mut *lookup.lock; let (latch, mut _query_blocked_prof_timer) = match lock.active.entry((*key).clone()) { @@ -135,8 +173,7 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { entry.insert(QueryResult::Started(job)); - let owner = - JobOwner { cache: Q::query_cache(tcx), id: global_id, key: (*key).clone() }; + let owner = JobOwner { tcx, id: global_id, key: (*key).clone() }; return TryGetJob::NotYetStarted(owner); } }; @@ -179,19 +216,20 @@ impl<'a, 'tcx, Q: QueryDescription<'tcx>> JobOwner<'a, 'tcx, Q> { pub(super) fn complete(self, result: &Q::Value, dep_node_index: DepNodeIndex) { // We can move out of `self` here because we `mem::forget` it below let key = unsafe { ptr::read(&self.key) }; - let cache = self.cache; + let tcx = self.tcx; // Forget ourself so our destructor won't poison the query mem::forget(self); - let value = QueryValue::new(result.clone(), dep_node_index); let job = { - let mut lock = cache.get_shard_by_value(&key).lock(); + let state = Q::query_state(tcx); + let result = result.clone(); + let mut lock = state.shards.get_shard_by_value(&key).lock(); let job = match lock.active.remove(&key).unwrap() { QueryResult::Started(job) => job, QueryResult::Poisoned => panic!(), }; - lock.results.insert(key, value); + state.cache.complete(tcx, &mut lock.cache, key, result, dep_node_index); job }; @@ -209,12 +247,13 @@ where (result, diagnostics.into_inner()) } -impl<'a, 'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'a, 'tcx, Q> { +impl<'tcx, Q: QueryDescription<'tcx>> Drop for JobOwner<'tcx, Q> { #[inline(never)] #[cold] fn drop(&mut self) { // Poison the query so jobs waiting on it panic. - let shard = self.cache.get_shard_by_value(&self.key); + let state = Q::query_state(self.tcx); + let shard = state.shards.get_shard_by_value(&self.key); let job = { let mut shard = shard.lock(); let job = match shard.active.remove(&self.key).unwrap() { @@ -237,10 +276,10 @@ pub struct CycleError<'tcx> { pub(super) cycle: Vec>, } -/// The result of `try_get_lock`. -pub(super) enum TryGetJob<'a, 'tcx, D: QueryDescription<'tcx>> { +/// The result of `try_start`. +pub(super) enum TryGetJob<'tcx, D: QueryDescription<'tcx>> { /// The query is not yet started. Contains a guard to the cache eventually used to start it. - NotYetStarted(JobOwner<'a, 'tcx, D>), + NotYetStarted(JobOwner<'tcx, D>), /// The query was already completed. /// Returns the result of the query and its dep-node index @@ -390,30 +429,20 @@ impl<'tcx> TyCtxt<'tcx> { OnHit: FnOnce(&Q::Value, DepNodeIndex) -> R, OnMiss: FnOnce(Q::Key, QueryLookup<'tcx, Q>) -> R, { - let cache = Q::query_cache(self); - - // We compute the key's hash once and then use it for both the - // shard lookup and the hashmap lookup. This relies on the fact - // that both of them use `FxHasher`. - let mut state = FxHasher::default(); - key.hash(&mut state); - let key_hash = state.finish(); - - let shard = cache.get_shard_index_by_hash(key_hash); - let mut lock_guard = cache.get_shard_by_index(shard).lock(); - let lock = &mut *lock_guard; + let state = Q::query_state(self); - let result = lock.results.raw_entry().from_key_hashed_nocheck(key_hash, &key); - - if let Some((_, value)) = result { - if unlikely!(self.prof.enabled()) { - self.prof.query_cache_hit(value.index.into()); - } - - on_hit(&value.value, value.index) - } else { - on_miss(key, QueryLookup { lock: lock_guard, shard }) - } + state.cache.lookup( + state, + QueryStateShard::::get_cache, + key, + |value, index| { + if unlikely!(self.prof.enabled()) { + self.prof.query_cache_hit(index.into()); + } + on_hit(value, index) + }, + on_miss, + ) } #[inline(never)] @@ -430,7 +459,7 @@ impl<'tcx> TyCtxt<'tcx> { self.dep_graph.read_index(index); value.clone() }, - |key, lookup| self.try_execute_query(span, key, lookup), + |key, lookup| self.try_execute_query::(span, key, lookup), ) } @@ -602,7 +631,7 @@ impl<'tcx> TyCtxt<'tcx> { fn force_query_with_job>( self, key: Q::Key, - job: JobOwner<'_, 'tcx, Q>, + job: JobOwner<'tcx, Q>, dep_node: DepNode, ) -> (Q::Value, DepNodeIndex) { // If the following assertion triggers, it can have two reasons: @@ -783,7 +812,6 @@ macro_rules! define_queries_inner { [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)*) => { use std::mem; - use rustc_data_structures::sharded::Sharded; use crate::{ rustc_data_structures::stable_hasher::HashStable, rustc_data_structures::stable_hasher::StableHasher, @@ -818,11 +846,11 @@ macro_rules! define_queries_inner { $( // We use try_lock_shards here since we are called from the // deadlock handler, and this shouldn't be locked. - let shards = self.$name.try_lock_shards()?; + let shards = self.$name.shards.try_lock_shards()?; let shards = shards.iter().enumerate(); jobs.extend(shards.flat_map(|(shard_id, shard)| { shard.active.iter().filter_map(move |(k, v)| { - if let QueryResult::Started(ref job) = *v { + if let QueryResult::Started(ref job) = *v { let id = QueryJobId { job: job.id, shard: u16::try_from(shard_id).unwrap(), @@ -834,9 +862,9 @@ macro_rules! define_queries_inner { query: queries::$name::query(k.clone()) }; Some((id, QueryJobInfo { info, job: job.clone() })) - } else { - None - } + } else { + None + } }) })); )* @@ -858,22 +886,21 @@ macro_rules! define_queries_inner { entry_count: usize, } - fn stats<'tcx, Q: QueryConfig<'tcx>>( + fn stats<'tcx, Q: QueryAccessors<'tcx>>( name: &'static str, - map: &Sharded>, + map: &QueryState<'tcx, Q>, ) -> QueryStats { - let map = map.lock_shards(); QueryStats { name, #[cfg(debug_assertions)] - cache_hits: map.iter().map(|shard| shard.cache_hits).sum(), + cache_hits: map.cache_hits, #[cfg(not(debug_assertions))] cache_hits: 0, key_size: mem::size_of::(), key_type: type_name::(), value_size: mem::size_of::(), value_type: type_name::(), - entry_count: map.iter().map(|shard| shard.results.len()).sum(), + entry_count: map.iter_results(|results| results.count()), } } @@ -1014,7 +1041,6 @@ macro_rules! define_queries_inner { $(impl<$tcx> QueryConfig<$tcx> for queries::$name<$tcx> { type Key = $K; type Value = $V; - const NAME: &'static str = stringify!($name); const CATEGORY: ProfileCategory = $category; } @@ -1023,13 +1049,15 @@ macro_rules! define_queries_inner { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); + type Cache = <<$K as Key>::CacheSelector as CacheSelector<$K, $V>>::Cache; + #[inline(always)] fn query(key: Self::Key) -> Query<'tcx> { Query::$name(key) } #[inline(always)] - fn query_cache<'a>(tcx: TyCtxt<$tcx>) -> &'a Sharded> { + fn query_state<'a>(tcx: TyCtxt<$tcx>) -> &'a QueryState<$tcx, Self> { &tcx.queries.$name } @@ -1190,7 +1218,7 @@ macro_rules! define_queries_struct { providers: IndexVec>, fallback_extern_providers: Box>, - $($(#[$attr])* $name: Sharded>>,)* + $($(#[$attr])* $name: QueryState<$tcx, queries::$name<$tcx>>,)* } }; } diff --git a/src/librustc/ty/query/profiling_support.rs b/src/librustc/ty/query/profiling_support.rs index 79b32ba83ae..99ada34d59e 100644 --- a/src/librustc/ty/query/profiling_support.rs +++ b/src/librustc/ty/query/profiling_support.rs @@ -1,11 +1,10 @@ use crate::hir::map::definitions::DefPathData; use crate::ty::context::TyCtxt; -use crate::ty::query::config::QueryConfig; -use crate::ty::query::plumbing::QueryCache; +use crate::ty::query::config::QueryAccessors; +use crate::ty::query::plumbing::QueryState; use measureme::{StringComponent, StringId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::profiling::SelfProfiler; -use rustc_data_structures::sharded::Sharded; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; use std::fmt::Debug; use std::io::Write; @@ -161,10 +160,10 @@ where pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>( tcx: TyCtxt<'tcx>, query_name: &'static str, - query_cache: &Sharded>, + query_state: &QueryState<'tcx, Q>, string_cache: &mut QueryKeyStringCache, ) where - Q: QueryConfig<'tcx>, + Q: QueryAccessors<'tcx>, { tcx.prof.with_profiler(|profiler| { let event_id_builder = profiler.event_id_builder(); @@ -181,20 +180,8 @@ pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>( // need to invoke queries itself, we cannot keep the query caches // locked while doing so. Instead we copy out the // `(query_key, dep_node_index)` pairs and release the lock again. - let query_keys_and_indices = { - let shards = query_cache.lock_shards(); - let len = shards.iter().map(|shard| shard.results.len()).sum(); - - let mut query_keys_and_indices = Vec::with_capacity(len); - - for shard in &shards { - query_keys_and_indices.extend( - shard.results.iter().map(|(q_key, q_val)| (q_key.clone(), q_val.index)), - ); - } - - query_keys_and_indices - }; + let query_keys_and_indices: Vec<_> = query_state + .iter_results(|results| results.map(|(k, _, i)| (k.clone(), i)).collect()); // Now actually allocate the strings. If allocating the strings // generates new entries in the query cache, we'll miss them but @@ -218,18 +205,14 @@ pub(super) fn alloc_self_profile_query_strings_for_query_cache<'tcx, Q>( let query_name = profiler.get_or_alloc_cached_string(query_name); let event_id = event_id_builder.from_label(query_name).to_string_id(); - let shards = query_cache.lock_shards(); + query_state.iter_results(|results| { + let query_invocation_ids: Vec<_> = results.map(|v| v.2.into()).collect(); - for shard in shards.iter() { - let query_invocation_ids = shard - .results - .values() - .map(|v| v.index) - .map(|dep_node_index| dep_node_index.into()); - - profiler - .bulk_map_query_invocation_id_to_single_string(query_invocation_ids, event_id); - } + profiler.bulk_map_query_invocation_id_to_single_string( + query_invocation_ids.into_iter(), + event_id, + ); + }); } }); } From 8a2ad75a60b599cab49b57000660b884e8fb27dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 14 Feb 2020 18:29:20 +0100 Subject: [PATCH 0331/1250] Add a `storage` query modifier to override the query cache --- src/librustc/dep_graph/dep_node.rs | 12 ++++----- src/librustc/ty/query/plumbing.rs | 40 +++++++++++++++++++----------- src/librustc_macros/src/query.rs | 21 ++++++++++++++++ 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 29b94986a5f..963f45b3f17 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -99,17 +99,17 @@ macro_rules! is_eval_always_attr { } macro_rules! contains_anon_attr { - ($($attr:ident),*) => ({$(is_anon_attr!($attr) | )* false}); + ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_anon_attr!($attr) | )* false}); } macro_rules! contains_eval_always_attr { - ($($attr:ident),*) => ({$(is_eval_always_attr!($attr) | )* false}); + ($($attr:ident $(($($attr_args:tt)*))* ),*) => ({$(is_eval_always_attr!($attr) | )* false}); } macro_rules! define_dep_nodes { (<$tcx:tt> $( - [$($attr:ident),* ] + [$($attrs:tt)*] $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* ,)* @@ -126,7 +126,7 @@ macro_rules! define_dep_nodes { match *self { $( DepKind :: $variant => { - if contains_anon_attr!($($attr),*) { + if contains_anon_attr!($($attrs)*) { return false; } @@ -152,7 +152,7 @@ macro_rules! define_dep_nodes { pub fn is_anon(&self) -> bool { match *self { $( - DepKind :: $variant => { contains_anon_attr!($($attr),*) } + DepKind :: $variant => { contains_anon_attr!($($attrs)*) } )* } } @@ -160,7 +160,7 @@ macro_rules! define_dep_nodes { pub fn is_eval_always(&self) -> bool { match *self { $( - DepKind :: $variant => { contains_eval_always_attr!($($attr), *) } + DepKind :: $variant => { contains_eval_always_attr!($($attrs)*) } )* } } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 3eaf4e36f39..13132739f89 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -746,17 +746,17 @@ macro_rules! handle_cycle_error { $tcx.report_cycle($error).emit(); Value::from_cycle_error($tcx) }}; - ([fatal_cycle$(, $modifiers:ident)*][$tcx:expr, $error:expr]) => {{ + ([fatal_cycle $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $tcx.report_cycle($error).emit(); $tcx.sess.abort_if_errors(); unreachable!() }}; - ([cycle_delay_bug$(, $modifiers:ident)*][$tcx:expr, $error:expr]) => {{ + ([cycle_delay_bug $($rest:tt)*][$tcx:expr, $error:expr]) => {{ $tcx.report_cycle($error).delay_as_bug(); Value::from_cycle_error($tcx) }}; - ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => { - handle_cycle_error!([$($modifiers),*][$($args)*]) + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { + handle_cycle_error!([$($($modifiers)*)*][$($args)*]) }; } @@ -764,11 +764,11 @@ macro_rules! is_anon { ([]) => {{ false }}; - ([anon$(, $modifiers:ident)*]) => {{ + ([anon $($rest:tt)*]) => {{ true }}; - ([$other:ident$(, $modifiers:ident)*]) => { - is_anon!([$($modifiers),*]) + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { + is_anon!([$($($modifiers)*)*]) }; } @@ -776,11 +776,23 @@ macro_rules! is_eval_always { ([]) => {{ false }}; - ([eval_always$(, $modifiers:ident)*]) => {{ + ([eval_always $($rest:tt)*]) => {{ true }}; - ([$other:ident$(, $modifiers:ident)*]) => { - is_eval_always!([$($modifiers),*]) + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*]) => { + is_eval_always!([$($($modifiers)*)*]) + }; +} + +macro_rules! query_storage { + ([][$K:ty, $V:ty]) => { + <<$K as Key>::CacheSelector as CacheSelector<$K, $V>>::Cache + }; + ([storage($ty:ty) $($rest:tt)*][$K:ty, $V:ty]) => { + $ty + }; + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { + query_storage!([$($($modifiers)*)*][$($args)*]) }; } @@ -788,11 +800,11 @@ macro_rules! hash_result { ([][$hcx:expr, $result:expr]) => {{ dep_graph::hash_result($hcx, &$result) }}; - ([no_hash$(, $modifiers:ident)*][$hcx:expr, $result:expr]) => {{ + ([no_hash $($rest:tt)*][$hcx:expr, $result:expr]) => {{ None }}; - ([$other:ident$(, $modifiers:ident)*][$($args:tt)*]) => { - hash_result!([$($modifiers),*][$($args)*]) + ([$other:ident $(($($other_args:tt)*))* $(, $($modifiers:tt)*)*][$($args:tt)*]) => { + hash_result!([$($($modifiers)*)*][$($args)*]) }; } @@ -1049,7 +1061,7 @@ macro_rules! define_queries_inner { const ANON: bool = is_anon!([$($modifiers)*]); const EVAL_ALWAYS: bool = is_eval_always!([$($modifiers)*]); - type Cache = <<$K as Key>::CacheSelector as CacheSelector<$K, $V>>::Cache; + type Cache = query_storage!([$($modifiers)*][$K, $V]); #[inline(always)] fn query(key: Self::Key) -> Query<'tcx> { diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 294cdb7643f..6362f3c2c49 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -33,6 +33,9 @@ enum QueryModifier { /// The description of the query. Desc(Option, Punctuated), + /// Use this type for the in-memory cache. + Storage(Type), + /// Cache the query to disk if the `Expr` returns true. Cache(Option<(IdentOrWild, IdentOrWild)>, Block), @@ -106,6 +109,9 @@ impl Parse for QueryModifier { let id = args.parse()?; let block = input.parse()?; Ok(QueryModifier::LoadCached(tcx, id, block)) + } else if modifier == "storage" { + let ty = input.parse()?; + Ok(QueryModifier::Storage(ty)) } else if modifier == "fatal_cycle" { Ok(QueryModifier::FatalCycle) } else if modifier == "cycle_delay_bug" { @@ -198,6 +204,9 @@ struct QueryModifiers { /// The description of the query. desc: Option<(Option, Punctuated)>, + /// Use this type for the in-memory cache. + storage: Option, + /// Cache the query to disk if the `Block` returns true. cache: Option<(Option<(IdentOrWild, IdentOrWild)>, Block)>, @@ -226,6 +235,7 @@ struct QueryModifiers { /// Process query modifiers into a struct, erroring on duplicates fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut load_cached = None; + let mut storage = None; let mut cache = None; let mut desc = None; let mut fatal_cycle = false; @@ -242,6 +252,12 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } load_cached = Some((tcx, id, block)); } + QueryModifier::Storage(ty) => { + if storage.is_some() { + panic!("duplicate modifier `storage` for query `{}`", query.name); + } + storage = Some(ty); + } QueryModifier::Cache(args, expr) => { if cache.is_some() { panic!("duplicate modifier `cache` for query `{}`", query.name); @@ -294,6 +310,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } QueryModifiers { load_cached, + storage, cache, desc, fatal_cycle, @@ -451,6 +468,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if modifiers.fatal_cycle { attributes.push(quote! { fatal_cycle }); }; + // Pass on the storage modifier + if let Some(ref ty) = modifiers.storage { + attributes.push(quote! { storage(#ty) }); + }; // Pass on the cycle_delay_bug modifier if modifiers.cycle_delay_bug { attributes.push(quote! { cycle_delay_bug }); From d1a81c779dcc6022ff591f219a0d14e001a51f7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 15 Feb 2020 09:48:10 +0100 Subject: [PATCH 0332/1250] Split query stats into its own file --- src/librustc/ty/query/mod.rs | 4 +- src/librustc/ty/query/plumbing.rs | 95 ---------------------------- src/librustc/ty/query/stats.rs | 102 ++++++++++++++++++++++++++++++ src/librustc_interface/passes.rs | 4 +- src/librustc_interface/queries.rs | 2 +- 5 files changed, 108 insertions(+), 99 deletions(-) create mode 100644 src/librustc/ty/query/stats.rs diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 91ae11b327e..540344a11ed 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -52,7 +52,6 @@ use rustc_target::spec::PanicStrategy; use rustc_attr as attr; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; -use std::any::type_name; use std::borrow::Cow; use std::convert::TryFrom; use std::ops::Deref; @@ -64,6 +63,9 @@ mod plumbing; use self::plumbing::*; pub use self::plumbing::{force_from_dep_node, CycleError}; +mod stats; +pub use self::stats::print_stats; + mod job; #[cfg(parallel_compiler)] pub use self::job::handle_deadlock; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 13132739f89..c724209f878 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -883,101 +883,6 @@ macro_rules! define_queries_inner { Some(jobs) } - - pub fn print_stats(&self) { - let mut queries = Vec::new(); - - #[derive(Clone)] - struct QueryStats { - name: &'static str, - cache_hits: usize, - key_size: usize, - key_type: &'static str, - value_size: usize, - value_type: &'static str, - entry_count: usize, - } - - fn stats<'tcx, Q: QueryAccessors<'tcx>>( - name: &'static str, - map: &QueryState<'tcx, Q>, - ) -> QueryStats { - QueryStats { - name, - #[cfg(debug_assertions)] - cache_hits: map.cache_hits, - #[cfg(not(debug_assertions))] - cache_hits: 0, - key_size: mem::size_of::(), - key_type: type_name::(), - value_size: mem::size_of::(), - value_type: type_name::(), - entry_count: map.iter_results(|results| results.count()), - } - } - - $( - queries.push(stats::>( - stringify!($name), - &self.$name, - )); - )* - - if cfg!(debug_assertions) { - let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); - let results: usize = queries.iter().map(|s| s.entry_count).sum(); - println!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64); - } - - let mut query_key_sizes = queries.clone(); - query_key_sizes.sort_by_key(|q| q.key_size); - println!("\nLarge query keys:"); - for q in query_key_sizes.iter().rev() - .filter(|q| q.key_size > 8) { - println!( - " {} - {} x {} - {}", - q.name, - q.key_size, - q.entry_count, - q.key_type - ); - } - - let mut query_value_sizes = queries.clone(); - query_value_sizes.sort_by_key(|q| q.value_size); - println!("\nLarge query values:"); - for q in query_value_sizes.iter().rev() - .filter(|q| q.value_size > 8) { - println!( - " {} - {} x {} - {}", - q.name, - q.value_size, - q.entry_count, - q.value_type - ); - } - - if cfg!(debug_assertions) { - let mut query_cache_hits = queries.clone(); - query_cache_hits.sort_by_key(|q| q.cache_hits); - println!("\nQuery cache hits:"); - for q in query_cache_hits.iter().rev() { - println!( - " {} - {} ({}%)", - q.name, - q.cache_hits, - q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64 - ); - } - } - - let mut query_value_count = queries.clone(); - query_value_count.sort_by_key(|q| q.entry_count); - println!("\nQuery value count:"); - for q in query_value_count.iter().rev() { - println!(" {} - {}", q.name, q.entry_count); - } - } } #[allow(nonstandard_style)] diff --git a/src/librustc/ty/query/stats.rs b/src/librustc/ty/query/stats.rs new file mode 100644 index 00000000000..0c775e5f728 --- /dev/null +++ b/src/librustc/ty/query/stats.rs @@ -0,0 +1,102 @@ +use crate::ty::query::config::QueryAccessors; +use crate::ty::query::plumbing::QueryState; +use crate::ty::query::queries; +use crate::ty::TyCtxt; + +use std::any::type_name; +use std::mem; + +#[derive(Clone)] +struct QueryStats { + name: &'static str, + cache_hits: usize, + key_size: usize, + key_type: &'static str, + value_size: usize, + value_type: &'static str, + entry_count: usize, +} + +fn stats<'tcx, Q: QueryAccessors<'tcx>>( + name: &'static str, + map: &QueryState<'tcx, Q>, +) -> QueryStats { + QueryStats { + name, + #[cfg(debug_assertions)] + cache_hits: map.cache_hits, + #[cfg(not(debug_assertions))] + cache_hits: 0, + key_size: mem::size_of::(), + key_type: type_name::(), + value_size: mem::size_of::(), + value_type: type_name::(), + entry_count: map.iter_results(|results| results.count()), + } +} + +pub fn print_stats(tcx: TyCtxt<'_>) { + let queries = query_stats(tcx); + + if cfg!(debug_assertions) { + let hits: usize = queries.iter().map(|s| s.cache_hits).sum(); + let results: usize = queries.iter().map(|s| s.entry_count).sum(); + println!("\nQuery cache hit rate: {}", hits as f64 / (hits + results) as f64); + } + + let mut query_key_sizes = queries.clone(); + query_key_sizes.sort_by_key(|q| q.key_size); + println!("\nLarge query keys:"); + for q in query_key_sizes.iter().rev().filter(|q| q.key_size > 8) { + println!(" {} - {} x {} - {}", q.name, q.key_size, q.entry_count, q.key_type); + } + + let mut query_value_sizes = queries.clone(); + query_value_sizes.sort_by_key(|q| q.value_size); + println!("\nLarge query values:"); + for q in query_value_sizes.iter().rev().filter(|q| q.value_size > 8) { + println!(" {} - {} x {} - {}", q.name, q.value_size, q.entry_count, q.value_type); + } + + if cfg!(debug_assertions) { + let mut query_cache_hits = queries.clone(); + query_cache_hits.sort_by_key(|q| q.cache_hits); + println!("\nQuery cache hits:"); + for q in query_cache_hits.iter().rev() { + println!( + " {} - {} ({}%)", + q.name, + q.cache_hits, + q.cache_hits as f64 / (q.cache_hits + q.entry_count) as f64 + ); + } + } + + let mut query_value_count = queries.clone(); + query_value_count.sort_by_key(|q| q.entry_count); + println!("\nQuery value count:"); + for q in query_value_count.iter().rev() { + println!(" {} - {}", q.name, q.entry_count); + } +} + +macro_rules! print_stats { + (<$tcx:tt> $($category:tt { + $($(#[$attr:meta])* [$($modifiers:tt)*] fn $name:ident: $node:ident($K:ty) -> $V:ty,)* + },)*) => { + fn query_stats(tcx: TyCtxt<'_>) -> Vec { + let mut queries = Vec::new(); + + $($( + queries.push(stats::>( + stringify!($name), + &tcx.queries.$name, + )); + )*)* + + queries + } + } +} + +rustc_query_append! { [print_stats!][<'tcx>] } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 0b4a337051f..96a2ac08f2c 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -696,8 +696,8 @@ impl<'tcx> QueryContext<'tcx> { ty::tls::enter_global(self.0, |tcx| f(tcx)) } - pub fn print_stats(&self) { - self.0.queries.print_stats() + pub fn print_stats(&mut self) { + self.enter(|tcx| ty::query::print_stats(tcx)) } } diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 720d162ac81..0c77ab57500 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -340,7 +340,7 @@ impl Compiler { if self.session().opts.debugging_opts.query_stats { if let Ok(gcx) = queries.global_ctxt() { - gcx.peek().print_stats(); + gcx.peek_mut().print_stats(); } } From 52872ca1cbefd48c3639dcf7d3b32fa0d460a1df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 15 Feb 2020 10:44:27 +0100 Subject: [PATCH 0333/1250] Add a stat for local DefId density --- src/librustc/ty/query/stats.rs | 37 ++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/query/stats.rs b/src/librustc/ty/query/stats.rs index 0c775e5f728..cecad5f2eeb 100644 --- a/src/librustc/ty/query/stats.rs +++ b/src/librustc/ty/query/stats.rs @@ -2,10 +2,27 @@ use crate::ty::query::config::QueryAccessors; use crate::ty::query::plumbing::QueryState; use crate::ty::query::queries; use crate::ty::TyCtxt; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use std::any::type_name; use std::mem; +trait KeyStats { + fn key_stats(&self, stats: &mut QueryStats); +} + +impl KeyStats for T { + default fn key_stats(&self, _: &mut QueryStats) {} +} + +impl KeyStats for DefId { + fn key_stats(&self, stats: &mut QueryStats) { + if self.krate == LOCAL_CRATE { + stats.local_def_id_keys = Some(stats.local_def_id_keys.unwrap_or(0) + 1); + } + } +} + #[derive(Clone)] struct QueryStats { name: &'static str, @@ -15,13 +32,14 @@ struct QueryStats { value_size: usize, value_type: &'static str, entry_count: usize, + local_def_id_keys: Option, } fn stats<'tcx, Q: QueryAccessors<'tcx>>( name: &'static str, map: &QueryState<'tcx, Q>, ) -> QueryStats { - QueryStats { + let mut stats = QueryStats { name, #[cfg(debug_assertions)] cache_hits: map.cache_hits, @@ -32,7 +50,14 @@ fn stats<'tcx, Q: QueryAccessors<'tcx>>( value_size: mem::size_of::(), value_type: type_name::(), entry_count: map.iter_results(|results| results.count()), - } + local_def_id_keys: None, + }; + map.iter_results(|results| { + for (key, _, _) in results { + key.key_stats(&mut stats) + } + }); + stats } pub fn print_stats(tcx: TyCtxt<'_>) { @@ -78,6 +103,14 @@ pub fn print_stats(tcx: TyCtxt<'_>) { for q in query_value_count.iter().rev() { println!(" {} - {}", q.name, q.entry_count); } + + let mut def_id_density: Vec<_> = + queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect(); + def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap()); + println!("\nLocal DefId density:"); + for q in def_id_density.iter().rev() { + println!(" {} - {}", q.name, q.local_def_id_keys.unwrap()); + } } macro_rules! print_stats { From 19170cd217c1469fd7d78c6a99caf6b2bfc91f90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 15 Feb 2020 12:00:31 +0100 Subject: [PATCH 0334/1250] Fix cache hit stats --- src/librustc/ty/query/plumbing.rs | 10 ++++++++-- src/librustc/ty/query/stats.rs | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index c724209f878..781ed03f224 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -24,6 +24,8 @@ use std::hash::{Hash, Hasher}; use std::mem; use std::num::NonZeroU32; use std::ptr; +#[cfg(debug_assertions)] +use std::sync::atomic::{AtomicUsize, Ordering}; pub(crate) struct QueryStateShard<'tcx, D: QueryAccessors<'tcx> + ?Sized> { pub(super) cache: <>::Cache as QueryCache>::Sharded, @@ -51,7 +53,7 @@ pub(crate) struct QueryState<'tcx, D: QueryAccessors<'tcx> + ?Sized> { pub(super) cache: D::Cache, pub(super) shards: Sharded>, #[cfg(debug_assertions)] - pub(super) cache_hits: usize, + pub(super) cache_hits: AtomicUsize, } impl<'tcx, Q: QueryAccessors<'tcx>> QueryState<'tcx, Q> { @@ -100,7 +102,7 @@ impl<'tcx, M: QueryAccessors<'tcx>> Default for QueryState<'tcx, M> { cache: M::Cache::default(), shards: Default::default(), #[cfg(debug_assertions)] - cache_hits: 0, + cache_hits: AtomicUsize::new(0), } } } @@ -439,6 +441,10 @@ impl<'tcx> TyCtxt<'tcx> { if unlikely!(self.prof.enabled()) { self.prof.query_cache_hit(index.into()); } + #[cfg(debug_assertions)] + { + state.cache_hits.fetch_add(1, Ordering::Relaxed); + } on_hit(value, index) }, on_miss, diff --git a/src/librustc/ty/query/stats.rs b/src/librustc/ty/query/stats.rs index cecad5f2eeb..d257320d4ea 100644 --- a/src/librustc/ty/query/stats.rs +++ b/src/librustc/ty/query/stats.rs @@ -6,6 +6,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use std::any::type_name; use std::mem; +#[cfg(debug_assertions)] +use std::sync::atomic::Ordering; trait KeyStats { fn key_stats(&self, stats: &mut QueryStats); @@ -42,7 +44,7 @@ fn stats<'tcx, Q: QueryAccessors<'tcx>>( let mut stats = QueryStats { name, #[cfg(debug_assertions)] - cache_hits: map.cache_hits, + cache_hits: map.cache_hits.load(Ordering::Relaxed), #[cfg(not(debug_assertions))] cache_hits: 0, key_size: mem::size_of::(), @@ -108,8 +110,10 @@ pub fn print_stats(tcx: TyCtxt<'_>) { queries.iter().filter(|q| q.local_def_id_keys.is_some()).collect(); def_id_density.sort_by_key(|q| q.local_def_id_keys.unwrap()); println!("\nLocal DefId density:"); + let total = tcx.hir().definitions().def_index_count() as f64; for q in def_id_density.iter().rev() { - println!(" {} - {}", q.name, q.local_def_id_keys.unwrap()); + let local = q.local_def_id_keys.unwrap(); + println!(" {} - {} = ({}%)", q.name, local, (local as f64 * 100.0) / total); } } From a8522256c5ad5d7ec3b0f10f0d23da84d72ce73a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 17 Feb 2020 18:38:30 +0100 Subject: [PATCH 0335/1250] Tune inlining --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc_data_structures/profiling.rs | 9 ++++++--- src/librustc_data_structures/stable_hasher.rs | 1 + src/librustc_session/session.rs | 1 + 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index ae2fde96617..531a45b120c 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -1122,7 +1122,7 @@ impl CurrentDepGraph { } impl DepGraphData { - #[inline] + #[inline(never)] fn read_index(&self, source: DepNodeIndex) { ty::tls::with_context_opt(|icx| { let icx = if let Some(icx) = icx { icx } else { return }; diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index 1d0ac4f4907..f2c80510f22 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -81,6 +81,7 @@ //! //! [mm]: https://github.com/rust-lang/measureme/ +use crate::cold_path; use crate::fx::FxHashMap; use std::borrow::Borrow; @@ -531,9 +532,11 @@ impl<'a> TimingGuard<'a> { #[inline] pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) { if let Some(guard) = self.0 { - let event_id = StringId::new_virtual(query_invocation_id.0); - let event_id = EventId::from_virtual(event_id); - guard.finish_with_override_event_id(event_id); + cold_path(|| { + let event_id = StringId::new_virtual(query_invocation_id.0); + let event_id = EventId::from_virtual(event_id); + guard.finish_with_override_event_id(event_id); + }); } } diff --git a/src/librustc_data_structures/stable_hasher.rs b/src/librustc_data_structures/stable_hasher.rs index 0a26bf3bdc9..a98e77cebd8 100644 --- a/src/librustc_data_structures/stable_hasher.rs +++ b/src/librustc_data_structures/stable_hasher.rs @@ -27,6 +27,7 @@ pub trait StableHasherResult: Sized { } impl StableHasher { + #[inline] pub fn new() -> Self { StableHasher { state: SipHasher128::new_with_keys(0, 0) } } diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 6f003043aa9..2fb7977dce9 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -392,6 +392,7 @@ impl Session { ); } + #[inline] pub fn source_map(&self) -> &source_map::SourceMap { self.parse_sess.source_map() } From b248767a0740b2031500ad62078f79d9eeb652aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 17 Feb 2020 18:41:21 +0100 Subject: [PATCH 0336/1250] Remove support for dep node structs --- src/librustc/dep_graph/dep_node.rs | 41 ------------------------------ 1 file changed, 41 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 963f45b3f17..216749a4930 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -111,7 +111,6 @@ macro_rules! define_dep_nodes { $( [$($attrs:tt)*] $variant:ident $(( $tuple_arg_ty:ty $(,)? ))* - $({ $($struct_arg_name:ident : $struct_arg_ty:ty),* })* ,)* ) => ( #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, @@ -136,13 +135,6 @@ macro_rules! define_dep_nodes { ::CAN_RECONSTRUCT_QUERY_KEY; })* - // struct args - $({ - - return <( $($struct_arg_ty,)* ) as DepNodeParams> - ::CAN_RECONSTRUCT_QUERY_KEY; - })* - true } )* @@ -176,12 +168,6 @@ macro_rules! define_dep_nodes { return true; })* - // struct args - $({ - $(erase!($struct_arg_name);)* - return true; - })* - false } )* @@ -192,7 +178,6 @@ macro_rules! define_dep_nodes { pub enum DepConstructor<$tcx> { $( $variant $(( $tuple_arg_ty ))* - $({ $($struct_arg_name : $struct_arg_ty),* })* ),* } @@ -212,7 +197,6 @@ macro_rules! define_dep_nodes { match dep { $( DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))* - $({ $($struct_arg_name),* })* => { // tuple args @@ -239,31 +223,6 @@ macro_rules! define_dep_nodes { return dep_node; })* - // struct args - $({ - let tupled_args = ( $($struct_arg_name,)* ); - let hash = DepNodeParams::to_fingerprint(&tupled_args, - tcx); - let dep_node = DepNode { - kind: DepKind::$variant, - hash - }; - - #[cfg(debug_assertions)] - { - if !dep_node.kind.can_reconstruct_query_key() && - (tcx.sess.opts.debugging_opts.incremental_info || - tcx.sess.opts.debugging_opts.query_dep_graph) - { - tcx.dep_graph.register_dep_node_debug_str(dep_node, || { - tupled_args.to_debug_str(tcx) - }); - } - } - - return dep_node; - })* - DepNode { kind: DepKind::$variant, hash: Fingerprint::ZERO, From d924a251f120ba44fd091962fcda733591a07485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 17 Feb 2020 19:04:06 +0100 Subject: [PATCH 0337/1250] Use a constructor function per dep node instead of an enum and a single function --- src/librustc/dep_graph/dep_node.rs | 86 +++++++++++++----------------- src/librustc/mir/mono.rs | 2 +- src/librustc/ty/context.rs | 4 +- src/librustc/ty/query/mod.rs | 2 +- src/librustc/ty/query/plumbing.rs | 4 +- 5 files changed, 41 insertions(+), 57 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 216749a4930..eb7e2871bfc 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -76,10 +76,6 @@ macro_rules! erase { ($x:tt) => {{}}; } -macro_rules! replace { - ($x:tt with $($y:tt)*) => ($($y)*) -} - macro_rules! is_anon_attr { (anon) => { true @@ -175,10 +171,43 @@ macro_rules! define_dep_nodes { } } - pub enum DepConstructor<$tcx> { + pub struct DepConstructor; + + impl DepConstructor { $( - $variant $(( $tuple_arg_ty ))* - ),* + #[inline(always)] + #[allow(unreachable_code, non_snake_case)] + pub fn $variant<'tcx>(_tcx: TyCtxt<'tcx>, $(arg: $tuple_arg_ty)*) -> DepNode { + // tuple args + $({ + erase!($tuple_arg_ty); + let hash = DepNodeParams::to_fingerprint(&arg, _tcx); + let dep_node = DepNode { + kind: DepKind::$variant, + hash + }; + + #[cfg(debug_assertions)] + { + if !dep_node.kind.can_reconstruct_query_key() && + (_tcx.sess.opts.debugging_opts.incremental_info || + _tcx.sess.opts.debugging_opts.query_dep_graph) + { + _tcx.dep_graph.register_dep_node_debug_str(dep_node, || { + arg.to_debug_str(_tcx) + }); + } + } + + return dep_node; + })* + + DepNode { + kind: DepKind::$variant, + hash: Fingerprint::ZERO, + } + } + )* } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, @@ -189,49 +218,6 @@ macro_rules! define_dep_nodes { } impl DepNode { - #[allow(unreachable_code, non_snake_case)] - pub fn new<'tcx>(tcx: TyCtxt<'tcx>, - dep: DepConstructor<'tcx>) - -> DepNode - { - match dep { - $( - DepConstructor :: $variant $(( replace!(($tuple_arg_ty) with arg) ))* - => - { - // tuple args - $({ - erase!($tuple_arg_ty); - let hash = DepNodeParams::to_fingerprint(&arg, tcx); - let dep_node = DepNode { - kind: DepKind::$variant, - hash - }; - - #[cfg(debug_assertions)] - { - if !dep_node.kind.can_reconstruct_query_key() && - (tcx.sess.opts.debugging_opts.incremental_info || - tcx.sess.opts.debugging_opts.query_dep_graph) - { - tcx.dep_graph.register_dep_node_debug_str(dep_node, || { - arg.to_debug_str(tcx) - }); - } - } - - return dep_node; - })* - - DepNode { - kind: DepKind::$variant, - hash: Fingerprint::ZERO, - } - } - )* - } - } - /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 6da7c09c7df..9a3ddfb0e82 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -362,7 +362,7 @@ impl<'tcx> CodegenUnit<'tcx> { } pub fn codegen_dep_node(&self, tcx: TyCtxt<'tcx>) -> DepNode { - DepNode::new(tcx, DepConstructor::CompileCodegenUnit(self.name())) + DepConstructor::CompileCodegenUnit(tcx, self.name()) } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 68c9ccc455f..e59738d8886 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2,7 +2,7 @@ use crate::arena::Arena; use crate::dep_graph::DepGraph; -use crate::dep_graph::{self, DepConstructor, DepNode}; +use crate::dep_graph::{self, DepConstructor}; use crate::hir::exports::Export; use crate::hir::map as hir_map; use crate::hir::map::DefPathHash; @@ -1347,7 +1347,7 @@ impl<'tcx> TyCtxt<'tcx> { // We cannot use the query versions of crates() and crate_hash(), since // those would need the DepNodes that we are allocating here. for cnum in self.cstore.crates_untracked() { - let dep_node = DepNode::new(self, DepConstructor::CrateMetadata(cnum)); + let dep_node = DepConstructor::CrateMetadata(self, cnum); let crate_hash = self.cstore.crate_hash_untracked(cnum); self.dep_graph.with_task( dep_node, diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 540344a11ed..381a7b1f03f 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{self, DepNode}; +use crate::dep_graph::{self, DepConstructor, DepNode}; use crate::hir::exports::Export; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 781ed03f224..a61256b9fcb 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -987,9 +987,7 @@ macro_rules! define_queries_inner { #[allow(unused)] #[inline(always)] fn to_dep_node(tcx: TyCtxt<$tcx>, key: &Self::Key) -> DepNode { - use crate::dep_graph::DepConstructor::*; - - DepNode::new(tcx, $node(*key)) + DepConstructor::$node(tcx, *key) } #[inline(always)] From 1b342f70dfb999e19026979f28a76952dcc216f4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 19 Feb 2020 12:59:35 +0100 Subject: [PATCH 0338/1250] Clean up E0317 explanation --- src/librustc_error_codes/error_codes/E0317.md | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0317.md b/src/librustc_error_codes/error_codes/E0317.md index e31a2b56be3..230911c2086 100644 --- a/src/librustc_error_codes/error_codes/E0317.md +++ b/src/librustc_error_codes/error_codes/E0317.md @@ -1,14 +1,30 @@ -This error occurs when an `if` expression without an `else` block is used in a -context where a type other than `()` is expected, for example a `let` -expression: +An `if` expression is missing an `else` block. + +Erroneous code example: ```compile_fail,E0317 -fn main() { - let x = 5; - let a = if x == 5 { 1 }; -} +let x = 5; +let a = if x == 5 { + 1 +}; ``` +This error occurs when an `if` expression without an `else` block is used in a +context where a type other than `()` is expected. In the previous code example, +the `let` expression was expecting a value but since there was no `else`, no +value was returned. + An `if` expression without an `else` block has the type `()`, so this is a type error. To resolve it, add an `else` block having the same type as the `if` block. + +So to fix the previous code example: + +``` +let x = 5; +let a = if x == 5 { + 1 +} else { + 2 +}; +``` From c797ce7877dff9189d828247493dfcada9c10e43 Mon Sep 17 00:00:00 2001 From: Bijan Tabatabai Date: Fri, 31 Jan 2020 10:16:55 -0600 Subject: [PATCH 0339/1250] Add LinkedList::remove() LinkedList::remove() removes the element at the specified index and returns it. Signed-off-by: Bijan Tabatabai --- src/liballoc/collections/linked_list.rs | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index b88ca8a0fb0..f8f987efeb8 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -878,6 +878,52 @@ impl LinkedList { unsafe { self.split_off_after_node(split_node, at) } } + /// Removes the element at the given index and returns it. + /// + /// This operation should compute in O(n) time. + /// + /// # Panics + /// Panics if at >= len + /// + /// # Examples + /// + /// ``` + /// #![feature(linked_list_remove)] + /// use std::collections::LinkedList; + /// + /// let mut d = LinkedList::new(); + /// + /// d.push_front(1); + /// d.push_front(2); + /// d.push_front(3); + /// + /// assert_eq!(d.remove(1), 2); + /// assert_eq!(d.remove(0), 3); + /// assert_eq!(d.remove(0), 1); + /// ``` + #[unstable(feature = "linked_list_remove", issue = "69210")] + pub fn remove(&mut self, at: usize) -> T { + let len = self.len(); + assert!(at < len, "Cannot remove at an index outside of the list bounds"); + + // Below, we iterate towards the node at the given index, either from + // the start or the end, depending on which would be faster. + let offset_from_end = len - at - 1; + if at <= offset_from_end { + let mut cursor = self.cursor_front_mut(); + for _ in 0..at { + cursor.move_next(); + } + cursor.remove_current().unwrap() + } else { + let mut cursor = self.cursor_back_mut(); + for _ in 0..offset_from_end { + cursor.move_prev(); + } + cursor.remove_current().unwrap() + } + } + /// Creates an iterator which uses a closure to determine if an element should be removed. /// /// If the closure returns true, then the element is removed and yielded. From 310f4707e59f696814e0e800be0b5ec6e81353d5 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Wed, 19 Feb 2020 17:59:24 +0100 Subject: [PATCH 0340/1250] Make is_object_safe a method. --- src/librustc/query/mod.rs | 3 --- src/librustc/ty/mod.rs | 4 ++++ src/librustc_incremental/persist/dirty_clean.rs | 2 +- src/librustc_infer/traits/object_safety.rs | 6 +----- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index df08501f007..8c40c28bb47 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -653,9 +653,6 @@ rustc_queries! { desc { |tcx| "building specialization graph of trait `{}`", tcx.def_path_str(key) } cache_on_disk_if { true } } - query is_object_safe(key: DefId) -> bool { - desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) } - } query object_safety_violations(key: DefId) -> Vec { desc { |tcx| "determine object safety of trait `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 45ea05efd4a..b76c637e3f1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2998,6 +2998,10 @@ impl<'tcx> TyCtxt<'tcx> { }; (ident, scope) } + + pub fn is_object_safe(self, key: DefId) -> bool { + self.object_safety_violations(key).is_empty() + } } #[derive(Clone, HashStable)] diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c5e74868bda..1fa57f1ecf2 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -78,7 +78,7 @@ const BASE_STRUCT: &[&str] = const BASE_TRAIT_DEF: &[&str] = &[ label_strs::associated_item_def_ids, label_strs::generics_of, - label_strs::is_object_safe, + label_strs::object_safety_violations, label_strs::predicates_of, label_strs::specialization_graph_of, label_strs::trait_def, diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index f409c22831f..f2770720346 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -772,10 +772,6 @@ fn contains_illegal_self_type_reference<'tcx>( error } -fn is_object_safe(tcx: TyCtxt<'_>, trait_def_id: DefId) -> bool { - tcx.object_safety_violations(trait_def_id).is_empty() -} - pub fn provide(providers: &mut ty::query::Providers<'_>) { - *providers = ty::query::Providers { is_object_safe, object_safety_violations, ..*providers }; + *providers = ty::query::Providers { object_safety_violations, ..*providers }; } From 19801b12c950f727a4e6938a87b0b2fdece73c07 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 15:45:54 -0800 Subject: [PATCH 0341/1250] Update tests --- .../const-check-fns-in-const-impl.rs | 2 +- .../const-check-fns-in-const-impl.stderr | 2 +- .../ui/rfc-2632-const-trait-impl/stability.rs | 12 +++++++++++- .../rfc-2632-const-trait-impl/stability.stderr | 18 +++++++++++++++--- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs index cad4f69033b..3278f35bad2 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.rs @@ -10,7 +10,7 @@ fn non_const() {} impl const T for S { fn foo() { non_const() } - //~^ ERROR + //~^ ERROR can only call other `const fn` } fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr index 8c220dc44ab..7fe3a9fd852 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/const-check-fns-in-const-impl.stderr @@ -4,7 +4,7 @@ error[E0723]: can only call other `const fn` within a `const fn`, but `const non LL | fn foo() { non_const() } | ^^^^^^^^^^^ | - = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.rs b/src/test/ui/rfc-2632-const-trait-impl/stability.rs index 36cfaff2ffa..03a6fb51503 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.rs +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.rs @@ -6,6 +6,17 @@ pub struct Int(i32); +#[stable(feature = "rust1", since = "1.0.0")] +#[rustc_const_stable(feature = "rust1", since = "1.0.0")] +impl const std::ops::Sub for Int { + type Output = Self; + + fn sub(self, rhs: Self) -> Self { + //~^ ERROR trait methods cannot be stable const fn + Int(self.0 - rhs.0) + } +} + #[rustc_const_unstable(feature = "const_add", issue = "none")] impl const std::ops::Add for Int { type Output = Self; @@ -29,5 +40,4 @@ pub const fn bar() -> Int { Int(1i32) + Int(2i32) } - fn main() {} diff --git a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr index ce3bada01e8..1ecff62955b 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/stability.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/stability.stderr @@ -1,12 +1,24 @@ +error[E0723]: trait methods cannot be stable const fn + --> $DIR/stability.rs:14:5 + | +LL | / fn sub(self, rhs: Self) -> Self { +LL | | +LL | | Int(self.0 - rhs.0) +LL | | } + | |_____^ + | + = note: see issue #57563 for more information + = help: add `#![feature(const_fn)]` to the crate attributes to enable + error[E0723]: can only call other `const fn` within a `const fn`, but `const ::add` is not stable as `const fn` - --> $DIR/stability.rs:21:5 + --> $DIR/stability.rs:32:5 | LL | Int(1i32) + Int(2i32) | ^^^^^^^^^^^^^^^^^^^^^ | - = note: for more information, see issue https://github.com/rust-lang/rust/issues/57563 + = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0723`. From ea3c9d27cffceb9d4c8dcfda1c96b138d7f01f3d Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sun, 16 Feb 2020 14:40:12 -0800 Subject: [PATCH 0342/1250] Implement an insertion-order preserving, efficient multi-map --- src/librustc_data_structures/sorted_map.rs | 4 + .../sorted_map/index_map.rs | 218 ++++++++++++++++++ .../sorted_map/tests.rs | 28 ++- 3 files changed, 249 insertions(+), 1 deletion(-) create mode 100644 src/librustc_data_structures/sorted_map/index_map.rs diff --git a/src/librustc_data_structures/sorted_map.rs b/src/librustc_data_structures/sorted_map.rs index 08706aac11e..8c42b74b85a 100644 --- a/src/librustc_data_structures/sorted_map.rs +++ b/src/librustc_data_structures/sorted_map.rs @@ -4,6 +4,10 @@ use std::iter::FromIterator; use std::mem; use std::ops::{Bound, Index, IndexMut, RangeBounds}; +mod index_map; + +pub use index_map::SortedIndexMultiMap; + /// `SortedMap` is a data structure with similar characteristics as BTreeMap but /// slightly different trade-offs: lookup, insertion, and removal are O(log(N)) /// and elements can be iterated in order cheaply. diff --git a/src/librustc_data_structures/sorted_map/index_map.rs b/src/librustc_data_structures/sorted_map/index_map.rs new file mode 100644 index 00000000000..b7005ccdc99 --- /dev/null +++ b/src/librustc_data_structures/sorted_map/index_map.rs @@ -0,0 +1,218 @@ +//! A variant of `SortedMap` that preserves insertion order. + +use std::borrow::Borrow; +use std::hash::{Hash, Hasher}; +use std::iter::FromIterator; + +use crate::stable_hasher::{HashStable, StableHasher}; +use rustc_index::vec::{Idx, IndexVec}; + +/// An indexed multi-map that preserves insertion order while permitting both `O(log n)` lookup of +/// an item by key and `O(1)` lookup by index. +/// +/// This data structure is a hybrid of an [`IndexVec`] and a [`SortedMap`]. Like `IndexVec`, +/// `SortedIndexMultiMap` assigns a typed index to each item while preserving insertion order. +/// Like `SortedMap`, `SortedIndexMultiMap` has efficient lookup of items by key. However, this +/// is accomplished by sorting an array of item indices instead of the items themselves. +/// +/// Unlike `SortedMap`, this data structure can hold multiple equivalent items at once, so the +/// `get_by_key` method and its variants return an iterator instead of an `Option`. Equivalent +/// items will be yielded in insertion order. +/// +/// Unlike a general-purpose map like `BTreeSet` or `HashSet`, `SortedMap` and +/// `SortedIndexMultiMap` require `O(n)` time to insert a single item. This is because we may need +/// to insert into the middle of the sorted array. Users should avoid mutating this data structure +/// in-place. +/// +/// [`IndexVec`]: ../../rustc_index/vec/struct.IndexVec.html +/// [`SortedMap`]: ../sorted_map/struct.SortedMap.html +#[derive(Clone, Debug)] +pub struct SortedIndexMultiMap { + /// The elements of the map in insertion order. + items: IndexVec, + + /// Indices of the items in the set, sorted by the item's key. + idx_sorted_by_item_key: Vec, +} + +impl SortedIndexMultiMap { + pub fn new() -> Self { + SortedIndexMultiMap { items: IndexVec::new(), idx_sorted_by_item_key: Vec::new() } + } + + pub fn len(&self) -> usize { + self.items.len() + } + + pub fn is_empty(&self) -> bool { + self.items.is_empty() + } + + /// Returns an iterator over the items in the map in insertion order. + pub fn into_iter(self) -> impl DoubleEndedIterator { + self.items.into_iter() + } + + /// Returns an iterator over the items in the map in insertion order along with their indices. + pub fn into_iter_enumerated(self) -> impl DoubleEndedIterator { + self.items.into_iter_enumerated() + } + + /// Returns an iterator over the items in the map in insertion order. + pub fn iter(&self) -> impl '_ + DoubleEndedIterator { + self.items.iter().map(|(ref k, ref v)| (k, v)) + } + + /// Returns an iterator over the items in the map in insertion order along with their indices. + pub fn iter_enumerated(&self) -> impl '_ + DoubleEndedIterator { + self.items.iter_enumerated().map(|(i, (ref k, ref v))| (i, (k, v))) + } + + /// Returns the item in the map with the given index. + pub fn get(&self, idx: I) -> Option<&(K, V)> { + self.items.get(idx) + } + + /// Returns an iterator over the items in the map that are equal to `key`. + /// + /// If there are multiple items that are equivalent to `key`, they will be yielded in + /// insertion order. + pub fn get_by_key(&'a self, key: &Q) -> impl 'a + Iterator + where + Q: Ord + ?Sized, + K: Borrow, + { + self.get_by_key_enumerated(key).map(|(_, v)| v) + } + + /// Returns an iterator over the items in the map that are equal to `key` along with their + /// indices. + /// + /// If there are multiple items that are equivalent to `key`, they will be yielded in + /// insertion order. + pub fn get_by_key_enumerated(&self, key: &Q) -> impl '_ + Iterator + where + Q: Ord + ?Sized, + K: Borrow, + { + // FIXME: This should be in the standard library as `equal_range`. See rust-lang/rfcs#2184. + match self.binary_search_idx(key) { + Err(_) => self.idxs_to_items_enumerated(&[]), + + Ok(idx) => { + let start = self.find_lower_bound(key, idx); + let end = self.find_upper_bound(key, idx); + self.idxs_to_items_enumerated(&self.idx_sorted_by_item_key[start..end]) + } + } + } + + fn binary_search_idx(&self, key: &Q) -> Result + where + Q: Ord + ?Sized, + K: Borrow, + { + self.idx_sorted_by_item_key.binary_search_by(|&idx| self.items[idx].0.borrow().cmp(key)) + } + + /// Returns the index into the `idx_sorted_by_item_key` array of the first item equal to + /// `key`. + /// + /// `initial` must be an index into that same array for an item that is equal to `key`. + fn find_lower_bound(&self, key: &Q, initial: usize) -> usize + where + Q: Ord + ?Sized, + K: Borrow, + { + debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key); + + // FIXME: At present, this uses linear search, meaning lookup is only `O(log n)` if duplicate + // entries are rare. It would be better to start with a linear search for the common case but + // fall back to an exponential search if many duplicates are found. This applies to + // `upper_bound` as well. + let mut start = initial; + while start != 0 && self.items[self.idx_sorted_by_item_key[start - 1]].0.borrow() == key { + start -= 1; + } + + start + } + + /// Returns the index into the `idx_sorted_by_item_key` array of the first item greater than + /// `key`, or `self.len()` if no such item exists. + /// + /// `initial` must be an index into that same array for an item that is equal to `key`. + fn find_upper_bound(&self, key: &Q, initial: usize) -> usize + where + Q: Ord + ?Sized, + K: Borrow, + { + debug_assert!(self.items[self.idx_sorted_by_item_key[initial]].0.borrow() == key); + + // See the FIXME for `find_lower_bound`. + let mut end = initial + 1; + let len = self.items.len(); + while end < len && self.items[self.idx_sorted_by_item_key[end]].0.borrow() == key { + end += 1; + } + + end + } + + fn idxs_to_items_enumerated(&'a self, idxs: &'a [I]) -> impl 'a + Iterator { + idxs.iter().map(move |&idx| (idx, &self.items[idx].1)) + } +} + +impl Eq for SortedIndexMultiMap {} +impl PartialEq for SortedIndexMultiMap { + fn eq(&self, other: &Self) -> bool { + // No need to compare the sorted index. If the items are the same, the index will be too. + self.items == other.items + } +} + +impl Hash for SortedIndexMultiMap +where + K: Hash, + V: Hash, +{ + fn hash(&self, hasher: &mut H) { + self.items.hash(hasher) + } +} +impl HashStable for SortedIndexMultiMap +where + K: HashStable, + V: HashStable, +{ + fn hash_stable(&self, ctx: &mut C, hasher: &mut StableHasher) { + self.items.hash_stable(ctx, hasher) + } +} + +impl FromIterator<(K, V)> for SortedIndexMultiMap { + fn from_iter(iter: J) -> Self + where + J: IntoIterator, + { + let items = IndexVec::from_iter(iter); + let mut idx_sorted_by_item_key: Vec<_> = items.indices().collect(); + + // `sort_by_key` is stable, so insertion order is preserved for duplicate items. + idx_sorted_by_item_key.sort_by_key(|&idx| &items[idx].0); + + SortedIndexMultiMap { items, idx_sorted_by_item_key } + } +} + +impl std::ops::Index for SortedIndexMultiMap { + type Output = V; + + fn index(&self, idx: I) -> &Self::Output { + &self.items[idx].1 + } +} + +#[cfg(tests)] +mod tests; diff --git a/src/librustc_data_structures/sorted_map/tests.rs b/src/librustc_data_structures/sorted_map/tests.rs index 692e1deb4be..7d91e1fdcef 100644 --- a/src/librustc_data_structures/sorted_map/tests.rs +++ b/src/librustc_data_structures/sorted_map/tests.rs @@ -1,4 +1,30 @@ -use super::SortedMap; +use super::{SortedIndexMultiMap, SortedMap}; + +#[test] +fn test_sorted_index_multi_map() { + let entries: Vec<_> = vec![(2, 0), (1, 0), (2, 1), (3, 0), (2, 2)]; + let set: SortedIndexMultiMap = entries.iter().copied().collect(); + + // Insertion order is preserved. + assert!(entries.iter().map(|(ref k, ref v)| (k, v)).eq(set.iter())); + + // Indexing + for (i, expect) in entries.iter().enumerate() { + assert_eq!(set[i], expect.1); + } + + // `get_by_key` works. + assert_eq!(set.get_by_key(&3).copied().collect::>(), vec![0]); + assert!(set.get_by_key(&4).next().is_none()); + + // `get_by_key` returns items in insertion order. + let twos: Vec<_> = set.get_by_key_enumerated(&2).collect(); + let idxs: Vec = twos.iter().map(|(i, _)| *i).collect(); + let values: Vec = twos.iter().map(|(_, &v)| v).collect(); + + assert_eq!(idxs, vec![0, 2, 4]); + assert_eq!(values, vec![0, 1, 2]); +} #[test] fn test_insert_and_iter() { From 3bb7da2e4fa54519069fd110cf665cdf0407f58d Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 11 Feb 2020 10:41:28 -0800 Subject: [PATCH 0343/1250] Replace `rustc_typeck::Namespace` with `rustc_hir::def::Namespace` --- src/librustc/ty/mod.rs | 9 ++++++- src/librustc_hir/hir.rs | 11 +++++++- src/librustc_typeck/astconv.rs | 5 ++-- src/librustc_typeck/check/method/mod.rs | 5 ++-- src/librustc_typeck/check/method/probe.rs | 6 ++--- src/librustc_typeck/check/method/suggest.rs | 13 +++++---- src/librustc_typeck/check/mod.rs | 2 +- .../coherence/inherent_impls_overlap.rs | 1 - src/librustc_typeck/lib.rs | 1 - src/librustc_typeck/namespace.rs | 27 ------------------- 10 files changed, 32 insertions(+), 48 deletions(-) delete mode 100644 src/librustc_typeck/namespace.rs diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a4b4e1d6574..c70a296e34b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -33,7 +33,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; +use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::{Constness, GlobMap, Node, TraitMap}; use rustc_index::vec::{Idx, IndexVec}; @@ -216,6 +216,13 @@ impl AssocKind { ty::AssocKind::Const => "associated constant", } } + + pub fn namespace(&self) -> Namespace { + match *self { + ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::TypeNS, + ty::AssocKind::Const | ty::AssocKind::Method => Namespace::ValueNS, + } + } } impl AssocItem { diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 56a8e2cfd02..8496a6ed23b 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1,4 +1,4 @@ -use crate::def::{DefKind, Res}; +use crate::def::{DefKind, Namespace, Res}; use crate::def_id::DefId; crate use crate::hir_id::HirId; use crate::itemlikevisit; @@ -1897,6 +1897,15 @@ pub enum ImplItemKind<'hir> { OpaqueTy(GenericBounds<'hir>), } +impl ImplItemKind<'_> { + pub fn namespace(&self) -> Namespace { + match self { + ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS, + ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS, + } + } +} + // The name of the associated type for `Fn` return types. pub const FN_OUTPUT_NAME: Symbol = sym::Output; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 69970faab3f..635c3038e0a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -9,7 +9,6 @@ use crate::collect::PlaceholderHirTyCollector; use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; -use crate::namespace::Namespace; use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; @@ -20,7 +19,7 @@ use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId}; use rustc_hir as hir; -use rustc_hir::def::{CtorOf, DefKind, Res}; +use rustc_hir::def::{CtorOf, DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::print; @@ -2202,7 +2201,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let item = tcx .associated_items(trait_did) .iter() - .find(|i| Namespace::from(i.kind) == Namespace::Type && i.ident.modern() == assoc_ident) + .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident) .expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 1856157fffb..84e00244942 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -11,7 +11,6 @@ pub use self::CandidateSource::*; pub use self::MethodError::*; use crate::check::FnCtxt; -use crate::namespace::Namespace; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; @@ -19,7 +18,7 @@ use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, W use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def::{CtorOf, DefKind}; +use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; use rustc_infer::traits; @@ -342,7 +341,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Trait must have a method named `m_name` and it should not have // type parameters or early-bound regions. let tcx = self.tcx; - let method_item = match self.associated_item(trait_def_id, m_name, Namespace::Value) { + let method_item = match self.associated_item(trait_def_id, m_name, Namespace::ValueNS) { Some(method_item) => method_item, None => { tcx.sess.delay_span_bug( diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 346406fff56..5ed39f04b07 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -7,7 +7,6 @@ use crate::check::autoderef::{self, Autoderef}; use crate::check::FnCtxt; use crate::hir::def::DefKind; use crate::hir::def_id::DefId; -use crate::namespace::Namespace; use rustc::lint; use rustc::middle::stability; @@ -22,6 +21,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_hir::def::Namespace; use rustc_infer::infer::canonical::OriginalQueryValues; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; @@ -1699,13 +1699,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .iter() .filter(|x| { let dist = lev_distance(&*name.as_str(), &x.ident.as_str()); - Namespace::from(x.kind) == Namespace::Value && dist > 0 && dist <= max_dist + x.kind.namespace() == Namespace::ValueNS && dist > 0 && dist <= max_dist }) .copied() .collect() } else { self.fcx - .associated_item(def_id, name, Namespace::Value) + .associated_item(def_id, name, Namespace::ValueNS) .map_or(Vec::new(), |x| vec![x]) } } else { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 83f063aceda..ea83b40a1cb 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -3,7 +3,6 @@ use crate::check::FnCtxt; use crate::middle::lang_items::FnOnceTraitLangItem; -use crate::namespace::Namespace; use rustc::hir::map as hir_map; use rustc::hir::map::Map; use rustc::ty::print::with_crate_prefix; @@ -11,7 +10,7 @@ use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, Wit use rustc_data_structures::fx::FxHashSet; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; @@ -97,13 +96,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Provide the best span we can. Use the item, if local to crate, else // the impl, if local to crate (item may be defaulted), else nothing. let item = match self - .associated_item(impl_did, item_name, Namespace::Value) + .associated_item(impl_did, item_name, Namespace::ValueNS) .or_else(|| { let impl_trait_ref = self.tcx.impl_trait_ref(impl_did)?; self.associated_item( impl_trait_ref.def_id, item_name, - Namespace::Value, + Namespace::ValueNS, ) }) { Some(item) => item, @@ -185,7 +184,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } CandidateSource::TraitSource(trait_did) => { let item = - match self.associated_item(trait_did, item_name, Namespace::Value) { + match self.associated_item(trait_did, item_name, Namespace::ValueNS) { Some(item) => item, None => continue, }; @@ -264,7 +263,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // be used exists at all, and the type is an ambiguous numeric type // ({integer}/{float}). let mut candidates = all_traits(self.tcx).into_iter().filter_map(|info| { - self.associated_item(info.def_id, item_name, Namespace::Value) + self.associated_item(info.def_id, item_name, Namespace::ValueNS) }); if let (true, false, SelfSource::MethodCall(expr), Some(_)) = ( actual.is_numeric(), @@ -779,7 +778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // here). (type_is_local || info.def_id.is_local()) && self - .associated_item(info.def_id, item_name, Namespace::Value) + .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { // We only want to suggest public or local traits (#45781). item.vis == ty::Visibility::Public || info.def_id.is_local() diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f7145140401..d6acd8dd894 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -89,7 +89,6 @@ pub mod writeback; use crate::astconv::{AstConv, PathSeg}; use crate::middle::lang_items; -use crate::namespace::Namespace; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::middle::region; @@ -1972,6 +1971,7 @@ fn check_impl_items_against_trait<'tcx>( // Check existing impl methods to see if they are both present in trait // and compatible with trait signature for impl_item in impl_items() { + let namespace = impl_item.kind.namespace(); let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); let ty_trait_item = tcx .associated_items(impl_trait_ref.def_id) diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 2a0d19b69fd..ad0e462afc7 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -1,4 +1,3 @@ -use crate::namespace::Namespace; use rustc::ty::{AssocItem, TyCtxt}; use rustc_errors::struct_span_err; use rustc_hir as hir; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 0a1c61b8aea..c5f339d6b76 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -83,7 +83,6 @@ mod collect; mod constrained_generic_params; mod impl_wf_check; mod mem_categorization; -mod namespace; mod outlives; mod structured_errors; mod variance; diff --git a/src/librustc_typeck/namespace.rs b/src/librustc_typeck/namespace.rs deleted file mode 100644 index 2aa97aa7e6f..00000000000 --- a/src/librustc_typeck/namespace.rs +++ /dev/null @@ -1,27 +0,0 @@ -use rustc::ty; -use rustc_hir as hir; - -// Whether an item exists in the type or value namespace. -#[derive(Copy, Clone, PartialEq, Eq, Debug)] -pub enum Namespace { - Type, - Value, -} - -impl From for Namespace { - fn from(a_kind: ty::AssocKind) -> Self { - match a_kind { - ty::AssocKind::OpaqueTy | ty::AssocKind::Type => Namespace::Type, - ty::AssocKind::Const | ty::AssocKind::Method => Namespace::Value, - } - } -} - -impl<'a> From<&'a hir::ImplItemKind<'_>> for Namespace { - fn from(impl_kind: &'a hir::ImplItemKind<'_>) -> Self { - match *impl_kind { - hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => Namespace::Type, - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => Namespace::Value, - } - } -} From 7f3ec5e50ba17633b194835a48a1a1178c73396a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 17 Feb 2020 13:09:01 -0800 Subject: [PATCH 0344/1250] Make lookup of associated item by name O(log n) --- src/librustc/arena.rs | 1 + src/librustc/query/mod.rs | 2 +- src/librustc/traits/specialization_graph.rs | 6 +- src/librustc/ty/adjustment.rs | 2 +- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 82 ++++++++++++++++- src/librustc/ty/sty.rs | 6 +- src/librustc/ty/util.rs | 2 +- src/librustc_infer/traits/mod.rs | 2 +- src/librustc_infer/traits/object_safety.rs | 6 +- src/librustc_infer/traits/util.rs | 4 +- src/librustc_infer/traits/wf.rs | 7 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_mir_build/hair/cx/mod.rs | 22 ++--- src/librustc_passes/stability.rs | 4 +- src/librustc_save_analysis/lib.rs | 19 ++-- src/librustc_ty/ty.rs | 8 +- src/librustc_typeck/astconv.rs | 29 +++--- src/librustc_typeck/check/closure.rs | 6 +- src/librustc_typeck/check/demand.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/mod.rs | 20 +++-- .../coherence/inherent_impls_overlap.rs | 88 +++++++++---------- src/librustdoc/clean/blanket_impl.rs | 3 +- src/librustdoc/clean/inline.rs | 6 +- .../passes/collect_intra_doc_links.rs | 8 +- 28 files changed, 216 insertions(+), 135 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index f5c83fed1fc..ca55d410ceb 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -48,6 +48,7 @@ macro_rules! arena_types { [] item_local_set: rustc_hir::ItemLocalSet, [decode] mir_const_qualif: rustc_index::bit_set::BitSet, [] trait_impls_of: rustc::ty::trait_def::TraitImpls, + [] associated_items: rustc::ty::AssociatedItems, [] dropck_outlives: rustc::infer::canonical::Canonical<'tcx, rustc::infer::canonical::QueryResponse<'tcx, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 45ab3fc0b85..06e20d0a2ae 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -325,7 +325,7 @@ rustc_queries! { query associated_item(_: DefId) -> ty::AssocItem {} /// Collects the associated items defined on a trait or impl. - query associated_items(key: DefId) -> &'tcx [ty::AssocItem] { + query associated_items(key: DefId) -> &'tcx ty::AssociatedItems { desc { |tcx| "collecting associated items of {}", tcx.def_path_str(key) } } diff --git a/src/librustc/traits/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs index 36a84369d4a..ee813bf606e 100644 --- a/src/librustc/traits/specialization_graph.rs +++ b/src/librustc/traits/specialization_graph.rs @@ -81,8 +81,8 @@ impl<'tcx> Node { } /// Iterate over the items defined directly by the given (impl or trait) node. - pub fn items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ty::AssocItem] { - tcx.associated_items(self.def_id()) + pub fn items(&self, tcx: TyCtxt<'tcx>) -> impl 'tcx + Iterator { + tcx.associated_items(self.def_id()).in_definition_order() } /// Finds an associated item defined in this node. @@ -99,7 +99,7 @@ impl<'tcx> Node { use crate::ty::AssocKind::*; tcx.associated_items(self.def_id()) - .iter() + .filter_by_name_unhygienic(trait_item_name.name) .find(move |impl_item| { match (trait_item_kind, impl_item.kind) { | (Const, Const) diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs index f4006a1cd40..851bffc2065 100644 --- a/src/librustc/ty/adjustment.rs +++ b/src/librustc/ty/adjustment.rs @@ -122,7 +122,7 @@ impl<'tcx> OverloadedDeref<'tcx> { }; let method_def_id = tcx .associated_items(trait_def_id.unwrap()) - .iter() + .in_definition_order() .find(|m| m.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 332fd0bf46f..0ec30bc583c 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -337,7 +337,7 @@ impl<'tcx> Instance<'tcx> { let fn_once = tcx.lang_items().fn_once_trait().unwrap(); let call_once = tcx .associated_items(fn_once) - .iter() + .in_definition_order() .find(|it| it.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c70a296e34b..fa46f521ba5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -30,6 +30,7 @@ use rustc_attr as attr; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{self, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; @@ -264,6 +265,81 @@ impl AssocItem { } } +/// A list of `ty::AssocItem`s in definition order that allows for efficient lookup by name. +/// +/// When doing lookup by name, we try to postpone hygienic comparison for as long as possible since +/// it is relatively expensive. Instead, items are indexed by `Symbol` and hygienic comparison is +/// done only on items with the same name. +#[derive(Debug, Clone, PartialEq, HashStable)] +pub struct AssociatedItems { + items: SortedIndexMultiMap, +} + +impl AssociatedItems { + /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. + pub fn new(items_in_def_order: Vec) -> Self { + let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); + AssociatedItems { items } + } + + /// Returns a slice of associated items in the order they were defined. + /// + /// New code should avoid relying on definition order. If you need a particular associated item + /// for a known trait, make that trait a lang item instead of indexing this array. + pub fn in_definition_order(&self) -> impl '_ + Iterator { + self.items.iter().map(|(_, v)| v) + } + + /// Returns an iterator over all associated items with the given name, ignoring hygiene. + pub fn filter_by_name_unhygienic( + &self, + name: Symbol, + ) -> impl '_ + Iterator { + self.items.get_by_key(&name) + } + + /// Returns an iterator over all associated items with the given name. + /// + /// Multiple items may have the same name if they are in different `Namespace`s. For example, + /// an associated type can have the same name as a method. Use one of the `find_by_name_and_*` + /// methods below if you know which item you are looking for. + pub fn filter_by_name( + &'a self, + tcx: TyCtxt<'a>, + ident: Ident, + parent_def_id: DefId, + ) -> impl 'a + Iterator { + self.filter_by_name_unhygienic(ident.name) + .filter(move |item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + } + + /// Returns the associated item with the given name and `AssocKind`, if one exists. + pub fn find_by_name_and_kind( + &self, + tcx: TyCtxt<'_>, + ident: Ident, + kind: AssocKind, + parent_def_id: DefId, + ) -> Option<&ty::AssocItem> { + self.filter_by_name_unhygienic(ident.name) + .filter(|item| item.kind == kind) + .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + } + + /// Returns the associated item with the given name in the given `Namespace`, if one exists. + pub fn find_by_name_and_namespace( + &self, + tcx: TyCtxt<'_>, + ident: Ident, + ns: Namespace, + parent_def_id: DefId, + ) -> Option<&ty::AssocItem> { + self.filter_by_name_unhygienic(ident.name) + .filter(|item| item.kind.namespace() == ns) + .find(|item| tcx.hygienic_eq(ident, item.ident, parent_def_id)) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Copy, RustcEncodable, RustcDecodable, HashStable)] pub enum Visibility { /// Visible everywhere (including in other crates). @@ -2738,14 +2814,14 @@ impl<'tcx> TyCtxt<'tcx> { .for_each(|&body_id| f(self.hir().body_owner_def_id(body_id))); } - pub fn provided_trait_methods(self, id: DefId) -> impl Iterator { + pub fn provided_trait_methods(self, id: DefId) -> impl 'tcx + Iterator { self.associated_items(id) - .iter() + .in_definition_order() .filter(|item| item.kind == AssocKind::Method && item.defaultness.has_value()) } pub fn trait_relevant_for_never(self, did: DefId) -> bool { - self.associated_items(did).iter().any(|item| item.relevant_for_never()) + self.associated_items(did).in_definition_order().any(|item| item.relevant_for_never()) } pub fn opt_item_name(self, def_id: DefId) -> Option { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9cf61ebe88a..c3698f402a9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1066,11 +1066,7 @@ impl<'tcx> ProjectionTy<'tcx> { ) -> ProjectionTy<'tcx> { let item_def_id = tcx .associated_items(trait_ref.def_id) - .iter() - .find(|item| { - item.kind == ty::AssocKind::Type - && tcx.hygienic_eq(item_name, item.ident, trait_ref.def_id) - }) + .find_by_name_and_kind(tcx, item_name, ty::AssocKind::Type, trait_ref.def_id) .unwrap() .def_id; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index cb43f7475b8..eec6893d357 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -357,7 +357,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); self.for_each_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item) = self.associated_items(impl_did).first() { + if let Some(item) = self.associated_items(impl_did).in_definition_order().nth(0) { if validate(self, impl_did).is_ok() { dtor_did = Some(item.def_id); } diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 06c6d651813..b49f0062a9c 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -537,7 +537,7 @@ fn vtable_methods<'tcx>( tcx.arena.alloc_from_iter(supertraits(tcx, trait_ref).flat_map(move |trait_ref| { let trait_methods = tcx .associated_items(trait_ref.def_id()) - .iter() + .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Method); // Now list each method's DefId and InternalSubsts (for within its trait). diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index d36d66e4e25..93eeb42a594 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -213,7 +213,7 @@ fn object_safety_violations_for_trait( // Check methods for violations. let mut violations: Vec<_> = tcx .associated_items(trait_def_id) - .iter() + .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Method) .filter_map(|item| { object_safety_violation_for_method(tcx, trait_def_id, &item) @@ -289,7 +289,7 @@ fn object_safety_violations_for_trait( violations.extend( tcx.associated_items(trait_def_id) - .iter() + .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Const) .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)), ); @@ -646,7 +646,7 @@ fn object_ty_for_trait<'tcx>( let mut associated_types = traits::supertraits(tcx, ty::Binder::dummy(trait_ref)) .flat_map(|super_trait_ref| { tcx.associated_items(super_trait_ref.def_id()) - .iter() + .in_definition_order() .map(move |item| (super_trait_ref, item)) }) .filter(|(_, item)| item.kind == ty::AssocKind::Type) diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index c1612a3b9a7..1dca01b3468 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -586,7 +586,7 @@ pub fn count_own_vtable_entries(tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<' let mut entries = 0; // Count number of methods and add them to the total offset. // Skip over associated types and constants. - for trait_item in tcx.associated_items(trait_ref.def_id()) { + for trait_item in tcx.associated_items(trait_ref.def_id()).in_definition_order() { if trait_item.kind == ty::AssocKind::Method { entries += 1; } @@ -606,7 +606,7 @@ pub fn get_vtable_index_of_object_method( // add them to the total offset. // Skip over associated types and constants. let mut entries = object.vtable_base; - for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()) { + for trait_item in tcx.associated_items(object.upcast_trait_ref.def_id()).in_definition_order() { if trait_item.def_id == method_def_id { // The item with the ID we were given really ought to be a method. assert_eq!(trait_item.kind, ty::AssocKind::Method); diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs index 89a271d0111..993eb41b9b1 100644 --- a/src/librustc_infer/traits/wf.rs +++ b/src/librustc_infer/traits/wf.rs @@ -318,7 +318,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { }; if let Elaborate::All = elaborate { - let trait_assoc_items = tcx.associated_items(trait_ref.def_id); + // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator + // instead of a slice. + let trait_assoc_items: Vec<_> = + tcx.associated_items(trait_ref.def_id).in_definition_order().copied().collect(); let predicates = obligations.iter().map(|obligation| obligation.predicate).collect(); let implied_obligations = traits::elaborate_predicates(tcx, predicates); @@ -327,7 +330,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { extend_cause_with_original_assoc_item_obligation( &mut cause, &pred, - trait_assoc_items, + &*trait_assoc_items, ); traits::Obligation::new(cause, param_env, pred) }); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index bfd30ff5da5..1f7db2861a2 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -68,7 +68,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); let call_mut = tcx .associated_items(fn_mut) - .iter() + .in_definition_order() .find(|it| it.kind == ty::AssocKind::Method) .unwrap() .def_id; diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 091ae1bbb79..fab64e37cbc 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -539,7 +539,7 @@ where debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let drop_fn = tcx.associated_items(drop_trait)[0]; + let drop_fn = tcx.associated_items(drop_trait).in_definition_order().nth(0).unwrap(); let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs index ee62af7f851..f4f7ab4bba6 100644 --- a/src/librustc_mir_build/hair/cx/mod.rs +++ b/src/librustc_mir_build/hair/cx/mod.rs @@ -167,17 +167,19 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { params: &[GenericArg<'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) { - // The unhygienic comparison here is acceptable because this is only - // used on known traits. - 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 ty::Const::zero_sized(self.tcx, method_ty); - } - } - bug!("found no method `{}` in `{:?}`", method_name, trait_def_id); + // The unhygienic comparison here is acceptable because this is only + // used on known traits. + let item = self + .tcx + .associated_items(trait_def_id) + .filter_by_name_unhygienic(method_name) + .find(|item| item.kind == ty::AssocKind::Method) + .expect("trait method not found"); + + let method_ty = self.tcx.type_of(item.def_id); + let method_ty = method_ty.subst(self.tcx, substs); + ty::Const::zero_sized(self.tcx, method_ty) } crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec { diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 99f005c29e8..5c2abb1efa4 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -468,8 +468,8 @@ impl Visitor<'tcx> for Checker<'tcx> { let trait_item_def_id = self .tcx .associated_items(trait_did) - .iter() - .find(|item| item.ident.name == impl_item.ident.name) + .filter_by_name_unhygienic(impl_item.ident.name) + .next() .map(|item| item.def_id); if let Some(def_id) = trait_item_def_id { // Pass `None` to skip deprecation warnings. diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 6a34e47130f..6e7ecf92441 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -408,7 +408,6 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { qualname.push_str(&self.tcx.hir().hir_to_pretty_string(self_ty.hir_id)); let trait_id = self.tcx.trait_id_of_impl(impl_id); - let mut decl_id = None; let mut docs = String::new(); let mut attrs = vec![]; let hir_id = self.tcx.hir().node_to_hir_id(id); @@ -417,15 +416,18 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attrs = item.attrs.to_vec(); } + let mut decl_id = None; if let Some(def_id) = trait_id { // A method in a trait impl. qualname.push_str(" as "); qualname.push_str(&self.tcx.def_path_str(def_id)); - self.tcx + + decl_id = self + .tcx .associated_items(def_id) - .iter() - .find(|item| item.ident.name == ident.name) - .map(|item| decl_id = Some(item.def_id)); + .filter_by_name_unhygienic(ident.name) + .next() + .map(|item| item.def_id); } qualname.push_str(">"); @@ -716,12 +718,11 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { Res::Def(HirDefKind::Method, decl_id) => { let def_id = if decl_id.is_local() { let ti = self.tcx.associated_item(decl_id); + self.tcx .associated_items(ti.container.id()) - .iter() - .find(|item| { - item.ident.name == ti.ident.name && item.defaultness.has_value() - }) + .filter_by_name_unhygienic(ti.ident.name) + .find(|item| item.defaultness.has_value()) .map(|item| item.def_id) } else { None diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index f9b2ee3cb8e..916a819090c 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -210,10 +210,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } } -fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx [ty::AssocItem] { - tcx.arena.alloc_from_iter( - tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)), - ) +fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems { + let items = + tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)).collect(); + tcx.arena.alloc(ty::AssociatedItems::new(items)) } fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 635c3038e0a..572d3f3264f 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1108,10 +1108,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id: DefId, assoc_name: ast::Ident, ) -> bool { - self.tcx().associated_items(trait_def_id).iter().any(|item| { - item.kind == ty::AssocKind::Type - && self.tcx().hygienic_eq(assoc_name, item.ident, trait_def_id) - }) + self.tcx() + .associated_items(trait_def_id) + .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, trait_def_id) + .is_some() } // Returns `true` if a bounds list includes `?Sized`. @@ -1344,9 +1344,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); + + // FIXME(ecstaticmorse): Can this use `find_by_name_and_kind` instead? let assoc_ty = tcx .associated_items(candidate.def_id()) - .iter() + .filter_by_name_unhygienic(assoc_ident.name) .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident) .expect("missing associated type"); @@ -1512,7 +1514,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ty::Predicate::Trait(pred, _) => { associated_types.entry(span).or_default().extend( tcx.associated_items(pred.def_id()) - .iter() + .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .map(|item| item.def_id), ); @@ -1967,14 +1969,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut where_bounds = vec![]; for bound in bounds { + let bound_id = bound.def_id(); let bound_span = self .tcx() - .associated_items(bound.def_id()) - .iter() - .find(|item| { - item.kind == ty::AssocKind::Type - && self.tcx().hygienic_eq(assoc_name, item.ident, bound.def_id()) - }) + .associated_items(bound_id) + .find_by_name_and_kind(self.tcx(), assoc_name, ty::AssocKind::Type, bound_id) .and_then(|item| self.tcx().hir().span_if_local(item.def_id)); if let Some(bound_span) = bound_span { @@ -2052,7 +2051,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); let all_candidate_names: Vec<_> = all_candidates() - .map(|r| self.tcx().associated_items(r.def_id())) + .map(|r| self.tcx().associated_items(r.def_id()).in_definition_order()) .flatten() .filter_map( |item| if item.kind == ty::AssocKind::Type { Some(item.ident.name) } else { None }, @@ -2198,9 +2197,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let trait_did = bound.def_id(); let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id); + + // FIXME(ecstaticmorse): Can this use `find_by_name_and_namespace` instead? let item = tcx .associated_items(trait_did) - .iter() + .in_definition_order() .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident) .expect("missing associated type"); diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index e17c65faf1f..816de5dadbc 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -248,7 +248,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if is_gen { // Check that we deduce the signature from the `<_ as std::ops::Generator>::Return` // associated item and not yield. - let return_assoc_item = self.tcx.associated_items(gen_trait)[1].def_id; + let return_assoc_item = + self.tcx.associated_items(gen_trait).in_definition_order().nth(1).unwrap().def_id; if return_assoc_item != projection.projection_def_id() { debug!("deduce_sig_from_projection: not return assoc item of generator"); return None; @@ -673,7 +674,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associted item, `Output`, // so check that this is what we see. - let output_assoc_item = self.tcx.associated_items(future_trait)[0].def_id; + let output_assoc_item = + self.tcx.associated_items(future_trait).in_definition_order().nth(0).unwrap().def_id; if output_assoc_item != predicate.projection_ty.item_def_id { span_bug!( cause_span, diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index bf74ab696d6..63ebf612964 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -539,7 +539,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let item_def_id = self .tcx .associated_items(deref_trait) - .iter() + .in_definition_order() .find(|item| item.kind == ty::AssocKind::Type) .unwrap() .def_id; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 84e00244942..de824648a25 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -483,11 +483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option { self.tcx .associated_items(def_id) - .iter() - .find(|item| { - Namespace::from(item.kind) == ns - && self.tcx.hygienic_eq(item_name, item.ident, def_id) - }) + .find_by_name_and_namespace(self.tcx, item_name, ns, def_id) .copied() } } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 5ed39f04b07..ea90aef4868 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1696,7 +1696,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let max_dist = max(name.as_str().len(), 3) / 3; self.tcx .associated_items(def_id) - .iter() + .in_definition_order() .filter(|x| { let dist = lev_distance(&*name.as_str(), &x.ident.as_str()); x.kind.namespace() == Namespace::ValueNS && dist > 0 && dist <= max_dist @@ -1709,7 +1709,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { .map_or(Vec::new(), |x| vec![x]) } } else { - self.tcx.associated_items(def_id).to_vec() + self.tcx.associated_items(def_id).in_definition_order().copied().collect() } } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d6acd8dd894..2f6d8b644c0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1975,16 +1975,12 @@ fn check_impl_items_against_trait<'tcx>( let ty_impl_item = tcx.associated_item(tcx.hir().local_def_id(impl_item.hir_id)); let ty_trait_item = tcx .associated_items(impl_trait_ref.def_id) - .iter() - .find(|ac| { - Namespace::from(&impl_item.kind) == Namespace::from(ac.kind) - && tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id) - }) + .find_by_name_and_namespace(tcx, ty_impl_item.ident, namespace, impl_trait_ref.def_id) .or_else(|| { // Not compatible, but needed for the error message tcx.associated_items(impl_trait_ref.def_id) - .iter() - .find(|ac| tcx.hygienic_eq(ty_impl_item.ident, ac.ident, impl_trait_ref.def_id)) + .filter_by_name(tcx, ty_impl_item.ident, impl_trait_ref.def_id) + .next() }); // Check that impl definition matches trait definition @@ -2088,7 +2084,7 @@ fn check_impl_items_against_trait<'tcx>( let mut missing_items = Vec::new(); let mut invalidated_items = Vec::new(); let associated_type_overridden = overridden_associated_type.is_some(); - for trait_item in tcx.associated_items(impl_trait_ref.def_id) { + for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { let is_implemented = trait_def .ancestors(tcx, impl_id) .leaf_def(tcx, trait_item.ident, trait_item.kind) @@ -5224,7 +5220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check for `Future` implementations by constructing a predicate to // prove: `::Output == U` let future_trait = self.tcx.lang_items().future_trait().unwrap(); - let item_def_id = self.tcx.associated_items(future_trait)[0].def_id; + let item_def_id = self + .tcx + .associated_items(future_trait) + .in_definition_order() + .nth(0) + .unwrap() + .def_id; let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate { // `::Output` diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index ad0e462afc7..fcded27463e 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -1,4 +1,4 @@ -use rustc::ty::{AssocItem, TyCtxt}; +use rustc::ty::TyCtxt; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; @@ -22,18 +22,18 @@ impl InherentOverlapChecker<'tcx> { let impl_items1 = self.tcx.associated_items(impl1); let impl_items2 = self.tcx.associated_items(impl2); - for item1 in &impl_items1[..] { - for item2 in &impl_items2[..] { - // Avoid costly `.modern()` calls as much as possible by doing them as late as we - // can. Compare raw symbols first. - if item1.ident.name == item2.ident.name - && Namespace::from(item1.kind) == Namespace::from(item2.kind) - { + for item1 in impl_items1.in_definition_order() { + let collision = impl_items2 + .filter_by_name_unhygienic(item1.ident.name) + .find(|item2| { // Symbols and namespace match, compare hygienically. - if item1.ident.modern() == item2.ident.modern() { - return true; - } - } + item1.kind.namespace() == item2.kind.namespace() + && item1.ident.modern() == item2.ident.modern() + }) + .is_some(); + + if collision { + return true; } } @@ -46,43 +46,43 @@ impl InherentOverlapChecker<'tcx> { impl2: DefId, overlap: traits::OverlapResult<'_>, ) { - let name_and_namespace = - |assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind)); - let impl_items1 = self.tcx.associated_items(impl1); let impl_items2 = self.tcx.associated_items(impl2); - for item1 in &impl_items1[..] { - let (name, namespace) = name_and_namespace(item1); - - for item2 in &impl_items2[..] { - if (name, namespace) == name_and_namespace(item2) { - let mut err = struct_span_err!( - self.tcx.sess, - self.tcx.span_of_impl(item1.def_id).unwrap(), - E0592, - "duplicate definitions with name `{}`", - name - ); - err.span_label( - self.tcx.span_of_impl(item1.def_id).unwrap(), - format!("duplicate definitions for `{}`", name), - ); - err.span_label( - self.tcx.span_of_impl(item2.def_id).unwrap(), - format!("other definition for `{}`", name), - ); - - for cause in &overlap.intercrate_ambiguity_causes { - cause.add_intercrate_ambiguity_hint(&mut err); - } - - if overlap.involves_placeholder { - traits::add_placeholder_note(&mut err); - } + for item1 in impl_items1.in_definition_order() { + let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| { + // Symbols and namespace match, compare hygienically. + item1.kind.namespace() == item2.kind.namespace() + && item1.ident.modern() == item2.ident.modern() + }); + + if let Some(item2) = collision { + let name = item1.ident.modern(); + let mut err = struct_span_err!( + self.tcx.sess, + self.tcx.span_of_impl(item1.def_id).unwrap(), + E0592, + "duplicate definitions with name `{}`", + name + ); + err.span_label( + self.tcx.span_of_impl(item1.def_id).unwrap(), + format!("duplicate definitions for `{}`", name), + ); + err.span_label( + self.tcx.span_of_impl(item2.def_id).unwrap(), + format!("other definition for `{}`", name), + ); + + for cause in &overlap.intercrate_ambiguity_causes { + cause.add_intercrate_ambiguity_hint(&mut err); + } - err.emit(); + if overlap.involves_placeholder { + traits::add_placeholder_note(&mut err); } + + err.emit(); } } } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index f7968bf7722..4a1e2570d06 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -114,8 +114,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> { .cx .tcx .associated_items(impl_def_id) - .iter() - .copied() + .in_definition_order() .collect::>() .clean(self.cx), polarity: None, diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 90ce8802f65..78222d21b93 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -190,8 +190,10 @@ pub fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKind) } pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::Trait { + let trait_items = + cx.tcx.associated_items(did).in_definition_order().map(|item| item.clean(cx)).collect(); + let auto_trait = cx.tcx.trait_def(did).has_auto_impl; - let trait_items = cx.tcx.associated_items(did).iter().map(|item| item.clean(cx)).collect(); let predicates = cx.tcx.predicates_of(did); let generics = (cx.tcx.generics_of(did), predicates).clean(cx); let generics = filter_non_trait_generics(did, generics); @@ -376,7 +378,7 @@ pub fn build_impl( } else { ( tcx.associated_items(did) - .iter() + .in_definition_order() .filter_map(|item| { if associated_trait.is_some() || item.vis == ty::Visibility::Public { Some(item.clean(cx)) diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 79bcfe7aee7..0b27e5cf806 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .tcx .inherent_impls(did) .iter() - .flat_map(|imp| cx.tcx.associated_items(*imp)) + .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order()) .any(|item| item.ident.name == variant_name) { return Err(ErrorKind::ResolutionFailure); @@ -206,8 +206,8 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { return cx .tcx .associated_items(did) - .iter() - .find(|item| item.ident.name == item_name) + .filter_by_name_unhygienic(item_name) + .next() .and_then(|item| match item.kind { ty::AssocKind::Method => Some("method"), _ => None, @@ -234,7 +234,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .tcx .inherent_impls(did) .iter() - .flat_map(|imp| cx.tcx.associated_items(*imp)) + .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order()) .find(|item| item.ident.name == item_name); if let Some(item) = item { let out = match item.kind { From 186cbfad8982cf0f40a311d0e76563662095ed36 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Mon, 17 Feb 2020 13:35:49 -0800 Subject: [PATCH 0345/1250] Replace FIXME with explanation --- src/librustc_typeck/astconv.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 572d3f3264f..88e0f8b30d9 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1345,7 +1345,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - // FIXME(ecstaticmorse): Can this use `find_by_name_and_kind` instead? + // We have already adjusted the item name above, so compare with `ident.modern()` instead + // of calling `filter_by_name_and_kind`. let assoc_ty = tcx .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) @@ -2198,7 +2199,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id); - // FIXME(ecstaticmorse): Can this use `find_by_name_and_namespace` instead? + // We have already adjusted the item name above, so compare with `ident.modern()` instead + // of calling `filter_by_name_and_kind`. let item = tcx .associated_items(trait_did) .in_definition_order() From 88d14bfbc986802601d2414ea5d6322e0056917b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 19 Feb 2020 20:12:01 +0100 Subject: [PATCH 0346/1250] fix 32bit-only test --- src/test/ui/huge-array-simple-32.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/huge-array-simple-32.rs b/src/test/ui/huge-array-simple-32.rs index 3e574dfa07b..2290e3d5e76 100644 --- a/src/test/ui/huge-array-simple-32.rs +++ b/src/test/ui/huge-array-simple-32.rs @@ -4,7 +4,7 @@ // FIXME https://github.com/rust-lang/rust/issues/59774 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" // normalize-stderr-test "note:.*RUST_BACKTRACE=1.*\n" -> "" -#![allow(exceeding_bitshifts)] +#![allow(arithmetic_overflow)] fn main() { let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture From a0212ba40fdeb07626449b5790537aca542b51d2 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 19 Feb 2020 12:55:59 -0800 Subject: [PATCH 0347/1250] Construct `AssociatedItems` from an iterator instead of a `Vec` --- src/librustc/ty/mod.rs | 2 +- src/librustc_ty/ty.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index fa46f521ba5..77ac319547b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -277,7 +277,7 @@ pub struct AssociatedItems { impl AssociatedItems { /// Constructs an `AssociatedItems` map from a series of `ty::AssocItem`s in definition order. - pub fn new(items_in_def_order: Vec) -> Self { + pub fn new(items_in_def_order: impl IntoIterator) -> Self { let items = items_in_def_order.into_iter().map(|item| (item.ident.name, item)).collect(); AssociatedItems { items } } diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 916a819090c..d466bbcca79 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -211,8 +211,7 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] { } fn associated_items<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::AssociatedItems { - let items = - tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)).collect(); + let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did)); tcx.arena.alloc(ty::AssociatedItems::new(items)) } From 883e69db950522afb73fc9ad8ea122bacdd42ee4 Mon Sep 17 00:00:00 2001 From: Peter Todd Date: Wed, 19 Feb 2020 16:37:58 -0500 Subject: [PATCH 0348/1250] Change FromStr for String to use Infallible directly Fixes the confusing documentation on `ParseError` by making it irrelevant. --- src/liballoc/string.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 3cb1f259a0b..f5afea15d65 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2106,18 +2106,11 @@ impl ops::DerefMut for String { } } -/// An error when parsing a `String`. +/// A type alias for [`Infallible`]. /// -/// This `enum` is slightly awkward: it will never actually exist. This error is -/// part of the type signature of the implementation of [`FromStr`] on -/// [`String`]. The return type of [`from_str`], requires that an error be -/// defined, but, given that a [`String`] can always be made into a new -/// [`String`] without error, this type will never actually be returned. As -/// such, it is only here to satisfy said signature, and is useless otherwise. +/// This alias exists for backwards compatibility, and may be eventually deprecated. /// -/// [`FromStr`]: ../../std/str/trait.FromStr.html -/// [`String`]: struct.String.html -/// [`from_str`]: ../../std/str/trait.FromStr.html#tymethod.from_str +/// [`Infallible`]: ../../core/convert/enum.Infallible.html #[stable(feature = "str_parse_error", since = "1.5.0")] pub type ParseError = core::convert::Infallible; @@ -2125,7 +2118,7 @@ pub type ParseError = core::convert::Infallible; impl FromStr for String { type Err = core::convert::Infallible; #[inline] - fn from_str(s: &str) -> Result { + fn from_str(s: &str) -> Result { Ok(String::from(s)) } } From f77d1076ab63dc68c1bce2b8cc08e05b0ea885b0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Feb 2020 21:12:46 +0100 Subject: [PATCH 0349/1250] Match MIR statements exhaustively --- src/librustc_mir/dataflow/impls/storage_liveness.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 7508d71945e..2a7c6c2ffc1 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -129,7 +129,14 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { sets.gen(place.local); } } - _ => (), + + // Nothing to do for these. Match exhaustively so this fails to compile when new + // variants are added. + StatementKind::AscribeUserType(..) + | StatementKind::FakeRead(..) + | StatementKind::Nop + | StatementKind::Retag(..) + | StatementKind::StorageLive(..) => {} } } From 3723fc1e45381ed8957b60967c8f7af5ab93e796 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Feb 2020 21:36:50 +0100 Subject: [PATCH 0350/1250] Use match ergonomics to simplify match --- src/librustc_mir/dataflow/impls/storage_liveness.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 2a7c6c2ffc1..5781b3982b1 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -118,13 +118,13 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc); // If a place is assigned to in a statement, it needs storage for that statement. - match stmt.kind { - StatementKind::StorageDead(l) => sets.kill(l), - StatementKind::Assign(box (ref place, _)) - | StatementKind::SetDiscriminant { box ref place, .. } => { + match &stmt.kind { + StatementKind::StorageDead(l) => sets.kill(*l), + StatementKind::Assign(box (place, _)) + | StatementKind::SetDiscriminant { box place, .. } => { sets.gen(place.local); } - StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => { + StatementKind::InlineAsm(box InlineAsm { outputs, .. }) => { for place in &**outputs { sets.gen(place.local); } From d4c6dfe6d6028dacc0dc59f509a823aad2d2cdf6 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Feb 2020 22:18:26 +0100 Subject: [PATCH 0351/1250] Handle resume args in `RequiresStorage` analysis --- .../dataflow/impls/storage_liveness.rs | 57 +++++++++++++++---- 1 file changed, 46 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 5781b3982b1..659b66823c2 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -152,23 +152,58 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { // If a place is borrowed in a terminator, it needs storage for that terminator. self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc); - if let TerminatorKind::Call { destination: Some((place, _)), .. } = terminator.kind { - sets.gen(place.local); + match &terminator.kind { + TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } + | TerminatorKind::Yield { resume_arg: Place { local, .. }, .. } => { + sets.gen(*local); + } + + // Nothing to do for these. Match exhaustively so this fails to compile when new + // variants are added. + TerminatorKind::Call { destination: None, .. } + | TerminatorKind::Abort + | TerminatorKind::Assert { .. } + | TerminatorKind::Drop { .. } + | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Return + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Unreachable => {} } } fn terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { - // For call terminators the destination requires storage for the call - // and after the call returns successfully, but not after a panic. - // Since `propagate_call_unwind` doesn't exist, we have to kill the - // destination here, and then gen it again in `propagate_call_return`. - if let TerminatorKind::Call { destination: Some((ref place, _)), .. } = - self.body[loc.block].terminator().kind - { - if let Some(local) = place.as_local() { - sets.kill(local); + match &self.body[loc.block].terminator().kind { + // For call terminators the destination requires storage for the call + // and after the call returns successfully, but not after a panic. + // Since `propagate_call_unwind` doesn't exist, we have to kill the + // destination here, and then gen it again in `propagate_call_return`. + TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } => { + sets.kill(*local); } + + // Nothing to do for these. Match exhaustively so this fails to compile when new + // variants are added. + TerminatorKind::Call { destination: None, .. } + | TerminatorKind::Yield { .. } + | TerminatorKind::Abort + | TerminatorKind::Assert { .. } + | TerminatorKind::Drop { .. } + | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } + | TerminatorKind::GeneratorDrop + | TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Return + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Unreachable => {} } + self.check_for_move(sets, loc); } From 71c4f76153590fc1744c7f73b94d2d39ae2e2f23 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 17 Feb 2020 21:20:48 +0100 Subject: [PATCH 0352/1250] Reorder yield visitation order to match call --- src/librustc/mir/visit.rs | 2 +- src/librustc_mir/dataflow/move_paths/builder.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 8330bbe0834..409c981801b 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -519,12 +519,12 @@ macro_rules! make_mir_visitor { resume_arg, drop: _, } => { + self.visit_operand(value, source_location); self.visit_place( resume_arg, PlaceContext::MutatingUse(MutatingUseContext::Store), source_location, ); - self.visit_operand(value, source_location); } } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 6f8caca5e21..57aa5de7f7a 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -381,9 +381,9 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } TerminatorKind::Yield { ref value, resume_arg: ref place, .. } => { + self.gather_operand(value); self.create_move_path(place); self.gather_init(place.as_ref(), InitKind::Deep); - self.gather_operand(value); } TerminatorKind::Drop { ref location, target: _, unwind: _ } => { From 689615724535d00c093c6c5dff0accaf6e38d9bc Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 19 Feb 2020 23:38:31 +0100 Subject: [PATCH 0353/1250] Remap the resume place if necessary --- src/librustc_mir/transform/generator.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index b3dc87d1a16..a94f03301f3 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -325,6 +325,15 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> { // Yield let state = 3 + self.suspension_points.len(); + // The resume arg target location might itself be remapped if its base local is + // live across a yield. + let resume_arg = + if let Some(&(ty, variant, idx)) = self.remap.get(&resume_arg.local) { + self.make_field(variant, idx, ty) + } else { + resume_arg + }; + self.suspension_points.push(SuspensionPoint { state, resume, From 66b1ae40606ae0c07645ebc8f97e537d8d30ef73 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 19 Feb 2020 23:39:00 +0100 Subject: [PATCH 0354/1250] Add more comments to `SuspensionPoint` --- src/librustc_mir/transform/generator.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index a94f03301f3..3621ca63209 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -186,18 +186,24 @@ fn self_arg() -> Local { Local::new(1) } -/// Generator have not been resumed yet +/// Generator has not been resumed yet. const UNRESUMED: usize = GeneratorSubsts::UNRESUMED; -/// Generator has returned / is completed +/// Generator has returned / is completed. const RETURNED: usize = GeneratorSubsts::RETURNED; -/// Generator has been poisoned +/// Generator has panicked and is poisoned. const POISONED: usize = GeneratorSubsts::POISONED; +/// A `yield` point in the generator. struct SuspensionPoint<'tcx> { + /// State discriminant used when suspending or resuming at this point. state: usize, + /// The block to jump to after resumption. resume: BasicBlock, + /// Where to move the resume argument after resumption. resume_arg: Place<'tcx>, + /// Which block to jump to if the generator is dropped in this state. drop: Option, + /// Set of locals that have live storage while at this suspension point. storage_liveness: liveness::LiveVarSet, } From fc2702c96c0db560f55683e4cd33075c054ed062 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 19 Feb 2020 23:44:53 +0100 Subject: [PATCH 0355/1250] Add regression test --- src/test/ui/generator/issue-69039.rs | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/ui/generator/issue-69039.rs diff --git a/src/test/ui/generator/issue-69039.rs b/src/test/ui/generator/issue-69039.rs new file mode 100644 index 00000000000..60004f3b0ae --- /dev/null +++ b/src/test/ui/generator/issue-69039.rs @@ -0,0 +1,30 @@ +// run-pass + +#![feature(generators, generator_trait)] + +use std::ops::{Generator, GeneratorState}; + +fn my_scenario() -> impl Generator { + |_arg: String| { + let my_name = yield "What is your name?"; + let my_mood = yield "How are you feeling?"; + format!("{} is {}", my_name.trim(), my_mood.trim()) + } +} + +fn main() { + let mut my_session = Box::pin(my_scenario()); + + assert_eq!( + my_session.as_mut().resume("_arg".to_string()), + GeneratorState::Yielded("What is your name?") + ); + assert_eq!( + my_session.as_mut().resume("Your Name".to_string()), + GeneratorState::Yielded("How are you feeling?") + ); + assert_eq!( + my_session.as_mut().resume("Sensory Organs".to_string()), + GeneratorState::Complete("Your Name is Sensory Organs".to_string()) + ); +} From 9f3bc82fe40fd38fadfd24b7968548929abc9d4c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 19 Feb 2020 07:59:21 -0500 Subject: [PATCH 0356/1250] Check `RUSTC_CTFE_BACKTRACE` much less by generating fewer errors Before this change, `get_size_and_align()` calls `get_fn_alloc()` *a lot* in CTFE heavy code. This previously returned an `Error` which would check if `RUSTC_CTFE_BACKTRACE` was set on construction. Doing this turned out to be a performance hotspot as @nnethercote discovered in #68792. This is an alternate take on that PR which resolves the performance issue by generating *many* fewer errors. Previously, `ctfe-stress-4` would generate over 5,000,000 errors each of which would check for the presence of the environment variable. With these changes, that number is reduced to 30. --- src/librustc_mir/interpret/memory.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0bcdf9ae3c1..1df389d9c8b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -560,7 +560,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) - if let Ok(_) = self.get_fn_alloc(id) { + if let Some(_) = self.get_fn_alloc(id) { return if let AllocCheck::Dereferenceable = liveness { // The caller requested no function pointers. throw_unsup!(DerefFunctionPointer) @@ -602,14 +602,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } - fn get_fn_alloc(&self, id: AllocId) -> InterpResult<'tcx, FnVal<'tcx, M::ExtraFnVal>> { + fn get_fn_alloc(&self, id: AllocId) -> Option> { trace!("reading fn ptr: {}", id); if let Some(extra) = self.extra_fn_ptr_map.get(&id) { - Ok(FnVal::Other(*extra)) + Some(FnVal::Other(*extra)) } else { match self.tcx.alloc_map.lock().get(id) { - Some(GlobalAlloc::Function(instance)) => Ok(FnVal::Instance(instance)), - _ => throw_unsup!(ExecuteMemory), + Some(GlobalAlloc::Function(instance)) => Some(FnVal::Instance(instance)), + _ => None, } } } @@ -622,7 +622,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if ptr.offset.bytes() != 0 { throw_unsup!(InvalidFunctionPointer) } - self.get_fn_alloc(ptr.alloc_id) + self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { From c816430f9901b93aa7895a789685f012d7043697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 19 Feb 2020 18:04:03 -0800 Subject: [PATCH 0357/1250] Tweak binding lifetime suggestion text We already have a structured suggestion, but the wording made it seem like that wasn't the case. Fix #65286. r? @varkor --- .../infer/error_reporting/mod.rs | 22 ++++++++++--------- .../builtin-superkinds-self-type.stderr | 2 +- ...-infer_static_outlives_requirements.stderr | 2 +- .../must_outlive_least_region_or_bound.stderr | 2 +- .../type_parameters_captured.stderr | 2 +- .../lifetime-doesnt-live-long-enough.stderr | 10 ++++----- .../regions-close-object-into-object-5.stderr | 14 ++++++------ ...regions-close-over-type-parameter-1.stderr | 8 +++---- .../regions-close-param-into-object.stderr | 8 +++---- .../ui/regions/regions-enum-not-wf.stderr | 8 +++---- ...ons-implied-bounds-projection-gap-1.stderr | 2 +- .../regions-infer-bound-from-trait.stderr | 4 ++-- .../dont-infer-static.stderr | 2 +- .../regions-enum-not-wf.stderr | 8 +++---- .../regions-struct-not-wf.stderr | 4 ++-- .../suggest-impl-trait-lifetime.fixed | 2 +- .../suggest-impl-trait-lifetime.rs | 2 +- .../suggest-impl-trait-lifetime.stderr | 7 +++--- ...eric_type_does_not_live_long_enough.stderr | 2 +- .../wf/wf-impl-associated-type-region.stderr | 2 +- src/test/ui/wf/wf-in-fn-type-static.stderr | 4 ++-- src/test/ui/wf/wf-in-obj-type-static.stderr | 2 +- .../wf/wf-outlives-ty-in-fn-or-trait.stderr | 4 ++-- 23 files changed, 62 insertions(+), 61 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 77119b8618f..1ed890962da 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1781,14 +1781,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { bound_kind: GenericKind<'tcx>, sub: S, ) { - let consider = format!( - "consider adding an explicit lifetime bound {}", - if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) { - format!(" `{}` to `{}`...", sub, bound_kind) - } else { - format!("`{}: {}`...", bound_kind, sub) - }, - ); + let msg = "consider adding an explicit lifetime bound"; if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span { let suggestion = if is_impl_trait { format!("{} + {}", bound_kind, sub) @@ -1796,13 +1789,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let tail = if has_lifetimes { " + " } else { "" }; format!("{}: {}{}", bound_kind, sub, tail) }; - err.span_suggestion_short( + err.span_suggestion( sp, - &consider, + &format!("{}...", msg), suggestion, Applicability::MaybeIncorrect, // Issue #41966 ); } else { + let consider = format!( + "{} {}...", + msg, + if type_param_span.map(|(_, _, is_impl_trait)| is_impl_trait).unwrap_or(false) { + format!(" `{}` to `{}`", sub, bound_kind) + } else { + format!("`{}: {}`", bound_kind, sub) + }, + ); err.help(&consider); } } diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr index 2fdb3836dd9..999a5839ba6 100644 --- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr +++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr @@ -4,7 +4,7 @@ error[E0310]: the parameter type `T` may not live long enough LL | impl Foo for T { } | -- ^^^ | | - | help: consider adding an explicit lifetime bound `T: 'static`... + | help: consider adding an explicit lifetime bound...: `T: 'static +` | note: ...so that the type `T` will meet its required lifetime bounds --> $DIR/builtin-superkinds-self-type.rs:10:16 diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr index 689a3757343..fbc4e8abc42 100644 --- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr +++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5 | LL | struct Foo { - | - help: consider adding an explicit lifetime bound `U: 'static`... + | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar | ^^^^^^^^^^^ | diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr index 7f92e709af5..cffa5ee8f14 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr @@ -67,7 +67,7 @@ error[E0310]: the parameter type `T` may not live long enough LL | fn ty_param_wont_outlive_static(x: T) -> impl Debug + 'static { | -- ^^^^^^^^^^^^^^^^^^^^ | | - | help: consider adding an explicit lifetime bound `T: 'static`... + | help: consider adding an explicit lifetime bound...: `T: 'static +` | note: ...so that the type `T` will meet its required lifetime bounds --> $DIR/must_outlive_least_region_or_bound.rs:22:51 diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr index 708b479ab17..34f0f7f1d73 100644 --- a/src/test/ui/impl-trait/type_parameters_captured.stderr +++ b/src/test/ui/impl-trait/type_parameters_captured.stderr @@ -4,7 +4,7 @@ error[E0310]: the parameter type `T` may not live long enough LL | fn foo(x: T) -> impl Any + 'static { | - ^^^^^^^^^^^^^^^^^^ | | - | help: consider adding an explicit lifetime bound `T: 'static`... + | help: consider adding an explicit lifetime bound...: `T: 'static` | note: ...so that the type `T` will meet its required lifetime bounds --> $DIR/type_parameters_captured.rs:7:20 diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr index 4e50064efb4..e60c461743c 100644 --- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr +++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5 | LL | struct Foo { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | foo: &'static T | ^^^^^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19 | LL | trait X: Sized { - | - help: consider adding an explicit lifetime bound `K: 'a`... + | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn foo<'a, L: X<&'a Nested>>(); | ^^^^^^^^^^^^^^^^ | @@ -45,7 +45,7 @@ error[E0309]: the parameter type `L` may not live long enough LL | fn baz<'a, L, M: X<&'a Nested>>() { | - ^^^^^^^^^^^^^^^^ | | - | help: consider adding an explicit lifetime bound `L: 'a`... + | help: consider adding an explicit lifetime bound...: `L: 'a` | note: ...so that the reference type `&'a Nested` does not outlive the data it points at --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22 @@ -57,7 +57,7 @@ error[E0309]: the parameter type `K` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33 | LL | impl Nested { - | - help: consider adding an explicit lifetime bound `K: 'a`... + | - help: consider adding an explicit lifetime bound...: `K: 'a` LL | fn generic_in_parent<'a, L: X<&'a Nested>>() { | ^^^^^^^^^^^^^^^^ | @@ -71,7 +71,7 @@ error[E0309]: the parameter type `M` may not live long enough --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 | LL | fn generic_in_child<'a, 'b, L: X<&'a Nested>, M: 'b>() { - | ^^^^^^^^^^^^^^^^ -- help: consider adding an explicit lifetime bound `M: 'a`... + | ^^^^^^^^^^^^^^^^ -- help: consider adding an explicit lifetime bound...: `M: 'a +` | note: ...so that the reference type `&'a Nested` does not outlive the data it points at --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36 diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr index 7c530cec7c3..14727000b2c 100644 --- a/src/test/ui/regions/regions-close-object-into-object-5.stderr +++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^^^^^^^^ @@ -17,7 +17,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:5 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^ @@ -47,7 +47,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:9 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^^^^ @@ -62,7 +62,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^ @@ -77,7 +77,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^ @@ -92,7 +92,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-object-into-object-5.rs:17:11 | LL | fn f<'a, T, U>(v: Box+'static>) -> Box { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // oh dear! LL | box B(&*v) as Box | ^^^ diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr index 81534b7b770..ed9a604e717 100644 --- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr +++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:10:5 | LL | fn make_object1(v: A) -> Box { - | -- help: consider adding an explicit lifetime bound `A: 'static`... + | -- help: consider adding an explicit lifetime bound...: `A: 'static +` LL | box v as Box | ^^^^^ | @@ -16,7 +16,7 @@ error[E0310]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:10:5 | LL | fn make_object1(v: A) -> Box { - | -- help: consider adding an explicit lifetime bound `A: 'static`... + | -- help: consider adding an explicit lifetime bound...: `A: 'static +` LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -30,7 +30,7 @@ error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:20:5 | LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box { - | -- help: consider adding an explicit lifetime bound `A: 'b`... + | -- help: consider adding an explicit lifetime bound...: `A: 'b +` LL | box v as Box | ^^^^^ | @@ -44,7 +44,7 @@ error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-close-over-type-parameter-1.rs:20:5 | LL | fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box { - | -- help: consider adding an explicit lifetime bound `A: 'b`... + | -- help: consider adding an explicit lifetime bound...: `A: 'b +` LL | box v as Box | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr index 7f2c646c121..3b1a89d9ced 100644 --- a/src/test/ui/regions/regions-close-param-into-object.stderr +++ b/src/test/ui/regions/regions-close-param-into-object.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:6:5 | LL | fn p1(v: T) -> Box - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) | ^^^^^^^^^^^ @@ -17,7 +17,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:12:5 | LL | fn p2(v: Box) -> Box - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` ... LL | Box::new(v) | ^^^^^^^^^^^ @@ -32,7 +32,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:18:5 | LL | fn p3<'a,T>(v: T) -> Box - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) | ^^^^^^^^^^^ @@ -47,7 +47,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-close-param-into-object.rs:24:5 | LL | fn p4<'a,T>(v: Box) -> Box - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` ... LL | Box::new(v) | ^^^^^^^^^^^ diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr index 87014085667..297fcb088d2 100644 --- a/src/test/ui/regions/regions-enum-not-wf.stderr +++ b/src/test/ui/regions/regions-enum-not-wf.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:18:18 | LL | enum Ref1<'a, T> { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) | ^^^^^^^^^^^^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 | LL | enum Ref2<'a, T> { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 | LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound `T: 'b`... + | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` | _| | | LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) @@ -52,7 +52,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 | LL | enum RefDouble<'a, 'b, T> { - | - help: consider adding an explicit lifetime bound `T: 'b`... + | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr index 7fbc1622c3a..2f1a4cea8e9 100644 --- a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr +++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10 | LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo) - | -- help: consider adding an explicit lifetime bound `T: 'x`... + | -- help: consider adding an explicit lifetime bound...: `T: 'x +` LL | { LL | wf::<&'x T>(); | ^^^^^ diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr index 382d932e81a..a5a0ff52fac 100644 --- a/src/test/ui/regions/regions-infer-bound-from-trait.stderr +++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:33:5 | LL | fn bar1<'a,A>(x: Inv<'a>, a: A) { - | - help: consider adding an explicit lifetime bound `A: 'a`... + | - help: consider adding an explicit lifetime bound...: `A: 'a` LL | check_bound(x, a) | ^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `A` may not live long enough --> $DIR/regions-infer-bound-from-trait.rs:37:5 | LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) { - | -- help: consider adding an explicit lifetime bound `A: 'a`... + | -- help: consider adding an explicit lifetime bound...: `A: 'a +` LL | check_bound(x, a) | ^^^^^^^^^^^ | diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr index b049d8a4ab3..c3cfc5a4d97 100644 --- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `U` may not live long enough --> $DIR/dont-infer-static.rs:8:5 | LL | struct Foo { - | - help: consider adding an explicit lifetime bound `U: 'static`... + | - help: consider adding an explicit lifetime bound...: `U: 'static` LL | bar: Bar | ^^^^^^^^^^^ | diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr index 87014085667..297fcb088d2 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:18:18 | LL | enum Ref1<'a, T> { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref1Variant1(RequireOutlives<'a, T>) | ^^^^^^^^^^^^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:23:25 | LL | enum Ref2<'a, T> { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | Ref2Variant1, LL | Ref2Variant2(isize, RequireOutlives<'a, T>), | ^^^^^^^^^^^^^^^^^^^^^^ @@ -31,7 +31,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:35:1 | LL | enum RefDouble<'a, 'b, T> { - | ^ - help: consider adding an explicit lifetime bound `T: 'b`... + | ^ - help: consider adding an explicit lifetime bound...: `T: 'b` | _| | | LL | | RefDoubleVariant1(&'a RequireOutlives<'b, T>) @@ -52,7 +52,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-enum-not-wf.rs:36:23 | LL | enum RefDouble<'a, 'b, T> { - | - help: consider adding an explicit lifetime bound `T: 'b`... + | - help: consider adding an explicit lifetime bound...: `T: 'b` LL | RefDoubleVariant1(&'a RequireOutlives<'b, T>) | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr index 825c1015c51..f6658891fa6 100644 --- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr +++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:13:5 | LL | impl<'a, T> Trait<'a, T> for usize { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a T; | ^^^^^^^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/regions-struct-not-wf.rs:21:5 | LL | impl<'a, T> Trait<'a, T> for u32 { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = RefOk<'a, T>; | ^^^^^^^^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed index 8592af1262e..589ee1a474a 100644 --- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.fixed @@ -3,7 +3,7 @@ use std::fmt::Debug; fn foo(d: impl Debug + 'static) { -//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` +//~^ HELP consider adding an explicit lifetime bound... bar(d); //~^ ERROR the parameter type `impl Debug` may not live long enough //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs index c67d78ea4c7..9a87129fbf2 100644 --- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; fn foo(d: impl Debug) { -//~^ HELP consider adding an explicit lifetime bound `'static` to `impl Debug` +//~^ HELP consider adding an explicit lifetime bound... bar(d); //~^ ERROR the parameter type `impl Debug` may not live long enough //~| NOTE ...so that the type `impl Debug` will meet its required lifetime bounds diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr index cba231d0e86..b6e6c0bbf32 100644 --- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr +++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr @@ -1,6 +1,9 @@ error[E0310]: the parameter type `impl Debug` may not live long enough --> $DIR/suggest-impl-trait-lifetime.rs:7:5 | +LL | fn foo(d: impl Debug) { + | ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static` +LL | LL | bar(d); | ^^^ | @@ -9,10 +12,6 @@ note: ...so that the type `impl Debug` will meet its required lifetime bounds | LL | bar(d); | ^^^ -help: consider adding an explicit lifetime bound `'static` to `impl Debug`... - | -LL | fn foo(d: impl Debug + 'static) { - | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr index 5a7f9d74eba..22e2391f838 100644 --- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr +++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr @@ -25,7 +25,7 @@ LL | type WrongGeneric = impl 'static; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | fn wrong_generic(t: T) -> WrongGeneric { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` | note: ...so that the type `T` will meet its required lifetime bounds --> $DIR/generic_type_does_not_live_long_enough.rs:9:1 diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr index 9cc36025305..9942c80effe 100644 --- a/src/test/ui/wf/wf-impl-associated-type-region.stderr +++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-impl-associated-type-region.rs:10:5 | LL | impl<'a, T> Foo<'a> for T { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Bar = &'a T; | ^^^^^^^^^^^^^^^^^ | diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr index 8952c78aacd..7dc8f5a9661 100644 --- a/src/test/ui/wf/wf-in-fn-type-static.stderr +++ b/src/test/ui/wf/wf-in-fn-type-static.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:13:5 | LL | struct Foo { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: fn() -> &'static T | ^^^^^^^^^^^^^^^^^^^^^ @@ -17,7 +17,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-fn-type-static.rs:18:5 | LL | struct Bar { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: Copy LL | x: fn(&'static T) | ^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr index c461da76a25..32c3198d55b 100644 --- a/src/test/ui/wf/wf-in-obj-type-static.stderr +++ b/src/test/ui/wf/wf-in-obj-type-static.stderr @@ -2,7 +2,7 @@ error[E0310]: the parameter type `T` may not live long enough --> $DIR/wf-in-obj-type-static.rs:14:5 | LL | struct Foo { - | - help: consider adding an explicit lifetime bound `T: 'static`... + | - help: consider adding an explicit lifetime bound...: `T: 'static` LL | // needs T: 'static LL | x: dyn Object<&'static T> | ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr index f1cf514e6b2..52786fb3bca 100644 --- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr +++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr @@ -2,7 +2,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5 | LL | impl<'a, T> Trait<'a, T> for usize { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a fn(T); | ^^^^^^^^^^^^^^^^^^^^^ | @@ -16,7 +16,7 @@ error[E0309]: the parameter type `T` may not live long enough --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5 | LL | impl<'a, T> Trait<'a, T> for u32 { - | - help: consider adding an explicit lifetime bound `T: 'a`... + | - help: consider adding an explicit lifetime bound...: `T: 'a` LL | type Out = &'a dyn Baz; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | From f77f07c55b52ba9a462065fff2f0bc74a0727641 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Fri, 24 Jan 2020 20:05:07 +1300 Subject: [PATCH 0358/1250] Canonicalize inputs to const eval where needed. --- src/librustc_infer/infer/mod.rs | 32 ++++++++++++++++++++++++++++ src/librustc_infer/traits/fulfill.rs | 30 ++++++++------------------ src/librustc_infer/traits/select.rs | 23 ++++++++------------ 3 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index c9e58c2aa73..93d48184b42 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -15,6 +15,8 @@ use rustc::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToTy use rustc::middle::free_region::RegionRelations; use rustc::middle::lang_items; use rustc::middle::region; +use rustc::mir; +use rustc::mir::interpret::ConstEvalResult; use rustc::session::config::BorrowckMode; use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; @@ -63,6 +65,7 @@ pub mod resolve; mod sub; pub mod type_variable; +use crate::infer::canonical::OriginalQueryValues; pub use rustc::infer::unify_key; #[must_use] @@ -1565,6 +1568,35 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.universe.set(u); u } + + /// Resolves and evaluates a constant. + /// + /// The constant can be located on a trait like `::C`, in which case the given + /// substitutions and environment are used to resolve the constant. Alternatively if the + /// constant has generic parameters in scope the substitutions are used to evaluate the value of + /// the constant. For example in `fn foo() { let _ = [0; bar::()]; }` the repeat count + /// constant `bar::()` requires a substitution for `T`, if the substitution for `T` is still + /// too generic for the constant to be evaluated then `Err(ErrorHandled::TooGeneric)` is + /// returned. + /// + /// This handles inferences variables within both `param_env` and `substs` by + /// performing the operation on their respective canonical forms. + pub fn const_eval_resolve( + &self, + param_env: ty::ParamEnv<'tcx>, + def_id: DefId, + substs: SubstsRef<'tcx>, + promoted: Option, + span: Option, + ) -> ConstEvalResult<'tcx> { + let mut original_values = OriginalQueryValues::default(); + let canonical = self.canonicalize_query(&(param_env, substs), &mut original_values); + + let (param_env, substs) = canonical.value; + // The return value is the evaluated value which doesn't contain any reference to inference + // variables, thus we don't need to substitute back the original values. + self.tcx.const_eval_resolve(param_env, def_id, substs, promoted, span) + } } pub struct ShallowResolver<'a, 'tcx> { diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs index 6055b0e74df..28d3f269180 100644 --- a/src/librustc_infer/traits/fulfill.rs +++ b/src/librustc_infer/traits/fulfill.rs @@ -510,27 +510,15 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { } ty::Predicate::ConstEvaluatable(def_id, substs) => { - if obligation.param_env.has_local_value() { - ProcessResult::Unchanged - } else { - if !substs.has_local_value() { - match self.selcx.tcx().const_eval_resolve( - obligation.param_env, - def_id, - substs, - None, - Some(obligation.cause.span), - ) { - Ok(_) => ProcessResult::Changed(vec![]), - Err(err) => { - ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))) - } - } - } else { - pending_obligation.stalled_on = - substs.types().map(|ty| infer_ty(ty)).collect(); - ProcessResult::Unchanged - } + match self.selcx.infcx().const_eval_resolve( + obligation.param_env, + def_id, + substs, + None, + Some(obligation.cause.span), + ) { + Ok(_) => ProcessResult::Changed(vec![]), + Err(err) => ProcessResult::Error(CodeSelectionError(ConstEvalFailure(err))), } } } diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index 371268b5ee4..4572b3c026e 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -532,20 +532,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Predicate::ConstEvaluatable(def_id, substs) => { - if !(obligation.param_env, substs).has_local_value() { - match self.tcx().const_eval_resolve( - obligation.param_env, - def_id, - substs, - None, - None, - ) { - Ok(_) => Ok(EvaluatedToOk), - Err(_) => Ok(EvaluatedToErr), - } - } else { - // Inference variables still left in param_env or substs. - Ok(EvaluatedToAmbig) + match self.tcx().const_eval_resolve( + obligation.param_env, + def_id, + substs, + None, + None, + ) { + Ok(_) => Ok(EvaluatedToOk), + Err(_) => Ok(EvaluatedToErr), } } } From b8523fd0ec19a70e9d02954d1e6e3145746b63d7 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sat, 25 Jan 2020 12:32:58 +1300 Subject: [PATCH 0359/1250] Erase regions before before performing const eval, to improve caching. --- src/librustc/mir/interpret/queries.rs | 36 ++++++++++------------ src/librustc/query/mod.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 6 +--- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/librustc/mir/interpret/queries.rs b/src/librustc/mir/interpret/queries.rs index ed57f81e782..46bf1d96957 100644 --- a/src/librustc/mir/interpret/queries.rs +++ b/src/librustc/mir/interpret/queries.rs @@ -13,13 +13,13 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_poly(self, def_id: DefId) -> ConstEvalResult<'tcx> { // In some situations def_id will have substitutions within scope, but they aren't allowed // to be used. So we can't use `Instance::mono`, instead we feed unresolved substitutions - // into `const_eval` which will return `ErrorHandled::ToGeneric` if any og them are + // into `const_eval` which will return `ErrorHandled::ToGeneric` if any of them are // encountered. let substs = InternalSubsts::identity_for_item(self, def_id); let instance = ty::Instance::new(def_id, substs); let cid = GlobalId { instance, promoted: None }; let param_env = self.param_env(def_id).with_reveal_all(); - self.const_eval_validated(param_env.and(cid)) + self.const_eval_global_id(param_env, cid, None) } /// Resolves and evaluates a constant. @@ -41,11 +41,8 @@ impl<'tcx> TyCtxt<'tcx> { ) -> ConstEvalResult<'tcx> { let instance = ty::Instance::resolve(self, param_env, def_id, substs); if let Some(instance) = instance { - if let Some(promoted) = promoted { - self.const_eval_promoted(param_env, instance, promoted) - } else { - self.const_eval_instance(param_env, instance, span) - } + let cid = GlobalId { instance, promoted }; + self.const_eval_global_id(param_env, cid, span) } else { Err(ErrorHandled::TooGeneric) } @@ -57,22 +54,23 @@ impl<'tcx> TyCtxt<'tcx> { instance: ty::Instance<'tcx>, span: Option, ) -> ConstEvalResult<'tcx> { - let cid = GlobalId { instance, promoted: None }; - if let Some(span) = span { - self.at(span).const_eval_validated(param_env.and(cid)) - } else { - self.const_eval_validated(param_env.and(cid)) - } + self.const_eval_global_id(param_env, GlobalId { instance, promoted: None }, span) } - /// Evaluate a promoted constant. - pub fn const_eval_promoted( + /// Evaluate a constant. + pub fn const_eval_global_id( self, param_env: ty::ParamEnv<'tcx>, - instance: ty::Instance<'tcx>, - promoted: mir::Promoted, + cid: GlobalId<'tcx>, + span: Option, ) -> ConstEvalResult<'tcx> { - let cid = GlobalId { instance, promoted: Some(promoted) }; - self.const_eval_validated(param_env.and(cid)) + // Const-eval shouldn't depend on lifetimes at all, so we can erase them, which should + // improve caching of queries. + let inputs = self.erase_regions(¶m_env.and(cid)); + if let Some(span) = span { + self.at(span).const_eval_validated(inputs) + } else { + self.const_eval_validated(inputs) + } } } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 45ab3fc0b85..e119c214f33 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -502,7 +502,7 @@ rustc_queries! { /// returns a proper constant that is usable by the rest of the compiler. /// /// **Do not use this** directly, use one of the following wrappers: `tcx.const_eval_poly`, - /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_promoted`. + /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalResult<'tcx> { no_force diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index fc4ba4d6cd9..cce4b90e224 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -768,11 +768,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } else { self.param_env }; - let val = if let Some(promoted) = gid.promoted { - self.tcx.const_eval_promoted(param_env, gid.instance, promoted)? - } else { - self.tcx.const_eval_instance(param_env, gid.instance, Some(self.tcx.span))? - }; + let val = self.tcx.const_eval_global_id(param_env, gid, Some(self.tcx.span))?; // Even though `ecx.const_eval` is called from `eval_const_to_op` we can never have a // recursion deeper than one level, because the `tcx.const_eval` above is guaranteed to not From ea18cd7c6473df1e0de19a36ecb81165ada721ab Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Sun, 26 Jan 2020 19:37:32 +1300 Subject: [PATCH 0360/1250] Change FIXME message to indicate plan to handle inference variables within this code path. --- src/librustc/ty/sty.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 9cf61ebe88a..3e0c8e23302 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2488,8 +2488,8 @@ impl<'tcx> Const<'tcx> { // HACK(eddyb) when substs contain e.g. inference variables, // attempt using identity substs instead, that will succeed // when the expression doesn't depend on any parameters. - // FIXME(eddyb) make `const_eval` a canonical query instead, - // that would properly handle inference variables in `substs`. + // FIXME(eddyb, skinny121) pass `InferCtxt` into here when it's available, so that + // we can call `infcx.const_eval_resolve` which handles inference variables. if substs.has_local_value() { let identity_substs = InternalSubsts::identity_for_item(tcx, did); // The `ParamEnv` needs to match the `identity_substs`. From ebfa2f448efcce8f8121b883ee876653fc098261 Mon Sep 17 00:00:00 2001 From: Ben Lewis Date: Mon, 27 Jan 2020 20:42:09 +1300 Subject: [PATCH 0361/1250] Add regression test for issue 68477. --- .../incremental/const-generics/issue-68477.rs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/incremental/const-generics/issue-68477.rs diff --git a/src/test/incremental/const-generics/issue-68477.rs b/src/test/incremental/const-generics/issue-68477.rs new file mode 100644 index 00000000000..925931bc4a6 --- /dev/null +++ b/src/test/incremental/const-generics/issue-68477.rs @@ -0,0 +1,23 @@ +// edition:2018 +// revisions:rpass1 +#![feature(const_generics)] + +const FOO: usize = 1; + +struct Container { + val: std::marker::PhantomData, + blah: [(); FOO] +} + +async fn dummy() {} + +async fn foo() { + let a: Container<&'static ()>; + dummy().await; +} + +fn is_send(_: T) {} + +fn main() { + is_send(foo()); +} From a6b5f875c1cb3a77200c6f3da3d7df0601f90173 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 20 Feb 2020 14:26:43 +0100 Subject: [PATCH 0362/1250] clean up E0321 explanation --- src/librustc_error_codes/error_codes/E0321.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0321.md b/src/librustc_error_codes/error_codes/E0321.md index 49cec94430b..bfcdabfe9de 100644 --- a/src/librustc_error_codes/error_codes/E0321.md +++ b/src/librustc_error_codes/error_codes/E0321.md @@ -1,5 +1,7 @@ A cross-crate opt-out trait was implemented on something which wasn't a struct -or enum type. Erroneous code example: +or enum type. + +Erroneous code example: ```compile_fail,E0321 #![feature(optin_builtin_traits)] From 90ebf93bdfe2acdaeb504a24dea27fbfd74e3218 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 20 Feb 2020 14:26:56 +0100 Subject: [PATCH 0363/1250] Greatly improve E0322 explanation --- src/librustc_error_codes/error_codes/E0322.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/librustc_error_codes/error_codes/E0322.md b/src/librustc_error_codes/error_codes/E0322.md index d2ee426763e..ccef8681dd6 100644 --- a/src/librustc_error_codes/error_codes/E0322.md +++ b/src/librustc_error_codes/error_codes/E0322.md @@ -1,3 +1,13 @@ +The `Sized` trait was implemented explicitly. + +Erroneous code example: + +```compile_fail,E0322 +struct Foo; + +impl Sized for Foo {} // error! +``` + The `Sized` trait is a special trait built-in to the compiler for types with a constant size known at compile-time. This trait is automatically implemented for types as needed by the compiler, and it is currently disallowed to From 8e793ed649a2770211f1a61e7bc6c9119decc991 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 20 Feb 2020 17:20:31 +0100 Subject: [PATCH 0364/1250] Fix broken link to the rustc guide --- src/librustc_passes/region.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index e79ca5c78d6..d0f49fdcc75 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -4,7 +4,7 @@ //! For more information about how MIR-based region-checking works, //! see the [rustc guide]. //! -//! [rustc guide]: https://rust-lang.github.io/rustc-guide/mir/borrowck.html +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/borrow_check.html use rustc::hir::map::Map; use rustc::middle::region::*; From 259977158e19acccc1bbc71c8cc4449ad40a8bef Mon Sep 17 00:00:00 2001 From: Sebastian Imlay Date: Thu, 20 Feb 2020 10:16:32 -0800 Subject: [PATCH 0365/1250] fmt --- src/librustc_target/spec/aarch64_apple_ios.rs | 2 +- .../spec/aarch64_apple_tvos.rs | 2 +- src/librustc_target/spec/apple_sdk_base.rs | 20 +++++++++---------- src/librustc_target/spec/armv7_apple_ios.rs | 2 +- src/librustc_target/spec/armv7s_apple_ios.rs | 2 +- src/librustc_target/spec/i386_apple_ios.rs | 2 +- src/librustc_target/spec/x86_64_apple_ios.rs | 2 +- .../spec/x86_64_apple_ios_macabi.rs | 2 +- src/librustc_target/spec/x86_64_apple_tvos.rs | 2 +- 9 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs index 2216af428fa..e896b46da9a 100644 --- a/src/librustc_target/spec/aarch64_apple_ios.rs +++ b/src/librustc_target/spec/aarch64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs index a87d5965c3d..794bc7900e7 100644 --- a/src/librustc_target/spec/aarch64_apple_tvos.rs +++ b/src/librustc_target/spec/aarch64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs index 2c93cbc4d85..513754352fb 100644 --- a/src/librustc_target/spec/apple_sdk_base.rs +++ b/src/librustc_target/spec/apple_sdk_base.rs @@ -1,4 +1,3 @@ - use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions}; use std::env; use std::io; @@ -102,14 +101,14 @@ pub fn get_sdk_root(sdk_name: &str) -> Result { fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result { let sdk_name = match (arch, os) { - (Arm64, AppleOS::tvOS) => "appletvos", - (X86_64, AppleOS::tvOS) => "appletvsimulator", - (Armv7, AppleOS::iOS) => "iphoneos", - (Armv7s, AppleOS::iOS) => "iphoneos", - (Arm64, AppleOS::iOS) => "iphoneos", - (I386, AppleOS::iOS) => "iphonesimulator", - (X86_64, AppleOS::iOS) => "iphonesimulator", - (X86_64_macabi, AppleOS::iOS) => "macosx10.15", + (Arm64, AppleOS::tvOS) => "appletvos", + (X86_64, AppleOS::tvOS) => "appletvsimulator", + (Armv7, AppleOS::iOS) => "iphoneos", + (Armv7s, AppleOS::iOS) => "iphoneos", + (Arm64, AppleOS::iOS) => "iphoneos", + (I386, AppleOS::iOS) => "iphonesimulator", + (X86_64, AppleOS::iOS) => "iphonesimulator", + (X86_64_macabi, AppleOS::iOS) => "macosx10.15", _ => unreachable!(), }; @@ -145,11 +144,10 @@ fn target_cpu(arch: Arch) -> String { .to_string() } - fn link_env_remove(arch: Arch) -> Vec { match arch { Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()], - X86_64_macabi => vec![ "IPHONEOS_DEPLOYMENT_TARGET".to_string() ,], + X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()], } } diff --git a/src/librustc_target/spec/armv7_apple_ios.rs b/src/librustc_target/spec/armv7_apple_ios.rs index 19d189e2543..c0c2ae909f8 100644 --- a/src/librustc_target/spec/armv7_apple_ios.rs +++ b/src/librustc_target/spec/armv7_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/armv7s_apple_ios.rs b/src/librustc_target/spec/armv7s_apple_ios.rs index 53fb8a9ff9f..6a5654f10d4 100644 --- a/src/librustc_target/spec/armv7s_apple_ios.rs +++ b/src/librustc_target/spec/armv7s_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/i386_apple_ios.rs b/src/librustc_target/spec/i386_apple_ios.rs index eb0c68bc7b8..a121d49769d 100644 --- a/src/librustc_target/spec/i386_apple_ios.rs +++ b/src/librustc_target/spec/i386_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/x86_64_apple_ios.rs b/src/librustc_target/spec/x86_64_apple_ios.rs index db5361f1d81..cfcf856836b 100644 --- a/src/librustc_target/spec/x86_64_apple_ios.rs +++ b/src/librustc_target/spec/x86_64_apple_ios.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs index cce6221134d..c42d0911725 100644 --- a/src/librustc_target/spec/x86_64_apple_ios_macabi.rs +++ b/src/librustc_target/spec/x86_64_apple_ios_macabi.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { diff --git a/src/librustc_target/spec/x86_64_apple_tvos.rs b/src/librustc_target/spec/x86_64_apple_tvos.rs index 794df42f43e..a56062c0b2b 100644 --- a/src/librustc_target/spec/x86_64_apple_tvos.rs +++ b/src/librustc_target/spec/x86_64_apple_tvos.rs @@ -1,4 +1,4 @@ -use super::apple_sdk_base::{opts, Arch, AppleOS}; +use super::apple_sdk_base::{opts, AppleOS, Arch}; use crate::spec::{LinkerFlavor, Target, TargetOptions, TargetResult}; pub fn target() -> TargetResult { From 1cb555a1dc809a8d310354678ef9c43f01e41ad4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 20 Feb 2020 11:05:24 -0800 Subject: [PATCH 0366/1250] Backport only: avoid ICE on bad placeholder type #69148 has a proper fix, but it is too big to backport. This change avoids the ICE by actually emitting an appropriate error. The output will be duplicated in some cases, but that's better than the avoidable ICE. --- src/librustc_typeck/collect.rs | 2 +- src/test/ui/did_you_mean/bad-assoc-ty.rs | 1 + src/test/ui/did_you_mean/bad-assoc-ty.stderr | 26 +- src/test/ui/self/self-infer.rs | 2 + src/test/ui/self/self-infer.stderr | 16 +- .../ui/typeck/typeck_type_placeholder_item.rs | 34 ++ .../typeck_type_placeholder_item.stderr | 316 +++++++++++++++--- 7 files changed, 329 insertions(+), 68 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 80d914d8d0a..79dc1817498 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -319,7 +319,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - self.tcx().sess.delay_span_bug(span, "bad placeholder type"); + placeholder_type_error(self.tcx(), span, &[], vec![span], false); self.tcx().types.err } diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index fccfb7911ce..f02931eeb6f 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -17,6 +17,7 @@ type D = (u8, u8)::AssocTy; type E = _::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures type F = &'static (u8)::AssocTy; //~^ ERROR missing angle brackets in associated item path diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 64e49934d87..d5b2abf2f8b 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -29,25 +29,25 @@ LL | type E = _::AssocTy; | ^^^^^^^^^^ help: try: `<_>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:21:19 + --> $DIR/bad-assoc-ty.rs:22:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:27:10 + --> $DIR/bad-assoc-ty.rs:28:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:44:10 + --> $DIR/bad-assoc-ty.rs:45:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:37:19 + --> $DIR/bad-assoc-ty.rs:38:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` @@ -87,26 +87,32 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | type E = _::AssocTy; | ^ not allowed in type signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:17:10 + | +LL | type E = _::AssocTy; + | ^ not allowed in type signatures + error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:21:19 + --> $DIR/bad-assoc-ty.rs:22:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:27:10 + --> $DIR/bad-assoc-ty.rs:28:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:33:10 + --> $DIR/bad-assoc-ty.rs:34:10 | LL | type H = Fn(u8) -> (u8)::Output; | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:37:19 + --> $DIR/bad-assoc-ty.rs:38:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` @@ -117,12 +123,12 @@ LL | type J = ty!(u8); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:44:10 + --> $DIR/bad-assoc-ty.rs:45:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors Some errors have detailed explanations: E0121, E0223. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs index 0956f2a5691..77c80521236 100644 --- a/src/test/ui/self/self-infer.rs +++ b/src/test/ui/self/self-infer.rs @@ -2,7 +2,9 @@ struct S; impl S { fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig + //~^ ERROR the type placeholder `_` is not allowed within types on item sig fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig + //~^ ERROR the type placeholder `_` is not allowed within types on item sig } fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index 1475b212b56..d6bf8b44d60 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -1,3 +1,9 @@ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/self-infer.rs:4:16 + | +LL | fn f(self: _) {} + | ^ not allowed in type signatures + error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/self-infer.rs:4:16 | @@ -10,7 +16,13 @@ LL | fn f(self: T) {} | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:5:17 + --> $DIR/self-infer.rs:6:17 + | +LL | fn g(self: &_) {} + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/self-infer.rs:6:17 | LL | fn g(self: &_) {} | ^ not allowed in type signatures @@ -20,6 +32,6 @@ help: use type parameters instead LL | fn g(self: &T) {} | ^^^ ^ -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 86c7c52b271..eb6cc832fb4 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -19,19 +19,24 @@ static TEST5: (_, _) = (1, 2); fn test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_b(_: _, _: T) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_c(_: _, _: (T, K, L, A, B)) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Test9; @@ -41,6 +46,7 @@ impl Test9 { fn test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn test11(x: &usize) -> &_ { @@ -59,12 +65,16 @@ impl Clone for Test9 { fn clone_from(&mut self, other: _) { *self = Test9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct Test10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } pub fn main() { @@ -92,13 +102,16 @@ pub fn main() { fn fn_test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures struct FnTest9; @@ -108,6 +121,7 @@ pub fn main() { fn fn_test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } impl Clone for FnTest9 { @@ -116,12 +130,16 @@ pub fn main() { fn clone_from(&mut self, other: _) { *self = FnTest9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct FnTest10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn fn_test11(_: _) -> (_, _) { panic!() } @@ -138,28 +156,40 @@ pub fn main() { trait T { fn method_test1(&self, x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test2(&self, x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test3(&self) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test1(x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test2(x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test3() -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct BadStruct<_>(_); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -168,18 +198,22 @@ struct BadStruct1<_, _>(_); //~| ERROR expected identifier, found reserved identifier `_` //~| ERROR the name `_` is already used //~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct BadStruct2<_, T>(_, T); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 95e8f94c6f3..a8fdd66ee37 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:153:18 + --> $DIR/typeck_type_placeholder_item.rs:179:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:156:16 + --> $DIR/typeck_type_placeholder_item.rs:183:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:19 + --> $DIR/typeck_type_placeholder_item.rs:196:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:196:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:202:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:196:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -79,6 +79,12 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:20:13 + | +LL | fn test6(_: _) { } + | ^ not allowed in type signatures + error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:20:13 | @@ -91,7 +97,13 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:23:18 + --> $DIR/typeck_type_placeholder_item.rs:24:18 + | +LL | fn test6_b(_: _, _: T) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:24:18 | LL | fn test6_b(_: _, _: T) { } | ^ not allowed in type signatures @@ -102,7 +114,13 @@ LL | fn test6_b(_: K, _: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:26:30 + --> $DIR/typeck_type_placeholder_item.rs:28:30 + | +LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:28:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } | ^ not allowed in type signatures @@ -113,7 +131,13 @@ LL | fn test6_c(_: C, _: (T, K, L, A, B)) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:29:13 + --> $DIR/typeck_type_placeholder_item.rs:32:13 + | +LL | fn test7(x: _) { let _x: usize = x; } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:32:13 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -124,13 +148,19 @@ LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:36:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:36:22 + | +LL | fn test8(_f: fn() -> _) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:36:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -141,7 +171,61 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:46:26 + --> $DIR/typeck_type_placeholder_item.rs:72:8 + | +LL | a: _, + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:75:9 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:75:12 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:137:12 + | +LL | a: _, + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:140:13 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:140:16 + | +LL | b: (_, _), + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:179:21 + | +LL | struct BadStruct<_>(_); + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:196:25 + | +LL | struct BadStruct1<_, _>(_); + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:202:25 + | +LL | struct BadStruct2<_, T>(_, T); + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:52:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -150,7 +234,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:51:52 + --> $DIR/typeck_type_placeholder_item.rs:57:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -159,11 +243,11 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:65:8 + --> $DIR/typeck_type_placeholder_item.rs:72:8 | LL | a: _, | ^ not allowed in type signatures -LL | +... LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -174,17 +258,18 @@ help: use type parameters instead LL | struct Test10 { LL | a: T, LL | +LL | LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:71:12 + --> $DIR/typeck_type_placeholder_item.rs:81:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:73:15 + --> $DIR/typeck_type_placeholder_item.rs:83:15 | LL | static B: _ = 42; | ^ @@ -193,13 +278,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:15 + --> $DIR/typeck_type_placeholder_item.rs:85:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:78:21 + --> $DIR/typeck_type_placeholder_item.rs:88:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -208,7 +293,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:81:23 + --> $DIR/typeck_type_placeholder_item.rs:91:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -218,7 +303,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:84:22 + --> $DIR/typeck_type_placeholder_item.rs:94:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -227,7 +312,7 @@ LL | static FN_TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:87:22 + --> $DIR/typeck_type_placeholder_item.rs:97:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -236,13 +321,19 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:90:22 + --> $DIR/typeck_type_placeholder_item.rs:100:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:93:20 + --> $DIR/typeck_type_placeholder_item.rs:103:20 + | +LL | fn fn_test6(_: _) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:103:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -253,7 +344,13 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:96:20 + --> $DIR/typeck_type_placeholder_item.rs:107:20 + | +LL | fn fn_test7(x: _) { let _x: usize = x; } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:107:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -264,13 +361,19 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:111:29 + | +LL | fn fn_test8(_f: fn() -> _) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:111:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:111:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -281,11 +384,11 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:12 + --> $DIR/typeck_type_placeholder_item.rs:137:12 | LL | a: _, | ^ not allowed in type signatures -LL | +... LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -296,17 +399,18 @@ help: use type parameters instead LL | struct FnTest10 { LL | a: T, LL | +LL | LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:127:18 + --> $DIR/typeck_type_placeholder_item.rs:145:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:127:28 + --> $DIR/typeck_type_placeholder_item.rs:145:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -314,7 +418,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:30 + --> $DIR/typeck_type_placeholder_item.rs:149:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -324,7 +428,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:134:33 + --> $DIR/typeck_type_placeholder_item.rs:152:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -333,7 +437,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:153:21 + --> $DIR/typeck_type_placeholder_item.rs:179:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -344,7 +448,19 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:15 + --> $DIR/typeck_type_placeholder_item.rs:185:32 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:15 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -357,13 +473,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:161:34 + --> $DIR/typeck_type_placeholder_item.rs:190:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:166:25 + --> $DIR/typeck_type_placeholder_item.rs:196:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -374,7 +490,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 + --> $DIR/typeck_type_placeholder_item.rs:202:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -385,13 +501,25 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:14 + --> $DIR/typeck_type_placeholder_item.rs:207:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:42:27 + --> $DIR/typeck_type_placeholder_item.rs:207:14 + | +LL | type X = Box<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:47:27 + | +LL | fn test10(&self, _x : _) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:47:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -402,7 +530,13 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:139:31 + --> $DIR/typeck_type_placeholder_item.rs:157:31 + | +LL | fn method_test1(&self, x: _); + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:157:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -413,7 +547,19 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:141:31 + --> $DIR/typeck_type_placeholder_item.rs:160:37 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:160:31 + | +LL | fn method_test2(&self, x: _) -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:160:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -426,7 +572,13 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:143:31 + --> $DIR/typeck_type_placeholder_item.rs:164:31 + | +LL | fn method_test3(&self) -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:164:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -437,7 +589,13 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:145:26 + --> $DIR/typeck_type_placeholder_item.rs:167:26 + | +LL | fn assoc_fn_test1(x: _); + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:167:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -448,7 +606,19 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:147:26 + --> $DIR/typeck_type_placeholder_item.rs:170:32 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:170:26 + | +LL | fn assoc_fn_test2(x: _) -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:170:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -461,7 +631,13 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:149:28 + --> $DIR/typeck_type_placeholder_item.rs:174:28 + | +LL | fn assoc_fn_test3() -> _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:174:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -472,7 +648,13 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:60:37 + --> $DIR/typeck_type_placeholder_item.rs:66:37 + | +LL | fn clone_from(&mut self, other: _) { *self = Test9; } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:66:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -483,7 +665,13 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:109:34 + --> $DIR/typeck_type_placeholder_item.rs:122:34 + | +LL | fn fn_test10(&self, _x : _) { } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:122:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -494,7 +682,13 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:117:41 + --> $DIR/typeck_type_placeholder_item.rs:131:41 + | +LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:131:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -505,13 +699,25 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:181:21 + --> $DIR/typeck_type_placeholder_item.rs:190:34 + | +LL | fn impl_trait() -> impl BadTrait<_> { + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:214:21 + | +LL | type Y = impl Trait<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:214:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:39:24 + --> $DIR/typeck_type_placeholder_item.rs:44:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -520,7 +726,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:24 + --> $DIR/typeck_type_placeholder_item.rs:63:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -529,7 +735,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:106:31 + --> $DIR/typeck_type_placeholder_item.rs:119:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -538,7 +744,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:114:28 + --> $DIR/typeck_type_placeholder_item.rs:128:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -546,7 +752,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 58 previous errors +error: aborting due to 92 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From 748dd455ad202b7d2366bac51de930deb61f0827 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 20 Feb 2020 23:23:22 +0100 Subject: [PATCH 0367/1250] lit_to_const: gracefully bubble up type errors. --- src/librustc/mir/interpret/mod.rs | 4 ++ src/librustc_mir_build/hair/constant.rs | 59 +++++++------------ src/librustc_mir_build/hair/cx/mod.rs | 1 + src/librustc_mir_build/hair/pattern/mod.rs | 1 + src/librustc_typeck/astconv.rs | 2 + .../issue-69310-array-size-lit-wrong-ty.rs | 11 ++++ ...issue-69310-array-size-lit-wrong-ty.stderr | 15 +++++ 7 files changed, 56 insertions(+), 37 deletions(-) create mode 100644 src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs create mode 100644 src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr diff --git a/src/librustc/mir/interpret/mod.rs b/src/librustc/mir/interpret/mod.rs index f0879bdd8ae..c62f9a049a0 100644 --- a/src/librustc/mir/interpret/mod.rs +++ b/src/librustc/mir/interpret/mod.rs @@ -148,6 +148,10 @@ pub struct LitToConstInput<'tcx> { /// Error type for `tcx.lit_to_const`. #[derive(Copy, Clone, Debug, Eq, PartialEq, HashStable)] pub enum LitToConstError { + /// The literal's inferred type did not match the expected `ty` in the input. + /// This is used for graceful error handling (`delay_span_bug`) in + /// type checking (`AstConv::ast_const_to_const`). + TypeError, UnparseableFloat, Reported, } diff --git a/src/librustc_mir_build/hair/constant.rs b/src/librustc_mir_build/hair/constant.rs index e594e1eeed0..e9dd7854275 100644 --- a/src/librustc_mir_build/hair/constant.rs +++ b/src/librustc_mir_build/hair/constant.rs @@ -1,7 +1,7 @@ use rustc::mir::interpret::{ truncate, Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, }; -use rustc::ty::{self, layout::Size, ParamEnv, TyCtxt}; +use rustc::ty::{self, layout::Size, ParamEnv, TyCtxt, TyS}; use rustc_span::symbol::Symbol; use syntax::ast; @@ -20,50 +20,35 @@ crate fn lit_to_const<'tcx>( Ok(ConstValue::Scalar(Scalar::from_uint(result, width))) }; - let lit = match *lit { - ast::LitKind::Str(ref s, _) => { + let lit = match (lit, &ty.kind) { + (ast::LitKind::Str(s, _), ty::Ref(_, TyS { kind: ty::Str, .. }, _)) => { let s = s.as_str(); let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes()); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: s.len() } } - ast::LitKind::ByteStr(ref data) => { - if let ty::Ref(_, ref_ty, _) = ty.kind { - match ref_ty.kind { - ty::Slice(_) => { - let allocation = Allocation::from_byte_aligned_bytes(data as &Vec); - let allocation = tcx.intern_const_alloc(allocation); - ConstValue::Slice { data: allocation, start: 0, end: data.len() } - } - ty::Array(_, _) => { - let id = tcx.allocate_bytes(data); - ConstValue::Scalar(Scalar::Ptr(id.into())) - } - _ => { - bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty) - } - } - } else { - bug!("bytestring should have type of either &[u8] or &[u8; _], not {}", ty) - } + (ast::LitKind::ByteStr(data), ty::Ref(_, TyS { kind: ty::Slice(_), .. }, _)) => { + let allocation = Allocation::from_byte_aligned_bytes(data as &Vec); + let allocation = tcx.intern_const_alloc(allocation); + ConstValue::Slice { data: allocation, start: 0, end: data.len() } + } + (ast::LitKind::ByteStr(data), ty::Ref(_, TyS { kind: ty::Array(_, _), .. }, _)) => { + let id = tcx.allocate_bytes(data); + ConstValue::Scalar(Scalar::Ptr(id.into())) + } + (ast::LitKind::Byte(n), ty::Uint(ast::UintTy::U8)) => { + ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1))) } - ast::LitKind::Byte(n) => ConstValue::Scalar(Scalar::from_uint(n, Size::from_bytes(1))), - ast::LitKind::Int(n, _) if neg => { - let n = n as i128; - let n = n.overflowing_neg().0; - trunc(n as u128)? + (ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => { + trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })? } - ast::LitKind::Int(n, _) => trunc(n)?, - ast::LitKind::Float(n, _) => { - let fty = match ty.kind { - ty::Float(fty) => fty, - _ => bug!(), - }; - parse_float(n, fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? + (ast::LitKind::Float(n, _), ty::Float(fty)) => { + parse_float(*n, *fty, neg).map_err(|_| LitToConstError::UnparseableFloat)? } - ast::LitKind::Bool(b) => ConstValue::Scalar(Scalar::from_bool(b)), - ast::LitKind::Char(c) => ConstValue::Scalar(Scalar::from_char(c)), - ast::LitKind::Err(_) => return Err(LitToConstError::Reported), + (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), + (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), + (ast::LitKind::Err(_), _) => return Err(LitToConstError::Reported), + _ => return Err(LitToConstError::TypeError), }; Ok(ty::Const::from_value(tcx, lit, ty)) } diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs index ee62af7f851..feafd1f7835 100644 --- a/src/librustc_mir_build/hair/cx/mod.rs +++ b/src/librustc_mir_build/hair/cx/mod.rs @@ -148,6 +148,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { // create a dummy value and continue compiling Const::from_bits(self.tcx, 0, self.param_env.and(ty)) } + Err(LitToConstError::TypeError) => bug!("const_eval_literal: had type error"), } } diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index 91011746469..6979a98e687 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -846,6 +846,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { PatKind::Wild } Err(LitToConstError::Reported) => PatKind::Wild, + Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"), } } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 69970faab3f..329358678fd 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2740,6 +2740,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // mir. if let Ok(c) = tcx.at(expr.span).lit_to_const(lit_input) { return c; + } else { + tcx.sess.delay_span_bug(expr.span, "ast_const_to_const: couldn't lit_to_const"); } } diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs new file mode 100644 index 00000000000..98be8c345a9 --- /dev/null +++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.rs @@ -0,0 +1,11 @@ +// This is a regression test for #69310, which was injected by #68118. +// The issue here was that as a performance optimization, +// we call the query `lit_to_const(input);`. +// However, the literal `input.lit` would not be of the type expected by `input.ty`. +// As a result, we immediately called `bug!(...)` instead of bubbling up the problem +// so that it could be handled by the caller of `lit_to_const` (`ast_const_to_const`). + +fn main() {} + +const A: [(); 0.1] = [()]; //~ ERROR mismatched types +const B: [(); b"a"] = [()]; //~ ERROR mismatched types diff --git a/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr new file mode 100644 index 00000000000..7078b4bd7be --- /dev/null +++ b/src/test/ui/consts/issue-69310-array-size-lit-wrong-ty.stderr @@ -0,0 +1,15 @@ +error[E0308]: mismatched types + --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:10:15 + | +LL | const A: [(); 0.1] = [()]; + | ^^^ expected `usize`, found floating-point number + +error[E0308]: mismatched types + --> $DIR/issue-69310-array-size-lit-wrong-ty.rs:11:15 + | +LL | const B: [(); b"a"] = [()]; + | ^^^^ expected `usize`, found `&[u8; 1]` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 100ff5a25666a1903113ecff0dc63ad84e5bdff7 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 7 Feb 2020 11:53:07 +1100 Subject: [PATCH 0368/1250] Revert `u8to64_le` changes from #68914. `SipHasher128`'s `u8to64_le` function was simplified in #68914. Unfortunately, the new version is slower, because it introduces `memcpy` calls with non-statically-known lengths. This commit reverts the change, and adds an explanatory comment (which is also added to `libcore/hash/sip.rs`). This barely affects `SipHasher128`'s speed because it doesn't use `u8to64_le` much, but it does result in `SipHasher128` once again being consistent with `libcore/hash/sip.rs`. --- src/libcore/hash/sip.rs | 4 +- src/librustc_data_structures/sip128.rs | 55 ++++++++++++++++++++------ 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 7ebe01e26dc..c4fbd9dbada 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -121,7 +121,9 @@ macro_rules! load_int_le { }}; } -/// Loads an u64 using up to 7 bytes of a byte slice. +/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the +/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed +/// sizes and avoid calling `memcpy`, which is good for speed. /// /// Unsafe because: unchecked indexing at start..start+len #[inline] diff --git a/src/librustc_data_structures/sip128.rs b/src/librustc_data_structures/sip128.rs index 430f2f40caa..af0e9f79fe1 100644 --- a/src/librustc_data_structures/sip128.rs +++ b/src/librustc_data_structures/sip128.rs @@ -51,17 +51,48 @@ macro_rules! compress { }}; } -/// Loads up to 8 bytes from a byte-slice into a little-endian u64. -#[inline] -fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { - assert!(len <= 8 && start + len <= buf.len()); +/// Loads an integer of the desired type from a byte stream, in LE order. Uses +/// `copy_nonoverlapping` to let the compiler generate the most efficient way +/// to load it from a possibly unaligned address. +/// +/// Unsafe because: unchecked indexing at i..i+size_of(int_ty) +macro_rules! load_int_le { + ($buf:expr, $i:expr, $int_ty:ident) => {{ + debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len()); + let mut data = 0 as $int_ty; + ptr::copy_nonoverlapping( + $buf.get_unchecked($i), + &mut data as *mut _ as *mut u8, + mem::size_of::<$int_ty>(), + ); + data.to_le() + }}; +} - let mut out = 0u64; - unsafe { - let out_ptr = &mut out as *mut _ as *mut u8; - ptr::copy_nonoverlapping(buf.as_ptr().offset(start as isize), out_ptr, len); +/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the +/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed +/// sizes and avoid calling `memcpy`, which is good for speed. +/// +/// Unsafe because: unchecked indexing at start..start+len +#[inline] +unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 { + debug_assert!(len < 8); + let mut i = 0; // current byte index (from LSB) in the output u64 + let mut out = 0; + if i + 3 < len { + out = load_int_le!(buf, start + i, u32) as u64; + i += 4; + } + if i + 1 < len { + out |= (load_int_le!(buf, start + i, u16) as u64) << (i * 8); + i += 2 + } + if i < len { + out |= (*buf.get_unchecked(start + i) as u64) << (i * 8); + i += 1; } - out.to_le() + debug_assert_eq!(i, len); + out } impl SipHasher128 { @@ -243,7 +274,7 @@ impl Hasher for SipHasher128 { if self.ntail != 0 { needed = 8 - self.ntail; - self.tail |= u8to64_le(msg, 0, cmp::min(length, needed)) << (8 * self.ntail); + self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << 8 * self.ntail; if length < needed { self.ntail += length; return; @@ -261,7 +292,7 @@ impl Hasher for SipHasher128 { let mut i = needed; while i < len - left { - let mi = u8to64_le(msg, i, 8); + let mi = unsafe { load_int_le!(msg, i, u64) }; self.state.v3 ^= mi; Sip24Rounds::c_rounds(&mut self.state); @@ -270,7 +301,7 @@ impl Hasher for SipHasher128 { i += 8; } - self.tail = u8to64_le(msg, i, left); + self.tail = unsafe { u8to64_le(msg, i, left) }; self.ntail = left; } From 16790ae1f98692af59c37f6dd5db535fb3c5fe81 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 20 Feb 2020 16:00:39 -0800 Subject: [PATCH 0369/1250] Revert "Rollup merge of #69280 - ecstatic-morse:promote-shuffle-no-special-case, r=petrochenkov" This reverts commit 61d3b6dedb1ec1f3e3cbd3d66b1a3453225bc37c, reversing changes made to c6ad1e2c2a0c7e48537617d36085f866fa6a65a3. --- src/librustc_mir/const_eval/eval_queries.rs | 4 +-- src/librustc_mir/transform/promote_consts.rs | 24 +++++++++++---- src/test/incremental/issue-61530.rs | 3 +- src/test/ui/issues/issue-38074.rs | 3 +- .../simd-intrinsic-generic-elements.rs | 4 --- .../simd-intrinsic-generic-elements.stderr | 30 +++++++++---------- .../simd-intrinsic-inlining-issue67557-ice.rs | 3 +- .../simd-intrinsic-inlining-issue67557.rs | 3 +- .../simd/simd-intrinsic-generic-elements.rs | 6 +--- 9 files changed, 41 insertions(+), 39 deletions(-) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 1cec5d30e9b..4d5464f774f 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -72,8 +72,8 @@ fn eval_body_using_ecx<'mir, 'tcx>( Ok(ret) } -/// The `InterpCx` is only meant to be used to do field and index projections into promoteds -/// and const patterns in match arms. +/// The `InterpCx` is only meant to be used to do field and index projections into constants for +/// `simd_shuffle` and const patterns in match arms. /// /// The function containing the `match` that is currently being analyzed may have generic bounds /// that inform us about the generic bounds of the constant. E.g., using an associated constant diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index a11ee57f465..a5d59860c3d 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -24,6 +24,7 @@ use rustc_span::{Span, DUMMY_SP}; use syntax::ast::LitKind; use rustc_index::vec::{Idx, IndexVec}; +use rustc_target::spec::abi::Abi; use std::cell::Cell; use std::{cmp, iter, mem, usize}; @@ -105,10 +106,11 @@ pub enum Candidate { /// Promotion of the `x` in `[x; 32]`. Repeat(Location), - /// Function calls where the callee has the unstable - /// `#[rustc_args_required_const]` attribute. The attribute requires that - /// the arguments be constant, usually because they are encoded as an - /// immediate operand in a platform intrinsic. + /// Currently applied to function calls where the callee has the unstable + /// `#[rustc_args_required_const]` attribute as well as the SIMD shuffle + /// intrinsic. The intrinsic requires the arguments are indeed constant and + /// the attribute currently provides the semantic requirement that arguments + /// must be constant. Argument { bb: BasicBlock, index: usize }, } @@ -216,6 +218,17 @@ impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> { if let TerminatorKind::Call { ref func, .. } = *kind { if let ty::FnDef(def_id, _) = func.ty(self.body, self.tcx).kind { + let fn_sig = self.tcx.fn_sig(def_id); + if let Abi::RustIntrinsic | Abi::PlatformIntrinsic = fn_sig.abi() { + let name = self.tcx.item_name(def_id); + // FIXME(eddyb) use `#[rustc_args_required_const(2)]` for shuffles. + if name.as_str().starts_with("simd_shuffle") { + self.candidates.push(Candidate::Argument { bb: location.block, index: 2 }); + + return; // Don't double count `simd_shuffle` candidates + } + } + if let Some(constant_args) = args_required_const(self.tcx, def_id) { for index in constant_args { self.candidates.push(Candidate::Argument { bb: location.block, index }); @@ -717,7 +730,8 @@ pub fn validate_candidates( .filter(|&candidate| { validator.explicit = candidate.forces_explicit_promotion(); - // FIXME(eddyb) also emit the errors for `#[rustc_args_required_const]` arguments here. + // FIXME(eddyb) also emit the errors for shuffle indices + // and `#[rustc_args_required_const]` arguments here. let is_promotable = validator.validate_candidate(candidate).is_ok(); match candidate { diff --git a/src/test/incremental/issue-61530.rs b/src/test/incremental/issue-61530.rs index c9c600efed8..06b2957ac62 100644 --- a/src/test/incremental/issue-61530.rs +++ b/src/test/incremental/issue-61530.rs @@ -1,4 +1,4 @@ -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics)] // revisions:rpass1 rpass2 @@ -6,7 +6,6 @@ struct I32x2(i32, i32); extern "platform-intrinsic" { - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/issues/issue-38074.rs b/src/test/ui/issues/issue-38074.rs index 8f7905b31ec..214d6752cef 100644 --- a/src/test/ui/issues/issue-38074.rs +++ b/src/test/ui/issues/issue-38074.rs @@ -1,10 +1,9 @@ // run-pass // ignore-emscripten FIXME(#45351) -#![feature(platform_intrinsics, repr_simd, rustc_attrs)] +#![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs index c9c9ab879f2..5929d05f4de 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.rs @@ -42,13 +42,9 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle3(x: T, y: T, idx: [u32; 3]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr index 29916f85902..78022c0c8bd 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-generic-elements.stderr @@ -1,89 +1,89 @@ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:59:9 + --> $DIR/simd-intrinsic-generic-elements.rs:55:9 | LL | simd_insert(0, 0, 0); | ^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_insert` intrinsic: expected inserted type `i32` (element of input `i32x4`), found `f64` - --> $DIR/simd-intrinsic-generic-elements.rs:61:9 + --> $DIR/simd-intrinsic-generic-elements.rs:57:9 | LL | simd_insert(x, 0, 1.0); | ^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_extract` intrinsic: expected return type `i32` (element of input `i32x4`), found `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:63:9 + --> $DIR/simd-intrinsic-generic-elements.rs:59:9 | LL | simd_extract::<_, f32>(x, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:66:9 + --> $DIR/simd-intrinsic-generic-elements.rs:62:9 | LL | simd_shuffle2::(0, 0, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:68:9 + --> $DIR/simd-intrinsic-generic-elements.rs:64:9 | LL | simd_shuffle3::(0, 0, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:70:9 + --> $DIR/simd-intrinsic-generic-elements.rs:66:9 | LL | simd_shuffle4::(0, 0, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected SIMD input type, found non-SIMD `i32` - --> $DIR/simd-intrinsic-generic-elements.rs:72:9 + --> $DIR/simd-intrinsic-generic-elements.rs:68:9 | LL | simd_shuffle8::(0, 0, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x2` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:75:9 + --> $DIR/simd-intrinsic-generic-elements.rs:71:9 | LL | simd_shuffle2::<_, f32x2>(x, x, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x3` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:77:9 + --> $DIR/simd-intrinsic-generic-elements.rs:73:9 | LL | simd_shuffle3::<_, f32x3>(x, x, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x4` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:79:9 + --> $DIR/simd-intrinsic-generic-elements.rs:75:9 | LL | simd_shuffle4::<_, f32x4>(x, x, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return element type `i32` (element of input `i32x4`), found `f32x8` with element type `f32` - --> $DIR/simd-intrinsic-generic-elements.rs:81:9 + --> $DIR/simd-intrinsic-generic-elements.rs:77:9 | LL | simd_shuffle8::<_, f32x8>(x, x, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle2` intrinsic: expected return type of length 2, found `i32x8` with length 8 - --> $DIR/simd-intrinsic-generic-elements.rs:84:9 + --> $DIR/simd-intrinsic-generic-elements.rs:80:9 | LL | simd_shuffle2::<_, i32x8>(x, x, [0; 2]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle3` intrinsic: expected return type of length 3, found `i32x4` with length 4 - --> $DIR/simd-intrinsic-generic-elements.rs:86:9 + --> $DIR/simd-intrinsic-generic-elements.rs:82:9 | LL | simd_shuffle3::<_, i32x4>(x, x, [0; 3]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle4` intrinsic: expected return type of length 4, found `i32x3` with length 3 - --> $DIR/simd-intrinsic-generic-elements.rs:88:9 + --> $DIR/simd-intrinsic-generic-elements.rs:84:9 | LL | simd_shuffle4::<_, i32x3>(x, x, [0; 4]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0511]: invalid monomorphization of `simd_shuffle8` intrinsic: expected return type of length 8, found `i32x2` with length 2 - --> $DIR/simd-intrinsic-generic-elements.rs:90:9 + --> $DIR/simd-intrinsic-generic-elements.rs:86:9 | LL | simd_shuffle8::<_, i32x2>(x, x, [0; 8]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs index b03b0ef5089..4c09ae25c5f 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557-ice.rs @@ -3,10 +3,9 @@ // // run-pass // compile-flags: -Zmir-opt-level=3 -#![feature(platform_intrinsics, repr_simd, rustc_attrs)] +#![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs index 2741dc13336..7a0d955686b 100644 --- a/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs +++ b/src/test/ui/simd-intrinsic/simd-intrinsic-inlining-issue67557.rs @@ -3,10 +3,9 @@ // // run-pass // compile-flags: -Zmir-opt-level=3 -#![feature(platform_intrinsics, repr_simd, rustc_attrs)] +#![feature(platform_intrinsics, repr_simd)] extern "platform-intrinsic" { - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; } diff --git a/src/test/ui/simd/simd-intrinsic-generic-elements.rs b/src/test/ui/simd/simd-intrinsic-generic-elements.rs index abff59fea78..ea3d4b18944 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-elements.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-elements.rs @@ -1,7 +1,7 @@ // run-pass // ignore-emscripten FIXME(#45351) hits an LLVM assert -#![feature(repr_simd, platform_intrinsics, rustc_attrs)] +#![feature(repr_simd, platform_intrinsics)] #[repr(simd)] #[derive(Copy, Clone, Debug, PartialEq)] @@ -25,13 +25,9 @@ extern "platform-intrinsic" { fn simd_insert(x: T, idx: u32, y: E) -> T; fn simd_extract(x: T, idx: u32) -> E; - #[rustc_args_required_const(2)] fn simd_shuffle2(x: T, y: T, idx: [u32; 2]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle3(x: T, y: T, idx: [u32; 3]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle4(x: T, y: T, idx: [u32; 4]) -> U; - #[rustc_args_required_const(2)] fn simd_shuffle8(x: T, y: T, idx: [u32; 8]) -> U; } From e7ee42baeb54f6484fa76a88e03b3168ff3147ce Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 20 Feb 2020 19:46:09 -0500 Subject: [PATCH 0370/1250] Do not ping the infrastructure team on toolstate changes To my knowledge, there is essentially never any particular action that the infra team needs to take on these pings, and they are currently relatively annoying. --- src/tools/publish_toolstate.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 967333c1ace..81d44a3df25 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -211,14 +211,14 @@ def update_latest( if new > old: # things got fixed or at least the status quo improved changed = True - message += '🎉 {} on {}: {} → {} (cc {}, @rust-lang/infra).\n' \ + message += '🎉 {} on {}: {} → {} (cc {}).\n' \ .format(tool, os, old, new, maintainers) elif new < old: # tests or builds are failing and were not failing before changed = True title = '💔 {} on {}: {} → {}' \ .format(tool, os, old, new) - message += '{} (cc {}, @rust-lang/infra).\n' \ + message += '{} (cc {}).\n' \ .format(title, maintainers) # See if we need to create an issue. if tool == 'miri': From ec980a21b06de1988afff7275bd8d4d44f73722c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 20 Feb 2020 21:25:19 -0500 Subject: [PATCH 0371/1250] Add test for #69312 This bug was fixed by #67501. Closes #69312 --- src/test/ui/consts/issue-69312.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 src/test/ui/consts/issue-69312.rs diff --git a/src/test/ui/consts/issue-69312.rs b/src/test/ui/consts/issue-69312.rs new file mode 100644 index 00000000000..413c6752079 --- /dev/null +++ b/src/test/ui/consts/issue-69312.rs @@ -0,0 +1,10 @@ +// build-pass + +// Verify that the compiler doesn't ICE during const prop while evaluating the index operation. + +#![allow(unconditional_panic)] + +fn main() { + let cols = [0u32; 0]; + cols[0]; +} From 5b7e6c0f3c71891a40a77493bb251fccd5944feb Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 17 Feb 2020 06:41:37 -0500 Subject: [PATCH 0372/1250] Add documentation for the `-Zself-profile-events` flag --- .../src/compiler-flags/self-profile-events.md | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 src/doc/unstable-book/src/compiler-flags/self-profile-events.md diff --git a/src/doc/unstable-book/src/compiler-flags/self-profile-events.md b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md new file mode 100644 index 00000000000..3ce18743be5 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/self-profile-events.md @@ -0,0 +1,74 @@ +# `self-profile-events` + +--------------------- + +The `-Zself-profile-events` compiler flag controls what events are recorded by the self-profiler when it is enabled via the `-Zself-profile` flag. + +This flag takes a comma delimited list of event types to record. + +For example: + +```console +$ rustc -Zself-profile -Zself-profile-events=default,args +``` + +## Event types + +- `query-provider` + - Traces each query used internally by the compiler. + +- `generic-activity` + - Traces other parts of the compiler not covered by the query system. + +- `query-cache-hit` + - Adds tracing information that records when the in-memory query cache is "hit" and does not need to re-execute a query which has been cached. + - Disabled by default because this significantly increases the trace file size. + +- `query-blocked` + - Tracks time that a query tries to run but is blocked waiting on another thread executing the same query to finish executing. + - Query blocking only occurs when the compiler is built with parallel mode support. + +- `incr-cache-load` + - Tracks time that is spent loading and deserializing query results from the incremental compilation on-disk cache. + +- `query-keys` + - Adds a serialized representation of each query's query key to the tracing data. + - Disabled by default because this significantly increases the trace file size. + +- `function-args` + - Adds additional tracing data to some `generic-activity` events. + - Disabled by default for parity with `query-keys`. + +- `llvm` + - Adds tracing information about LLVM passes and codegeneration. + - Disabled by default because this only works when `-Znew-llvm-pass-manager` is enabled. + +## Event synonyms + +- `none` + - Disables all events. + Equivalent to the self-profiler being disabled. + +- `default` + - The default set of events which stikes a balance between providing detailed tracing data and adding additional overhead to the compilation. + +- `args` + - Equivalent to `query-keys` and `function-args`. + +- `all` + - Enables all events. + +## Examples + +Enable the profiler and capture the default set of events (both invocations are equivalent): + +```console +$ rustc -Zself-profile +$ rustc -Zself-profile -Zself-profile-events=default +``` + +Enable the profiler and capture the default events and their arguments: + +```console +$ rustc -Zself-profile -Zself-profile-events=default,args +``` From df11447ca8ccafd14de5d46b885ca73ead121b8d Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 21 Feb 2020 10:32:57 +0100 Subject: [PATCH 0373/1250] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 2855b214397..8fbb23f2549 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 2855b2143972df7102333193aa3c83ddce227e36 +Subproject commit 8fbb23f2549e75b89967f09b9293607bd3bb96a6 From 821c4408f9752b17c40b9cb879fc5f430136ecd8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 21 Feb 2020 11:50:15 +0100 Subject: [PATCH 0374/1250] bump Miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index ded5a52639a..5b8462066d9 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit ded5a52639a78907523b74a9d3ed8e3824c88ca5 +Subproject commit 5b8462066d99511a5ca119cbd3a1443ccf675714 From 211fefc78c619a99b5b1f0c2db05fa037d7e0ec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 21 Feb 2020 13:33:51 +0100 Subject: [PATCH 0375/1250] submodules: update rls from 0100ac8 to 10bf331 Changes: ```` Update cargo ```` --- src/tools/rls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rls b/src/tools/rls index 0100ac87b4c..10bf331d4d1 160000 --- a/src/tools/rls +++ b/src/tools/rls @@ -1 +1 @@ -Subproject commit 0100ac87b4ce5bbed6e56a62f313fbc3ff037a89 +Subproject commit 10bf331d4d1280d773045e57d65031969c51dec6 From c3303c7b086fef4d2571869fe6040ca9455c6e38 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 21 Feb 2020 13:31:21 +0100 Subject: [PATCH 0376/1250] Clean up E0323, E0324 and E0325 explanations --- src/librustc_error_codes/error_codes/E0323.md | 1 + src/librustc_error_codes/error_codes/E0324.md | 5 +++-- src/librustc_error_codes/error_codes/E0325.md | 1 + 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0323.md b/src/librustc_error_codes/error_codes/E0323.md index 6d34c35f9cb..0bf42d17ebc 100644 --- a/src/librustc_error_codes/error_codes/E0323.md +++ b/src/librustc_error_codes/error_codes/E0323.md @@ -1,4 +1,5 @@ An associated const was implemented when another trait item was expected. + Erroneous code example: ```compile_fail,E0323 diff --git a/src/librustc_error_codes/error_codes/E0324.md b/src/librustc_error_codes/error_codes/E0324.md index b8c9e596990..1442cb77dd9 100644 --- a/src/librustc_error_codes/error_codes/E0324.md +++ b/src/librustc_error_codes/error_codes/E0324.md @@ -1,5 +1,6 @@ -A method was implemented when another trait item was expected. Erroneous -code example: +A method was implemented when another trait item was expected. + +Erroneous code example: ```compile_fail,E0324 struct Bar; diff --git a/src/librustc_error_codes/error_codes/E0325.md b/src/librustc_error_codes/error_codes/E0325.md index f685b92cbf0..656fd1ec82b 100644 --- a/src/librustc_error_codes/error_codes/E0325.md +++ b/src/librustc_error_codes/error_codes/E0325.md @@ -1,4 +1,5 @@ An associated type was implemented when another trait item was expected. + Erroneous code example: ```compile_fail,E0325 From 8f3fcec351fcc24aba462f200c60dd712592b64d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 21 Feb 2020 13:32:04 +0100 Subject: [PATCH 0377/1250] Clean up E0326 explanation --- src/librustc_error_codes/error_codes/E0326.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0326.md b/src/librustc_error_codes/error_codes/E0326.md index 0702d00c2de..3d357819c7f 100644 --- a/src/librustc_error_codes/error_codes/E0326.md +++ b/src/librustc_error_codes/error_codes/E0326.md @@ -1,7 +1,6 @@ -The types of any associated constants in a trait implementation must match the -types in the trait definition. This error indicates that there was a mismatch. +An implementation of a trait doesn't match the type contraint. -Here's an example of this error: +Erroneous code example: ```compile_fail,E0326 trait Foo { @@ -14,3 +13,6 @@ impl Foo for Bar { const BAR: u32 = 5; // error, expected bool, found u32 } ``` + +The types of any associated constants in a trait implementation must match the +types in the trait definition. From 8893607a54180f77b85a65d428da6954114844fd Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 21 Feb 2020 11:03:21 -0300 Subject: [PATCH 0378/1250] MIR is not an experiment anymore --- src/librustc_mir/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 4f1b90e34cf..284dd74ce99 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -1,6 +1,6 @@ /*! -Rust MIR: a lowered representation of Rust. Also: an experiment! +Rust MIR: a lowered representation of Rust. */ From b3b252b401ad133fac6d7ea2b452da921ff7f3b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 21 Feb 2020 15:35:31 +0100 Subject: [PATCH 0379/1250] Fix MinGW detection for Cygwin --- src/librustc_codegen_ssa/back/link.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index aaa4448fc19..33036d97dfa 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1008,14 +1008,13 @@ fn get_crt_libs_path(sess: &Session) -> Option { path.pop(); path.pop(); // Based on Clang MinGW driver - let probe_path = path.join(&mingw_dir).join("lib"); - if probe_path.exists() { - return Some(probe_path); - }; - let probe_path = path.join(&mingw_dir).join("sys-root/mingw/lib"); - if probe_path.exists() { - return Some(probe_path); - }; + let probe_paths = vec!["lib", "sys-root/mingw/lib"]; + for probe_path in probe_paths { + let probe_path = path.join(&mingw_dir).join(&probe_path); + if probe_path.join("crt2.o").exists() { + return Some(probe_path); + }; + } }; }; None From 4904b9c228317a9cba963afb87425754a586acf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 21 Feb 2020 16:47:04 +0100 Subject: [PATCH 0380/1250] Detect Chocolatey MinGW installation --- src/librustc_codegen_ssa/back/link.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 33036d97dfa..78aacc56ea4 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1002,15 +1002,22 @@ fn get_crt_libs_path(sess: &Session) -> Option { x if x == "x86" => "i686", x => x, }; + let mingw_bits = &sess.target.target.target_pointer_width; let mingw_dir = format!("{}-w64-mingw32", mingw_arch); // Here we have path/bin/gcc but we need path/ let mut path = linker_path; path.pop(); path.pop(); - // Based on Clang MinGW driver - let probe_paths = vec!["lib", "sys-root/mingw/lib"]; + // Loosely based on Clang MinGW driver + let probe_paths = vec![ + path.join(&mingw_dir).join("lib"), // Typical path + path.join(&mingw_dir).join("sys-root/mingw/lib"), // Rare path + path.join(format!( + "lib/mingw/tools/install/mingw{}/{}/lib", + &mingw_bits, &mingw_dir + )), // Chocolatey is creative + ]; for probe_path in probe_paths { - let probe_path = path.join(&mingw_dir).join(&probe_path); if probe_path.join("crt2.o").exists() { return Some(probe_path); }; From e1c8c8cf63b48c798c1954749e58e99c6cc50093 Mon Sep 17 00:00:00 2001 From: Michael Mc Donnell Date: Thu, 20 Feb 2020 16:01:08 -0800 Subject: [PATCH 0381/1250] Test `Duration::new` panics on overflow A `Duration` is created from a second and nanoseconds variable. The documentation says: "This constructor will panic if the carry from the nanoseconds overflows the seconds counter". This was, however, not tested in the tests. I doubt the behavior will ever regress, but it is usually a good idea to test all documented behavior. --- src/libcore/tests/time.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/libcore/tests/time.rs b/src/libcore/tests/time.rs index 273f1258bb0..c1fbdf7df76 100644 --- a/src/libcore/tests/time.rs +++ b/src/libcore/tests/time.rs @@ -11,6 +11,12 @@ fn creation() { assert_eq!(Duration::from_millis(4000), Duration::new(4, 0)); } +#[test] +#[should_panic] +fn new_overflow() { + let _ = Duration::new(::core::u64::MAX, 1_000_000_000); +} + #[test] fn secs() { assert_eq!(Duration::new(0, 0).as_secs(), 0); From 14442e0ebbbd040f608316aee2f10c937ae5ac4f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 21 Feb 2020 01:21:17 +0100 Subject: [PATCH 0382/1250] print vis & defaultness for nested items --- src/librustc_ast_pretty/pprust.rs | 54 +++++++++++-------- src/librustc_ast_pretty/pprust/tests.rs | 10 +--- src/test/pretty/gat-bounds.pp | 25 --------- src/test/pretty/gat-bounds.rs | 1 - .../pretty/nested-item-vis-defaultness.rs | 47 ++++++++++++++++ 5 files changed, 82 insertions(+), 55 deletions(-) delete mode 100644 src/test/pretty/gat-bounds.pp create mode 100644 src/test/pretty/nested-item-vis-defaultness.rs diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 6e1567ce34e..27cef8502a1 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -2,7 +2,7 @@ use crate::pp::Breaks::{Consistent, Inconsistent}; use crate::pp::{self, Breaks}; use rustc_span::edition::Edition; -use rustc_span::source_map::{dummy_spanned, SourceMap, Spanned}; +use rustc_span::source_map::{SourceMap, Spanned}; use rustc_span::symbol::{kw, sym}; use rustc_span::{BytePos, FileName, Span}; use syntax::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; @@ -1026,7 +1026,7 @@ impl<'a> State<'a> { span: Span, ident: ast::Ident, attrs: &[Attribute], - defaultness: ast::Defaultness, + def: ast::Defaultness, kind: &ast::AssocItemKind, vis: &ast::Visibility, ) { @@ -1034,19 +1034,18 @@ impl<'a> State<'a> { self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); - self.print_defaultness(defaultness); match kind { ast::ForeignItemKind::Fn(sig, gen, body) => { - self.print_fn_full(sig, ident, gen, vis, body.as_deref(), attrs); + self.print_fn_full(sig, ident, gen, vis, def, body.as_deref(), attrs); } ast::ForeignItemKind::Const(ty, body) => { - self.print_item_const(ident, None, ty, body.as_deref(), vis); + self.print_item_const(ident, None, ty, body.as_deref(), vis, def); } ast::ForeignItemKind::Static(ty, mutbl, body) => { - self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis); + self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def); } ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { - self.print_associated_type(ident, generics, bounds, ty.as_deref()); + self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, def); } ast::ForeignItemKind::Macro(m) => { self.print_mac(m); @@ -1065,13 +1064,17 @@ impl<'a> State<'a> { ty: &ast::Ty, body: Option<&ast::Expr>, vis: &ast::Visibility, + defaultness: ast::Defaultness, ) { + self.head(""); + self.print_visibility(vis); + self.print_defaultness(defaultness); let leading = match mutbl { None => "const", Some(ast::Mutability::Not) => "static", Some(ast::Mutability::Mut) => "static mut", }; - self.head(visibility_qualified(vis, leading)); + self.word_space(leading); self.print_ident(ident); self.word_space(":"); self.print_type(ty); @@ -1091,7 +1094,12 @@ impl<'a> State<'a> { generics: &ast::Generics, bounds: &ast::GenericBounds, ty: Option<&ast::Ty>, + vis: &ast::Visibility, + defaultness: ast::Defaultness, ) { + self.head(""); + self.print_visibility(vis); + self.print_defaultness(defaultness); self.word_space("type"); self.print_ident(ident); self.print_generic_params(&generics.params); @@ -1102,7 +1110,9 @@ impl<'a> State<'a> { self.word_space("="); self.print_type(ty); } - self.s.word(";") + self.s.word(";"); + self.end(); // end inner head-block + self.end(); // end outer head-block } /// Pretty-prints an item. @@ -1133,13 +1143,17 @@ impl<'a> State<'a> { self.end(); // end outer head-block } ast::ItemKind::Static(ref ty, mutbl, ref body) => { - self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis); + let def = ast::Defaultness::Final; + self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def); } ast::ItemKind::Const(ref ty, ref body) => { - self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis); + let def = ast::Defaultness::Final; + self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def); } ast::ItemKind::Fn(ref sig, ref gen, ref body) => { - self.print_fn_full(sig, item.ident, gen, &item.vis, body.as_deref(), &item.attrs); + let def = ast::Defaultness::Final; + let body = body.as_deref(); + self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs); } ast::ItemKind::Mod(ref _mod) => { self.head(visibility_qualified(&item.vis, "mod")); @@ -2370,13 +2384,16 @@ impl<'a> State<'a> { name: ast::Ident, generics: &ast::Generics, vis: &ast::Visibility, + defaultness: ast::Defaultness, body: Option<&ast::Block>, attrs: &[ast::Attribute], ) { if body.is_some() { self.head(""); } - self.print_fn(&sig.decl, sig.header, Some(name), generics, vis); + self.print_visibility(vis); + self.print_defaultness(defaultness); + self.print_fn(&sig.decl, sig.header, Some(name), generics); if let Some(body) = body { self.nbsp(); self.print_block_with_attrs(body, attrs); @@ -2391,10 +2408,8 @@ impl<'a> State<'a> { header: ast::FnHeader, name: Option, generics: &ast::Generics, - vis: &ast::Visibility, ) { - self.print_fn_header_info(header, vis); - + self.print_fn_header_info(header); if let Some(name) = name { self.nbsp(); self.print_ident(name); @@ -2672,8 +2687,7 @@ impl<'a> State<'a> { span: rustc_span::DUMMY_SP, }; let header = ast::FnHeader { unsafety, ext, ..ast::FnHeader::default() }; - let vis = dummy_spanned(ast::VisibilityKind::Inherited); - self.print_fn(decl, header, name, &generics, &vis); + self.print_fn(decl, header, name, &generics); self.end(); } @@ -2700,9 +2714,7 @@ impl<'a> State<'a> { } } - crate fn print_fn_header_info(&mut self, header: ast::FnHeader, vis: &ast::Visibility) { - self.s.word(visibility_qualified(vis, "")); - + crate fn print_fn_header_info(&mut self, header: ast::FnHeader) { self.print_constness(header.constness); self.print_asyncness(header.asyncness); self.print_unsafety(header.unsafety); diff --git a/src/librustc_ast_pretty/pprust/tests.rs b/src/librustc_ast_pretty/pprust/tests.rs index 2c938453533..4531c7392a9 100644 --- a/src/librustc_ast_pretty/pprust/tests.rs +++ b/src/librustc_ast_pretty/pprust/tests.rs @@ -1,7 +1,7 @@ use super::*; use rustc_span; -use rustc_span::source_map::{dummy_spanned, respan}; +use rustc_span::source_map::respan; use syntax::ast; use syntax::with_default_globals; @@ -13,13 +13,7 @@ fn fun_to_string( ) -> String { to_string(|s| { s.head(""); - s.print_fn( - decl, - header, - Some(name), - generics, - &dummy_spanned(ast::VisibilityKind::Inherited), - ); + s.print_fn(decl, header, Some(name), generics); s.end(); // Close the head box. s.end(); // Close the outer box. }) diff --git a/src/test/pretty/gat-bounds.pp b/src/test/pretty/gat-bounds.pp deleted file mode 100644 index 0c95add4901..00000000000 --- a/src/test/pretty/gat-bounds.pp +++ /dev/null @@ -1,25 +0,0 @@ -// Check that associated types print generic parameters and where clauses. -// See issue #67509. - -// pretty-compare-only -// pp-exact:gat-bounds.pp - -#![feature(generic_associated_types)] - -trait X { - type - Y: Trait - where - Self: Sized; -} - -impl X for () { - type - Y - where - Self: Sized - = - u32; -} - -fn main() { } diff --git a/src/test/pretty/gat-bounds.rs b/src/test/pretty/gat-bounds.rs index 1275f432a3c..789e4bc80ac 100644 --- a/src/test/pretty/gat-bounds.rs +++ b/src/test/pretty/gat-bounds.rs @@ -2,7 +2,6 @@ // See issue #67509. // pretty-compare-only -// pp-exact:gat-bounds.pp #![feature(generic_associated_types)] diff --git a/src/test/pretty/nested-item-vis-defaultness.rs b/src/test/pretty/nested-item-vis-defaultness.rs new file mode 100644 index 00000000000..0a3f2a10c85 --- /dev/null +++ b/src/test/pretty/nested-item-vis-defaultness.rs @@ -0,0 +1,47 @@ +// Check that nested items have their visibility and `default`nesses in the right order. + +// pp-exact + +fn main() { } + +#[cfg(FALSE)] +extern "C" { + static X: u8 ; + type X; + fn foo(); + pub static X: u8 ; + pub type X; + pub fn foo(); +} + +#[cfg(FALSE)] +trait T { + const X: u8 ; + type X; + fn foo(); + default const X: u8 ; + default type X; + default fn foo(); + pub const X: u8 ; + pub type X; + pub fn foo(); + pub default const X: u8 ; + pub default type X; + pub default fn foo(); +} + +#[cfg(FALSE)] +impl T for S { + const X: u8 ; + type X; + fn foo(); + default const X: u8 ; + default type X; + default fn foo(); + pub const X: u8 ; + pub type X; + pub fn foo(); + pub default const X: u8 ; + pub default type X; + pub default fn foo(); +} From a323ff2c864801fdc8e044e88f11efb49a565ed1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 21:36:15 +0200 Subject: [PATCH 0383/1250] =?UTF-8?q?Implement=20RFC=202532=20=E2=80=93=20?= =?UTF-8?q?Associated=20Type=20Defaults?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/librustc_infer/traits/project.rs | 43 ++++--- src/librustc_typeck/check/mod.rs | 21 ---- .../associated-types-overridden-default.rs | 6 +- ...associated-types-overridden-default.stderr | 9 -- .../associated-types/defaults-cyclic-fail.rs | 35 ++++++ .../defaults-cyclic-fail.stderr | 21 ++++ .../associated-types/defaults-cyclic-pass.rs | 22 ++++ .../defaults-in-other-trait-items.rs | 50 ++++++++ .../defaults-in-other-trait-items.stderr | 25 ++++ .../privacy/associated-item-privacy-trait.rs | 9 +- .../associated-item-privacy-trait.stderr | 113 +++++------------- .../ui/privacy/private-in-public-assoc-ty.rs | 5 + .../privacy/private-in-public-assoc-ty.stderr | 25 ++-- src/test/ui/ufcs/ufcs-partially-resolved.rs | 4 +- .../ui/ufcs/ufcs-partially-resolved.stderr | 10 +- 15 files changed, 247 insertions(+), 151 deletions(-) delete mode 100644 src/test/ui/associated-types/associated-types-overridden-default.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass.rs create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items.rs create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items.stderr diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index a7c3e9110ab..8d9e5d3fa20 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -1054,25 +1054,40 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // an error when we confirm the candidate // (which will ultimately lead to `normalize_to_error` // being invoked). - node_item.item.defaultness.has_value() + false } else { + // If we're looking at a trait *impl*, the item is + // specializable if the impl or the item are marked + // `default`. node_item.item.defaultness.is_default() || super::util::impl_is_default(selcx.tcx(), node_item.node.def_id()) }; - // Only reveal a specializable default if we're past type-checking - // and the obligations is monomorphic, otherwise passes such as - // transmute checking and polymorphic MIR optimizations could - // get a result which isn't correct for all monomorphizations. - if !is_default { - true - } else if obligation.param_env.reveal == Reveal::All { - // NOTE(eddyb) inference variables can resolve to parameters, so - // assume `poly_trait_ref` isn't monomorphic, if it contains any. - let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); - !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() - } else { - false + match is_default { + // Non-specializable items are always projectable + false => true, + + // Only reveal a specializable default if we're past type-checking + // and the obligation is monomorphic, otherwise passes such as + // transmute checking and polymorphic MIR optimizations could + // get a result which isn't correct for all monomorphizations. + true if obligation.param_env.reveal == Reveal::All => { + // NOTE(eddyb) inference variables can resolve to parameters, so + // assume `poly_trait_ref` isn't monomorphic, if it contains any. + let poly_trait_ref = + selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); + !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() + } + + true => { + debug!( + "assemble_candidates_from_impls: not eligible due to default: \ + assoc_ty={} predicate={}", + selcx.tcx().def_path_str(node_item.item.def_id), + obligation.predicate, + ); + false + } } } super::VtableParam(..) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4f6eb20e6eb..4ab5d8f9ad3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1964,7 +1964,6 @@ fn check_impl_items_against_trait<'tcx>( // Locate trait definition and items let trait_def = tcx.trait_def(impl_trait_ref.def_id); - let mut overridden_associated_type = None; let impl_items = || impl_item_refs.iter().map(|iiref| tcx.hir().impl_item(iiref.id)); @@ -2046,9 +2045,6 @@ fn check_impl_items_against_trait<'tcx>( hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); if ty_trait_item.kind == ty::AssocKind::Type { - if ty_trait_item.defaultness.has_value() { - overridden_associated_type = Some(impl_item); - } compare_ty_impl( tcx, &ty_impl_item, @@ -2082,8 +2078,6 @@ fn check_impl_items_against_trait<'tcx>( // Check for missing items from trait let mut missing_items = Vec::new(); - let mut invalidated_items = Vec::new(); - let associated_type_overridden = overridden_associated_type.is_some(); for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { let is_implemented = trait_def .ancestors(tcx, impl_id) @@ -2094,8 +2088,6 @@ fn check_impl_items_against_trait<'tcx>( if !is_implemented && !traits::impl_is_default(tcx, impl_id) { if !trait_item.defaultness.has_value() { missing_items.push(*trait_item); - } else if associated_type_overridden { - invalidated_items.push(trait_item.ident); } } } @@ -2103,19 +2095,6 @@ fn check_impl_items_against_trait<'tcx>( if !missing_items.is_empty() { missing_items_err(tcx, impl_span, &missing_items, full_impl_span); } - - if !invalidated_items.is_empty() { - let invalidator = overridden_associated_type.unwrap(); - struct_span_err!( - tcx.sess, - invalidator.span, - E0399, - "the following trait items need to be reimplemented as `{}` was overridden: `{}`", - invalidator.ident, - invalidated_items.iter().map(|name| name.to_string()).collect::>().join("`, `") - ) - .emit(); - } } fn missing_items_err( diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs index 629fc7a7668..72c30df0b3d 100644 --- a/src/test/ui/associated-types/associated-types-overridden-default.rs +++ b/src/test/ui/associated-types/associated-types-overridden-default.rs @@ -1,3 +1,8 @@ +// check-pass + +// Before RFC 2532, overriding one assoc. type default required overriding all +// provided defaults. + #![feature(associated_type_defaults)] pub trait Tr { @@ -9,7 +14,6 @@ pub trait Tr { impl Tr for () { type Assoc = (); - //~^ ERROR need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo` } fn main() {} diff --git a/src/test/ui/associated-types/associated-types-overridden-default.stderr b/src/test/ui/associated-types/associated-types-overridden-default.stderr deleted file mode 100644 index 79fb9a613c2..00000000000 --- a/src/test/ui/associated-types/associated-types-overridden-default.stderr +++ /dev/null @@ -1,9 +0,0 @@ -error[E0399]: the following trait items need to be reimplemented as `Assoc` was overridden: `Assoc2`, `C`, `foo` - --> $DIR/associated-types-overridden-default.rs:11:5 - | -LL | type Assoc = (); - | ^^^^^^^^^^^^^^^^ - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0399`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.rs b/src/test/ui/associated-types/defaults-cyclic-fail.rs new file mode 100644 index 00000000000..ab66fe0b52e --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail.rs @@ -0,0 +1,35 @@ +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Self::B; + type B = Self::A; +} + +// ...but is an error in any impl that doesn't override at least one of the defaults +impl Tr for () {} +//~^ ERROR overflow evaluating the requirement + +// As soon as at least one is redefined, it works: +impl Tr for u8 { + type A = u8; +} + +impl Tr for u32 { + type A = (); + type B = u8; +} + +// ...but only if this actually breaks the cycle +impl Tr for bool { +//~^ ERROR overflow evaluating the requirement + type A = Box; + //~^ ERROR overflow evaluating the requirement +} +// (the error is shown twice for some reason) + +fn main() { + // Check that the overridden type propagates to the other + let _a: ::A = 0u8; + let _b: ::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.stderr b/src/test/ui/associated-types/defaults-cyclic-fail.stderr new file mode 100644 index 00000000000..dd0e5c2ef42 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail.rs:10:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail.rs:24:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail.rs:26:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs new file mode 100644 index 00000000000..618a2038507 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::new(); + let _item: <() as Tr>::Item = 0u8; + + let _container: ::Container = Vec::::new(); + let _item: ::Item = 0u16; +} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs new file mode 100644 index 00000000000..0455997b168 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs @@ -0,0 +1,50 @@ +#![feature(associated_type_defaults)] + +// Associated type defaults may not be assumed inside the trait defining them. +// ie. they only resolve to `::A`, not the actual type `()` +trait Tr { + type A = (); + + fn f(p: Self::A) { + let () = p; + //~^ ERROR mismatched types + //~| NOTE expected associated type, found `()` + //~| NOTE expected associated type `::A` + //~| NOTE consider constraining + //~| NOTE for more information, visit + } +} + +// An impl that doesn't override the type *can* assume the default. +impl Tr for () { + fn f(p: Self::A) { + let () = p; + } +} + +impl Tr for u8 { + type A = (); + + fn f(p: Self::A) { + let () = p; + } +} + +trait AssocConst { + type Ty = u8; + + // Assoc. consts also cannot assume that default types hold + const C: Self::Ty = 0u8; + //~^ ERROR mismatched types + //~| NOTE expected associated type, found `u8` + //~| NOTE expected associated type `::Ty` + //~| NOTE consider constraining + //~| NOTE for more information, visit +} + +// An impl can, however +impl AssocConst for () { + const C: Self::Ty = 0u8; +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr new file mode 100644 index 00000000000..9ecfe49c2b5 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/defaults-in-other-trait-items.rs:9:13 + | +LL | let () = p; + | ^^ expected associated type, found `()` + | + = note: expected associated type `::A` + found unit type `()` + = note: consider constraining the associated type `::A` to `()` or calling a method that returns `::A` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error[E0308]: mismatched types + --> $DIR/defaults-in-other-trait-items.rs:37:25 + | +LL | const C: Self::Ty = 0u8; + | ^^^ expected associated type, found `u8` + | + = note: expected associated type `::Ty` + found type `u8` + = note: consider constraining the associated type `::Ty` to `u8` or calling a method that returns `::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/privacy/associated-item-privacy-trait.rs b/src/test/ui/privacy/associated-item-privacy-trait.rs index b3d42f09596..03347d5b99a 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.rs +++ b/src/test/ui/privacy/associated-item-privacy-trait.rs @@ -23,8 +23,7 @@ mod priv_trait { ::CONST; //~^ ERROR associated constant `PrivTr::CONST` is private let _: ::AssocTy; - //~^ ERROR trait `priv_trait::PrivTr` is private - //~| ERROR trait `priv_trait::PrivTr` is private + //~^ ERROR associated type `PrivTr::AssocTy` is private pub type InSignatureTy = ::AssocTy; //~^ ERROR trait `priv_trait::PrivTr` is private pub trait InSignatureTr: PrivTr {} @@ -116,15 +115,11 @@ mod priv_parent_substs { >::CONST; //~^ ERROR type `priv_parent_substs::Priv` is private - let _: ::AssocTy; - //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private + let _: ::AssocTy; // FIXME no longer an error?! let _: >::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private let _: >::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private - //~| ERROR type `priv_parent_substs::Priv` is private pub type InSignatureTy1 = ::AssocTy; //~^ ERROR type `priv_parent_substs::Priv` is private diff --git a/src/test/ui/privacy/associated-item-privacy-trait.stderr b/src/test/ui/privacy/associated-item-privacy-trait.stderr index ac422e99855..db24e425a01 100644 --- a/src/test/ui/privacy/associated-item-privacy-trait.stderr +++ b/src/test/ui/privacy/associated-item-privacy-trait.stderr @@ -42,18 +42,7 @@ LL | priv_trait::mac!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: trait `priv_trait::PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:25:13 - | -LL | let _: ::AssocTy; - | ^ -... -LL | priv_trait::mac!(); - | ------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: trait `priv_trait::PrivTr` is private +error: associated type `PrivTr::AssocTy` is private --> $DIR/associated-item-privacy-trait.rs:25:16 | LL | let _: ::AssocTy; @@ -65,7 +54,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `priv_trait::PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:28:34 + --> $DIR/associated-item-privacy-trait.rs:27:34 | LL | pub type InSignatureTy = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -76,7 +65,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `priv_trait::PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:30:34 + --> $DIR/associated-item-privacy-trait.rs:29:34 | LL | pub trait InSignatureTr: PrivTr {} | ^^^^^^ @@ -87,7 +76,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `priv_trait::PrivTr` is private - --> $DIR/associated-item-privacy-trait.rs:32:14 + --> $DIR/associated-item-privacy-trait.rs:31:14 | LL | impl PrivTr for u8 {} | ^^^^^^ @@ -98,7 +87,7 @@ LL | priv_trait::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:49:21 + --> $DIR/associated-item-privacy-trait.rs:48:21 | LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +98,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:51:9 + --> $DIR/associated-item-privacy-trait.rs:50:9 | LL | value; | ^^^^^ @@ -120,7 +109,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:53:13 + --> $DIR/associated-item-privacy-trait.rs:52:13 | LL | Pub.method(loop {}); | ^^^^^^ @@ -131,7 +120,7 @@ LL | priv_signature::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:70:21 + --> $DIR/associated-item-privacy-trait.rs:69:21 | LL | let value = ::method::; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -142,7 +131,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:72:9 + --> $DIR/associated-item-privacy-trait.rs:71:9 | LL | value; | ^^^^^ @@ -153,7 +142,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:74:9 + --> $DIR/associated-item-privacy-trait.rs:73:9 | LL | Pub.method::(); | ^^^^^^^^^^^^^^^^^^^^ @@ -164,7 +153,7 @@ LL | priv_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:94:21 + --> $DIR/associated-item-privacy-trait.rs:93:21 | LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -175,7 +164,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:96:9 + --> $DIR/associated-item-privacy-trait.rs:95:9 | LL | value; | ^^^^^ @@ -186,7 +175,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:98:21 + --> $DIR/associated-item-privacy-trait.rs:97:21 | LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -197,7 +186,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:100:9 + --> $DIR/associated-item-privacy-trait.rs:99:9 | LL | value; | ^^^^^ @@ -208,7 +197,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:102:9 + --> $DIR/associated-item-privacy-trait.rs:101:9 | LL | Pub.method(); | ^^^^^^^^^^^^ @@ -219,7 +208,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:105:21 + --> $DIR/associated-item-privacy-trait.rs:104:21 | LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -230,7 +219,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:107:9 + --> $DIR/associated-item-privacy-trait.rs:106:9 | LL | value; | ^^^^^ @@ -241,7 +230,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:109:9 + --> $DIR/associated-item-privacy-trait.rs:108:9 | LL | Priv.method(); | ^^^^^^^^^^^^^ @@ -252,7 +241,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:112:9 + --> $DIR/associated-item-privacy-trait.rs:111:9 | LL | ::CONST; | ^^^^^^^^^^^^^^^^^^^^^ @@ -263,7 +252,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:114:9 + --> $DIR/associated-item-privacy-trait.rs:113:9 | LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -274,7 +263,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:116:9 + --> $DIR/associated-item-privacy-trait.rs:115:9 | LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -285,54 +274,10 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:119:13 - | -LL | let _: ::AssocTy; - | ^ -... -LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:119:16 - | -LL | let _: ::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:122:13 - | -LL | let _: >::AssocTy; - | ^ -... -LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:122:16 + --> $DIR/associated-item-privacy-trait.rs:119:30 | LL | let _: >::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | priv_parent_substs::mac!(); - | --------------------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) - -error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:125:13 - | -LL | let _: >::AssocTy; - | ^ + | ^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -340,10 +285,10 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:125:16 + --> $DIR/associated-item-privacy-trait.rs:121:17 | LL | let _: >::AssocTy; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^ ... LL | priv_parent_substs::mac!(); | --------------------------- in this macro invocation @@ -351,7 +296,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:129:35 + --> $DIR/associated-item-privacy-trait.rs:124:35 | LL | pub type InSignatureTy1 = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -362,7 +307,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:131:35 + --> $DIR/associated-item-privacy-trait.rs:126:35 | LL | pub type InSignatureTy2 = >::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +318,7 @@ LL | priv_parent_substs::mac!(); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private - --> $DIR/associated-item-privacy-trait.rs:133:14 + --> $DIR/associated-item-privacy-trait.rs:128:14 | LL | impl PubTr for u8 {} | ^^^^^ @@ -383,5 +328,5 @@ LL | priv_parent_substs::mac!(); | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 35 previous errors +error: aborting due to 30 previous errors diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.rs b/src/test/ui/privacy/private-in-public-assoc-ty.rs index ad1052ada60..62faae1f399 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.rs +++ b/src/test/ui/privacy/private-in-public-assoc-ty.rs @@ -10,6 +10,11 @@ mod m { impl PrivTr for Priv {} pub trait PubTrAux1 {} pub trait PubTrAux2 { type A; } + impl PubTrAux1 for u8 {} + impl PubTrAux2 for u8 { + type A = Priv; + //~^ ERROR private type `m::Priv` in public interface + } // "Private-in-public in associated types is hard error" in RFC 2145 // applies only to the aliased types, not bounds. diff --git a/src/test/ui/privacy/private-in-public-assoc-ty.stderr b/src/test/ui/privacy/private-in-public-assoc-ty.stderr index 3cc551cdede..c57073a004d 100644 --- a/src/test/ui/privacy/private-in-public-assoc-ty.stderr +++ b/src/test/ui/privacy/private-in-public-assoc-ty.stderr @@ -1,5 +1,14 @@ +error[E0446]: private type `m::Priv` in public interface + --> $DIR/private-in-public-assoc-ty.rs:15:9 + | +LL | struct Priv; + | - `m::Priv` declared as private +... +LL | type A = Priv; + | ^^^^^^^^^^^^^^ can't leak private type + warning: private trait `m::PrivTr` in public interface (error E0445) - --> $DIR/private-in-public-assoc-ty.rs:16:5 + --> $DIR/private-in-public-assoc-ty.rs:21:5 | LL | / pub trait PubTr { LL | | @@ -15,7 +24,7 @@ LL | | } = note: for more information, see issue #34537 warning: private type `m::Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:16:5 + --> $DIR/private-in-public-assoc-ty.rs:21:5 | LL | / pub trait PubTr { LL | | @@ -30,7 +39,7 @@ LL | | } = note: for more information, see issue #34537 warning: private type `m::Priv` in public interface (error E0446) - --> $DIR/private-in-public-assoc-ty.rs:16:5 + --> $DIR/private-in-public-assoc-ty.rs:21:5 | LL | / pub trait PubTr { LL | | @@ -45,7 +54,7 @@ LL | | } = note: for more information, see issue #34537 error[E0446]: private type `m::Priv` in public interface - --> $DIR/private-in-public-assoc-ty.rs:27:9 + --> $DIR/private-in-public-assoc-ty.rs:32:9 | LL | struct Priv; | - `m::Priv` declared as private @@ -54,7 +63,7 @@ LL | type Alias4 = Priv; | ^^^^^^^^^^^^^^^^^^^ can't leak private type error[E0446]: private type `m::Priv` in public interface - --> $DIR/private-in-public-assoc-ty.rs:34:9 + --> $DIR/private-in-public-assoc-ty.rs:39:9 | LL | struct Priv; | - `m::Priv` declared as private @@ -63,7 +72,7 @@ LL | type Alias1 = Priv; | ^^^^^^^^^^^^^^^^^^^ can't leak private type error[E0445]: private trait `m::PrivTr` in public interface - --> $DIR/private-in-public-assoc-ty.rs:37:9 + --> $DIR/private-in-public-assoc-ty.rs:42:9 | LL | trait PrivTr {} | - `m::PrivTr` declared as private @@ -72,7 +81,7 @@ LL | type Exist = impl PrivTr; | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait error[E0445]: private trait `m::PrivTr` in public interface - --> $DIR/private-in-public-assoc-ty.rs:37:9 + --> $DIR/private-in-public-assoc-ty.rs:42:9 | LL | trait PrivTr {} | - `m::PrivTr` declared as private @@ -80,7 +89,7 @@ LL | trait PrivTr {} LL | type Exist = impl PrivTr; | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0445, E0446. For more information about an error, try `rustc --explain E0445`. diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.rs b/src/test/ui/ufcs/ufcs-partially-resolved.rs index 66d4db3ebaf..e8c767b13e9 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.rs +++ b/src/test/ui/ufcs/ufcs-partially-resolved.rs @@ -35,7 +35,7 @@ fn main() { ::N::NN; //~ ERROR cannot find associated type `N` in `A` let _: ::Y::NN; //~ ERROR ambiguous associated type let _: ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` - ::Y::NN; //~ ERROR no associated item named `NN` found + ::Y::NN; //~ ERROR no associated item named `NN` found for type `u16` ::Y::NN; //~ ERROR expected associated type, found variant `E::Y` let _: ::NN; //~ ERROR cannot find associated type `NN` in `Tr::N` @@ -52,5 +52,5 @@ fn main() { let _: ::Z; //~ ERROR expected associated type, found method `Dr::Z` ::X; //~ ERROR expected method or associated constant, found associated type `Dr::X` let _: ::Z::N; //~ ERROR expected associated type, found method `Dr::Z` - ::X::N; //~ ERROR no associated item named `N` found + ::X::N; //~ ERROR no associated item named `N` found for type `u16` } diff --git a/src/test/ui/ufcs/ufcs-partially-resolved.stderr b/src/test/ui/ufcs/ufcs-partially-resolved.stderr index 60ebe8ee053..e5e6ed9fac9 100644 --- a/src/test/ui/ufcs/ufcs-partially-resolved.stderr +++ b/src/test/ui/ufcs/ufcs-partially-resolved.stderr @@ -205,19 +205,19 @@ error[E0223]: ambiguous associated type --> $DIR/ufcs-partially-resolved.rs:36:12 | LL | let _: ::Y::NN; - | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<::Y as Trait>::NN` + | ^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::NN` -error[E0599]: no associated item named `NN` found for associated type `::Y` in the current scope +error[E0599]: no associated item named `NN` found for type `u16` in the current scope --> $DIR/ufcs-partially-resolved.rs:38:20 | LL | ::Y::NN; - | ^^ associated item not found in `::Y` + | ^^ associated item not found in `u16` -error[E0599]: no associated item named `N` found for associated type `::X` in the current scope +error[E0599]: no associated item named `N` found for type `u16` in the current scope --> $DIR/ufcs-partially-resolved.rs:55:20 | LL | ::X::N; - | ^ associated item not found in `::X` + | ^ associated item not found in `u16` error: aborting due to 32 previous errors From a549bbdc3230b44d18d8828610053c521fe95d9e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 22:03:42 +0200 Subject: [PATCH 0384/1250] Add regression test for #54182 --- src/test/ui/associated-types/issue-54182-1.rs | 79 +++++++++++++++++++ src/test/ui/associated-types/issue-54182-2.rs | 15 ++++ 2 files changed, 94 insertions(+) create mode 100644 src/test/ui/associated-types/issue-54182-1.rs create mode 100644 src/test/ui/associated-types/issue-54182-2.rs diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs new file mode 100644 index 00000000000..bfbf7ed1f22 --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -0,0 +1,79 @@ +// run-pass + +#![feature(associated_type_defaults)] + +macro_rules! overload { + ($a:expr, $b:expr) => { + overload::overload2($a, $b) + }; + ($a:expr, $b:expr, $c:expr) => { + overload::overload3($a, $b, $c) + } +} + +fn main() { + let r = overload!(42, true); + println!("-> {:?}", r); + + let r = overload!("Hello world", 13.0); + println!("-> {:?}", r); + + let r = overload!(42, true, 42.5); + println!("-> {:?}", r); + + let r = overload!("Hello world", 13.0, 42); + println!("-> {:?}", r); +} + +mod overload { + pub trait Overload { + // type R; + type R = (); + fn overload(self) -> Self::R; + } + + // overloads for 2 args + impl Overload for (i32, bool) { + // type R = (); + fn overload(self) /*-> Self::R*/ { + let (a, b) = self; // destructure args + println!("i32 and bool {:?}", (a, b)); + } + } + impl<'a> Overload for (&'a str, f32) { + type R = f32; + fn overload(self) -> Self::R { + let (a, b) = self; // destructure args + println!("&str and f32 {:?}", (a, b)); + b + } + } + + // overloads for 3 args + impl Overload for (i32, bool, f32) { + // type R = (); + fn overload(self) /*-> Self::R*/ { + let (a, b, c) = self; // destructure args + println!("i32 and bool and f32 {:?}", (a, b, c)); + } + } + impl<'a> Overload for (&'a str, f32, i32) { + type R = i32; + fn overload(self) -> Self::R { + let (a, b, c) = self; // destructure args + println!("&str and f32 and i32: {:?}", (a, b, c)); + c + } + } + + // overloads for more args + // ... + + pub fn overload2(a: A, b: B) -> R where (A, B): Overload { + (a, b).overload() + } + + pub fn overload3(a: A, b: B, c: C) -> R where (A, B, C): Overload { + (a, b, c).overload() + } +} diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs new file mode 100644 index 00000000000..cba1b1b3ca6 --- /dev/null +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -0,0 +1,15 @@ +// compile-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Assoc = (); +} + +impl Tr for () {} + +fn f(thing: <() as Tr>::Assoc) { + let c: () = thing; +} + +fn main() {} From 37686edb852f857b0356c6ec41b1c46ed83e9582 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 13 Jun 2019 23:21:19 +0200 Subject: [PATCH 0385/1250] Add comments and assertions to tests --- src/test/ui/associated-types/issue-54182-1.rs | 29 ++++++++++++++----- src/test/ui/associated-types/issue-54182-2.rs | 4 +++ 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs index bfbf7ed1f22..3e10f3fb7df 100644 --- a/src/test/ui/associated-types/issue-54182-1.rs +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -1,5 +1,14 @@ // run-pass +// Tests that the return type of trait methods is correctly normalized when +// checking that a method in an impl matches the trait definition when the +// return type involves a defaulted associated type. +// ie. the trait has a method with return type `-> Self::R`, and `type R = ()`, +// but the impl leaves out the return type (resulting in `()`). +// Note that specialization is not involved in this test; no items in +// implementations may be overridden. If they were, the normalization wouldn't +// happen. + #![feature(associated_type_defaults)] macro_rules! overload { @@ -12,20 +21,20 @@ macro_rules! overload { } fn main() { - let r = overload!(42, true); - println!("-> {:?}", r); + let r: () = overload!(42, true); - let r = overload!("Hello world", 13.0); - println!("-> {:?}", r); + let r: f32 = overload!("Hello world", 13.0); + assert_eq!(r, 13.0); - let r = overload!(42, true, 42.5); - println!("-> {:?}", r); + let r: () = overload!(42, true, 42.5); - let r = overload!("Hello world", 13.0, 42); - println!("-> {:?}", r); + let r: i32 = overload!("Hello world", 13.0, 42); + assert_eq!(r, 42); } mod overload { + /// This trait has an assoc. type defaulting to `()`, and a required method returning a value + /// of that assoc. type. pub trait Overload { // type R; type R = (); @@ -35,6 +44,10 @@ mod overload { // overloads for 2 args impl Overload for (i32, bool) { // type R = (); + + /// This function has no return type specified, and so defaults to `()`. + /// + /// This should work, but didn't, until RFC 2532 was implemented. fn overload(self) /*-> Self::R*/ { let (a, b) = self; // destructure args println!("i32 and bool {:?}", (a, b)); diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs index cba1b1b3ca6..f55f4809780 100644 --- a/src/test/ui/associated-types/issue-54182-2.rs +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -1,5 +1,9 @@ // compile-pass +// Before RFC 2532, normalizing a defaulted assoc. type didn't work at all, +// unless the impl in question overrides that type, which makes the default +// pointless. + #![feature(associated_type_defaults)] trait Tr { From de447eb9f20cbc2a330d6093a4ac8b5eb730b193 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 00:03:32 +0200 Subject: [PATCH 0386/1250] Add tests for assoc. const defaults --- .../associated-const/defaults-cyclic-fail.rs | 17 +++++++ .../defaults-cyclic-fail.stderr | 21 +++++++++ .../associated-const/defaults-cyclic-pass.rs | 35 +++++++++++++++ .../defaults-not-assumed-fail.rs | 44 +++++++++++++++++++ .../defaults-not-assumed-fail.stderr | 23 ++++++++++ .../defaults-not-assumed-pass.rs | 42 ++++++++++++++++++ 6 files changed, 182 insertions(+) create mode 100644 src/test/ui/associated-const/defaults-cyclic-fail.rs create mode 100644 src/test/ui/associated-const/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-const/defaults-cyclic-pass.rs create mode 100644 src/test/ui/associated-const/defaults-not-assumed-fail.rs create mode 100644 src/test/ui/associated-const/defaults-not-assumed-fail.stderr create mode 100644 src/test/ui/associated-const/defaults-not-assumed-pass.rs diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs new file mode 100644 index 00000000000..0f54d67574d --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -0,0 +1,17 @@ +// compile-fail + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + //~^ ERROR cycle detected when const-evaluating `Tr::A` + + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used +impl Tr for () {} + +fn main() { + // This triggers the cycle error + assert_eq!(<() as Tr>::A, 0); +} diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr new file mode 100644 index 00000000000..4e595199091 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:19 + | +LL | const A: u8 = Self::B; + | ^^^^^^^ + | +note: ...which requires const-evaluating `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:19 + | +LL | const B: u8 = Self::A; + | ^^^^^^^ + = note: ...which again requires const-evaluating `Tr::A`, completing the cycle +note: cycle used when processing `main` + --> $DIR/defaults-cyclic-fail.rs:16:16 + | +LL | assert_eq!(<() as Tr>::A, 0); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/src/test/ui/associated-const/defaults-cyclic-pass.rs b/src/test/ui/associated-const/defaults-cyclic-pass.rs new file mode 100644 index 00000000000..1de733cfc37 --- /dev/null +++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs @@ -0,0 +1,35 @@ +// run-pass + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used +impl Tr for () {} + +// Overriding either constant breaks the cycle +impl Tr for u8 { + const A: u8 = 42; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 100; + const B: u8 = 123; +} + +fn main() { + assert_eq!(::A, 42); + assert_eq!(::B, 42); + + assert_eq!(::A, 0); + assert_eq!(::B, 0); + + assert_eq!(::A, 100); + assert_eq!(::B, 123); +} diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs new file mode 100644 index 00000000000..27435ef34a0 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -0,0 +1,44 @@ +// compile-fail + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; + //~^ ERROR any use of this value will cause an error +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + assert_eq!(<() as Tr>::B, 0); // causes the error above + //~^ ERROR evaluation of constant expression failed + + assert_eq!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr new file mode 100644 index 00000000000..aac1765c4b2 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -0,0 +1,23 @@ +error: any use of this value will cause an error + --> $DIR/defaults-not-assumed-fail.rs:8:19 + | +LL | const B: u8 = Self::A + 1; + | --------------^^^^^^^^^^^- + | | + | attempt to add with overflow + | + = note: #[deny(const_err)] on by default + +error[E0080]: evaluation of constant expression failed + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^-------------^^^^^ + | | + | referenced constant has errors + | + = 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 2 previous errors + +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/associated-const/defaults-not-assumed-pass.rs b/src/test/ui/associated-const/defaults-not-assumed-pass.rs new file mode 100644 index 00000000000..c08e05c8a30 --- /dev/null +++ b/src/test/ui/associated-const/defaults-not-assumed-pass.rs @@ -0,0 +1,42 @@ +// run-pass + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + //assert_eq!(<() as Tr>::B, 0); // using this is an error + + assert_eq!(::A, 254); + assert_eq!(::B, 255); + + assert_eq!(::A, 255); + assert_eq!(::B, 0); + + assert_eq!(::A, 254); + assert_eq!(::B, 0); +} From 1e3c02006372ca68d07d32493660583cc1c9e12c Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 21:26:42 +0200 Subject: [PATCH 0387/1250] Test interactions with specialization --- .../defaults-specialization.rs | 46 +++++++++++++++++++ .../defaults-specialization.stderr | 27 +++++++++++ 2 files changed, 73 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-specialization.rs create mode 100644 src/test/ui/associated-types/defaults-specialization.stderr diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs new file mode 100644 index 00000000000..c8aab8fb3ec --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -0,0 +1,46 @@ +// compile-fail + +#![feature(associated_type_defaults, specialization)] + +trait Tr { + type Ty = u8; + + fn make() -> Self::Ty; +} + +struct A(T); +// In a `default impl`, assoc. types are defaulted as well, +// so their values can't be assumed. +default impl Tr for A { + fn make() -> u8 { 0 } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct B(T); +// Explicitly defaulting the type does the same. +impl Tr for B { + default type Ty = bool; + + fn make() -> bool { true } + //~^ ERROR method `make` has an incompatible type for trait +} + +struct C(T); +// Only the method is defaulted, so this is fine. +impl Tr for C { + type Ty = bool; + + default fn make() -> bool { true } +} + +// Defaulted method *can* assume the type, if the default is kept. +struct D(T); +impl Tr for D { + default fn make() -> u8 { 0 } +} + +impl Tr for D { + fn make() -> u8 { 255 } +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr new file mode 100644 index 00000000000..0e6711780f8 --- /dev/null +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -0,0 +1,27 @@ +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:15:18 + | +LL | fn make() -> Self::Ty; + | -------- type in trait +... +LL | fn make() -> u8 { 0 } + | ^^ expected associated type, found u8 + | + = note: expected type `fn() -> as Tr>::Ty` + found type `fn() -> u8` + +error[E0053]: method `make` has an incompatible type for trait + --> $DIR/defaults-specialization.rs:24:18 + | +LL | fn make() -> Self::Ty; + | -------- type in trait +... +LL | fn make() -> bool { true } + | ^^^^ expected associated type, found bool + | + = note: expected type `fn() -> as Tr>::Ty` + found type `fn() -> bool` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0053`. From d3be26d6a8eaf3b5a7c22ba2324ef0751835ce26 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 14 Jun 2019 21:59:11 +0200 Subject: [PATCH 0388/1250] Improve test --- .../defaults-specialization.rs | 18 +++++++++++ .../defaults-specialization.stderr | 31 ++++++++++++++++--- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index c8aab8fb3ec..e3a5db0960c 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -1,3 +1,5 @@ +//! Tests the interaction of associated type defaults and specialization. + // compile-fail #![feature(associated_type_defaults, specialization)] @@ -16,6 +18,13 @@ default impl Tr for A { //~^ ERROR method `make` has an incompatible type for trait } +struct A2(T); +// ...same, but in the method body +default impl Tr for A2 { + fn make() -> Self::Ty { 0u8 } + //~^ ERROR mismatched types +} + struct B(T); // Explicitly defaulting the type does the same. impl Tr for B { @@ -25,6 +34,15 @@ impl Tr for B { //~^ ERROR method `make` has an incompatible type for trait } +struct B2(T); +// ...same, but in the method body +impl Tr for B2 { + default type Ty = bool; + + fn make() -> Self::Ty { true } + //~^ ERROR mismatched types +} + struct C(T); // Only the method is defaulted, so this is fine. impl Tr for C { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 0e6711780f8..2b2adfdb7c9 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,5 +1,5 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:15:18 + --> $DIR/defaults-specialization.rs:17:18 | LL | fn make() -> Self::Ty; | -------- type in trait @@ -11,7 +11,7 @@ LL | fn make() -> u8 { 0 } found type `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:24:18 + --> $DIR/defaults-specialization.rs:33:18 | LL | fn make() -> Self::Ty; | -------- type in trait @@ -22,6 +22,29 @@ LL | fn make() -> bool { true } = note: expected type `fn() -> as Tr>::Ty` found type `fn() -> bool` -error: aborting due to 2 previous errors +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:24:29 + | +LL | fn make() -> Self::Ty { 0u8 } + | -------- ^^^ expected associated type, found u8 + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:42:29 + | +LL | fn make() -> Self::Ty { true } + | -------- ^^^^ expected associated type, found bool + | | + | expected ` as Tr>::Ty` because of return type + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error: aborting due to 4 previous errors -For more information about this error, try `rustc --explain E0053`. +Some errors have detailed explanations: E0053, E0308. +For more information about an error, try `rustc --explain E0053`. From c73ee9861b44a16245e35615307425f6c928fd5e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 19:02:27 +0200 Subject: [PATCH 0389/1250] Check suitability of the provided default --- src/librustc_typeck/check/wfcheck.rs | 72 +++++++ .../associated-types/defaults-suitability.rs | 93 +++++++++ .../defaults-suitability.stderr | 177 ++++++++++++++++++ 3 files changed, 342 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-suitability.rs create mode 100644 src/test/ui/associated-types/defaults-suitability.stderr diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 4ffc3bf8e78..959feb766ee 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -425,6 +425,78 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id, None); + + // Type-check associated type defaults (if there are any): + // Assuming the defaults are used, check that all predicates (bounds on + // the assoc type and where clauses on the trait) hold. + + let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); + + // For all assoc. types with defaults, build a map from + // `>::Assoc` to the default type. + let map = tcx.associated_items(trait_def_id) + .filter_map(|item| { + if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { + // `>::Assoc` + let proj = ty::ProjectionTy { + substs, + item_def_id: item.def_id, + }; + let default_ty = tcx.type_of(item.def_id); + debug!("assoc. type default mapping: {} -> {}", proj, default_ty); + Some((proj, default_ty)) + } else { + None + } + }) + .collect::>(); + + struct DefaultNormalizer<'tcx> { + tcx: TyCtxt<'tcx>, + map: FxHashMap, Ty<'tcx>>, + } + + impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.sty { + ty::Projection(proj_ty) => { + if let Some(default) = self.map.get(&proj_ty) { + default + } else { + t.super_fold_with(self) + } + } + _ => t.super_fold_with(self), + } + } + } + + // Now take all predicates defined on the trait, replace any mention of + // the assoc. types with their default, and prove them. + // We only consider predicates that directly mention the assoc. type. + let mut norm = DefaultNormalizer { tcx, map }; + let predicates = fcx.tcx.predicates_of(trait_def_id); + for &(orig_pred, span) in predicates.predicates.iter() { + let pred = orig_pred.fold_with(&mut norm); + if pred != orig_pred { + // Mentions one of the defaulted assoc. types + debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); + let pred = fcx.normalize_associated_types_in(span, &pred); + let cause = traits::ObligationCause::new( + span, + fcx.body_id, + traits::ItemObligation(trait_def_id), + ); + let obligation = traits::Obligation::new(cause, fcx.param_env, pred); + + fcx.register_predicate(obligation); + } + } + vec![] }); } diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs new file mode 100644 index 00000000000..6a8ea3b6d42 --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -0,0 +1,93 @@ +//! Checks that associated type defaults are properly validated. +//! +//! This means: +//! * Default types are wfchecked +//! * Default types are checked against where clauses on the assoc. type +//! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on +//! the trait itself when possible + +// compile-fail + +#![feature(associated_type_defaults)] + +struct NotClone; + +// Assoc. type bounds must hold for the default type +trait Tr { + type Ty: Clone = NotClone; + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied +} + +// Where-clauses defined on the trait must also be considered +trait Tr2 where Self::Ty: Clone { + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied + type Ty = NotClone; +} + +// Independent of where-clauses (there are none here), default types must always be wf +trait Tr3 { + type Ty = Vec<[u8]>; + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} + +// Involved type parameters must fulfill all bounds required by defaults that mention them +trait Foo { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied +} + +trait Bar: Sized { + // `(): Foo` might hold for some possible impls but not all. + type Assoc: Foo = (); + //~^ ERROR the trait bound `(): Foo` is not satisfied +} + +trait IsU8 {} +impl IsU8 for T {} + +// Test that mentioning the assoc. type inside where clauses works +trait C where + Vec: Clone, + Self::Assoc: IsU8, + bool: IsU8, +{ + type Assoc = u8; +} + +// Test that we get all expected errors if that default is unsuitable +trait D where + Vec: Clone, + //~^ ERROR the trait bound `NotClone: std::clone::Clone` is not satisfied + Self::Assoc: IsU8, + //~^ ERROR the trait bound `NotClone: IsU8` is not satisfied + bool: IsU8, + //~^ ERROR the trait bound `bool: IsU8` is not satisfied +{ + type Assoc = NotClone; +} + +trait Foo2 where + >::Bar: Clone, + //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +{ + type Bar = Vec; + type Baz = T; +} + +trait Foo3 where + >::Bar: Clone, + //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +{ + type Bar = Vec; + type Baz = T; +} + +trait Foo4 where + >::Bar: Clone, +{ + type Bar = Vec; + type Baz: Clone = T; + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied +} + +fn main() {} diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr new file mode 100644 index 00000000000..67b31b414fa --- /dev/null +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -0,0 +1,177 @@ +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:17:14 + | +LL | type Ty: Clone = NotClone; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | +note: required by `Tr` + --> $DIR/defaults-suitability.rs:16:1 + | +LL | trait Tr { + | ^^^^^^^^ + +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:22:27 + | +LL | trait Tr2 where Self::Ty: Clone { + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | +note: required by `Tr2` + --> $DIR/defaults-suitability.rs:22:1 + | +LL | trait Tr2 where Self::Ty: Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:35:15 + | +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | + = help: consider adding a `where T: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` +note: required by `Foo` + --> $DIR/defaults-suitability.rs:34:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ + +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/defaults-suitability.rs:41:17 + | +LL | type Assoc: Foo = (); + | ^^^^^^^^^ the trait `Foo` is not implemented for `()` + | +note: required by `Bar` + --> $DIR/defaults-suitability.rs:39:1 + | +LL | trait Bar: Sized { + | ^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `NotClone: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:61:18 + | +LL | Self::Assoc: IsU8, + | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` + | +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `bool: IsU8` is not satisfied + --> $DIR/defaults-suitability.rs:63:11 + | +LL | bool: IsU8, + | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` + | +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:59:23 + | +LL | Vec: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` + | + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` +note: required by `D` + --> $DIR/defaults-suitability.rs:58:1 + | +LL | / trait D where +LL | | Vec: Clone, +LL | | +LL | | Self::Assoc: IsU8, +... | +LL | | type Assoc = NotClone; +LL | | } + | |_^ + +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:70:29 + | +LL | >::Bar: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` + | + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo2` + --> $DIR/defaults-suitability.rs:69:1 + | +LL | / trait Foo2 where +LL | | >::Bar: Clone, +LL | | +LL | | { +LL | | type Bar = Vec; +LL | | type Baz = T; +LL | | } + | |_^ + +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:78:29 + | +LL | >::Bar: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` + | + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo3` + --> $DIR/defaults-suitability.rs:77:1 + | +LL | / trait Foo3 where +LL | | >::Bar: Clone, +LL | | +LL | | { +LL | | type Bar = Vec; +LL | | type Baz = T; +LL | | } + | |_^ + +error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:89:15 + | +LL | type Baz: Clone = T; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | + = help: consider adding a `where T: std::clone::Clone` bound +note: required by `Foo4` + --> $DIR/defaults-suitability.rs:85:1 + | +LL | / trait Foo4 where +LL | | >::Bar: Clone, +LL | | { +LL | | type Bar = Vec; +LL | | type Baz: Clone = T; +LL | | +LL | | } + | |_^ + +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/defaults-suitability.rs:29:5 + | +LL | type Ty = Vec<[u8]>; + | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `[u8]` + = note: to learn more, visit + = note: required by `std::vec::Vec` + +error: aborting due to 11 previous errors + +For more information about this error, try `rustc --explain E0277`. From f40388292765477881d95a84eb11ef47f8a69500 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 19:07:56 +0200 Subject: [PATCH 0390/1250] Add a `Self: Sized` bound --- src/test/ui/lint/lint-missing-doc.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/lint/lint-missing-doc.rs b/src/test/ui/lint/lint-missing-doc.rs index a2466d28fb0..77f9a3770a3 100644 --- a/src/test/ui/lint/lint-missing-doc.rs +++ b/src/test/ui/lint/lint-missing-doc.rs @@ -60,7 +60,7 @@ pub trait D { } /// dox -pub trait E { +pub trait E: Sized { type AssociatedType; //~ ERROR: missing documentation for an associated type type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type From 5e9317a023ef6b5b5146a29d6b96ca3710d8fbfe Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Jun 2019 20:51:13 +0200 Subject: [PATCH 0391/1250] Put the check into its own function --- src/librustc_typeck/check/wfcheck.rs | 133 ++++++++++++++------------- 1 file changed, 70 insertions(+), 63 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 959feb766ee..603d877cf53 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -425,80 +425,87 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { for_item(tcx, item).with_fcx(|fcx, _| { check_where_clauses(tcx, fcx, item.span, trait_def_id, None); + check_associated_type_defaults(fcx, trait_def_id); - // Type-check associated type defaults (if there are any): - // Assuming the defaults are used, check that all predicates (bounds on - // the assoc type and where clauses on the trait) hold. - - let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); - - // For all assoc. types with defaults, build a map from - // `>::Assoc` to the default type. - let map = tcx.associated_items(trait_def_id) - .filter_map(|item| { - if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { - // `>::Assoc` - let proj = ty::ProjectionTy { - substs, - item_def_id: item.def_id, - }; - let default_ty = tcx.type_of(item.def_id); - debug!("assoc. type default mapping: {} -> {}", proj, default_ty); - Some((proj, default_ty)) - } else { - None - } - }) - .collect::>(); - - struct DefaultNormalizer<'tcx> { - tcx: TyCtxt<'tcx>, - map: FxHashMap, Ty<'tcx>>, - } + vec![] + }); +} - impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { - fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { - self.tcx +/// Checks all associated type defaults of trait `trait_def_id`. +/// +/// Assuming the defaults are used, check that all predicates (bounds on the +/// assoc type and where clauses on the trait) hold. +fn check_associated_type_defaults( + fcx: &FnCtxt<'_, '_>, + trait_def_id: DefId, +) { + let tcx = fcx.tcx; + let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); + + // For all assoc. types with defaults, build a map from + // `>::Assoc` to the default type. + let map = tcx.associated_items(trait_def_id) + .filter_map(|item| { + if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { + // `>::Assoc` + let proj = ty::ProjectionTy { + substs, + item_def_id: item.def_id, + }; + let default_ty = tcx.type_of(item.def_id); + debug!("assoc. type default mapping: {} -> {}", proj, default_ty); + Some((proj, default_ty)) + } else { + None } + }) + .collect::>(); - fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { - ty::Projection(proj_ty) => { - if let Some(default) = self.map.get(&proj_ty) { - default - } else { - t.super_fold_with(self) - } + struct DefaultNormalizer<'tcx> { + tcx: TyCtxt<'tcx>, + map: FxHashMap, Ty<'tcx>>, + } + + impl<'tcx> ty::fold::TypeFolder<'tcx> for DefaultNormalizer<'tcx> { + fn tcx<'a>(&'a self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { + match t.sty { + ty::Projection(proj_ty) => { + if let Some(default) = self.map.get(&proj_ty) { + default + } else { + t.super_fold_with(self) } - _ => t.super_fold_with(self), } + _ => t.super_fold_with(self), } } + } - // Now take all predicates defined on the trait, replace any mention of - // the assoc. types with their default, and prove them. - // We only consider predicates that directly mention the assoc. type. - let mut norm = DefaultNormalizer { tcx, map }; - let predicates = fcx.tcx.predicates_of(trait_def_id); - for &(orig_pred, span) in predicates.predicates.iter() { - let pred = orig_pred.fold_with(&mut norm); - if pred != orig_pred { - // Mentions one of the defaulted assoc. types - debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); - let pred = fcx.normalize_associated_types_in(span, &pred); - let cause = traits::ObligationCause::new( - span, - fcx.body_id, - traits::ItemObligation(trait_def_id), - ); - let obligation = traits::Obligation::new(cause, fcx.param_env, pred); + // Now take all predicates defined on the trait, replace any mention of + // the assoc. types with their default, and prove them. + // We only consider predicates that directly mention the assoc. type. + let mut norm = DefaultNormalizer { tcx, map }; + let predicates = fcx.tcx.predicates_of(trait_def_id); + for &(orig_pred, span) in predicates.predicates.iter() { + let pred = orig_pred.fold_with(&mut norm); + if pred != orig_pred { + // Mentions one of the defaulted assoc. types + debug!("default suitability check: proving predicate: {} -> {}", orig_pred, pred); + let pred = fcx.normalize_associated_types_in(span, &pred); + let cause = traits::ObligationCause::new( + span, + fcx.body_id, + traits::ItemObligation(trait_def_id), + ); + let obligation = traits::Obligation::new(cause, fcx.param_env, pred); - fcx.register_predicate(obligation); - } + fcx.register_predicate(obligation); } - - vec![] - }); + } } fn check_item_fn(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { From ff5d11e0434217531f2699543c7ec7f1e550a42f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 16 Jun 2019 20:53:35 +0200 Subject: [PATCH 0392/1250] Add comments and tests explaining the shallow substitution rule --- src/librustc_typeck/check/wfcheck.rs | 21 ++++++ .../associated-types/defaults-suitability.rs | 35 +++++++--- .../defaults-suitability.stderr | 66 ++++++++----------- 3 files changed, 73 insertions(+), 49 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 603d877cf53..9f1ae37da1a 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -461,6 +461,27 @@ fn check_associated_type_defaults( }) .collect::>(); + /// Replaces projections of associated types with their default types. + /// + /// This does a "shallow substitution", meaning that defaults that refer to + /// other defaulted assoc. types will still refer to the projection + /// afterwards, not to the other default. For example: + /// + /// ```compile_fail + /// trait Tr { + /// type A: Clone = Vec; + /// type B = u8; + /// } + /// ``` + /// + /// This will end up replacing the bound `Self::A: Clone` with + /// `Vec: Clone`, not with `Vec: Clone`. If we did a deep + /// substitution and ended up with the latter, the trait would be accepted. + /// If an `impl` then replaced `B` with something that isn't `Clone`, + /// suddenly the default for `A` is no longer valid. The shallow + /// substitution forces the trait to add a `B: Clone` bound to be accepted, + /// which means that an `impl` can replace any default without breaking + /// others. struct DefaultNormalizer<'tcx> { tcx: TyCtxt<'tcx>, map: FxHashMap, Ty<'tcx>>, diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 6a8ea3b6d42..5a128e56bcb 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -66,28 +66,43 @@ trait D where type Assoc = NotClone; } -trait Foo2 where - >::Bar: Clone, +// Test behavior of the check when defaults refer to other defaults: + +// Shallow substitution rejects this trait since `Baz` isn't guaranteed to be +// `Clone`. +trait Foo2 { + type Bar: Clone = Vec; //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied -{ - type Bar = Vec; type Baz = T; } -trait Foo3 where - >::Bar: Clone, - //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied +// Adding a `T: Clone` bound doesn't help since the requirement doesn't see `T` +// because of the shallow substitution. If we did a deep substitution instead, +// this would be accepted. +trait Foo25 { + type Bar: Clone = Vec; + //~^ ERROR the trait bound `>::Baz: std::clone::Clone` is not satisfied + type Baz = T; +} + +// Adding the `Baz: Clone` bound isn't enough since the default is type +// parameter `T`, which also might not be `Clone`. +trait Foo3 where + Self::Bar: Clone, + Self::Baz: Clone, + //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied { type Bar = Vec; type Baz = T; } +// This one finally works, with `Clone` bounds on all assoc. types and the type +// parameter. trait Foo4 where - >::Bar: Clone, + T: Clone, { - type Bar = Vec; + type Bar: Clone = Vec; type Baz: Clone = T; - //~^ ERROR the trait bound `T: std::clone::Clone` is not satisfied } fn main() {} diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 67b31b414fa..9a7febeb62d 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -104,61 +104,49 @@ LL | | } | |_^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:70:29 + --> $DIR/defaults-suitability.rs:74:15 | -LL | >::Bar: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` note: required by `Foo2` - --> $DIR/defaults-suitability.rs:69:1 + --> $DIR/defaults-suitability.rs:73:1 | -LL | / trait Foo2 where -LL | | >::Bar: Clone, -LL | | -LL | | { -LL | | type Bar = Vec; -LL | | type Baz = T; -LL | | } - | |_^ +LL | trait Foo2 { + | ^^^^^^^^^^^^^ -error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:78:29 +error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied + --> $DIR/defaults-suitability.rs:83:15 | -LL | >::Bar: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` +LL | type Bar: Clone = Vec; + | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound - = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo3` - --> $DIR/defaults-suitability.rs:77:1 + = help: consider adding a `where >::Baz: std::clone::Clone` bound + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +note: required by `Foo25` + --> $DIR/defaults-suitability.rs:82:1 | -LL | / trait Foo3 where -LL | | >::Bar: Clone, -LL | | -LL | | { -LL | | type Bar = Vec; -LL | | type Baz = T; -LL | | } - | |_^ +LL | trait Foo25 { + | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:89:15 + --> $DIR/defaults-suitability.rs:92:16 | -LL | type Baz: Clone = T; - | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` +LL | Self::Baz: Clone, + | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | = help: consider adding a `where T: std::clone::Clone` bound -note: required by `Foo4` - --> $DIR/defaults-suitability.rs:85:1 - | -LL | / trait Foo4 where -LL | | >::Bar: Clone, -LL | | { -LL | | type Bar = Vec; -LL | | type Baz: Clone = T; +note: required by `Foo3` + --> $DIR/defaults-suitability.rs:90:1 + | +LL | / trait Foo3 where +LL | | Self::Bar: Clone, +LL | | Self::Baz: Clone, LL | | +... | +LL | | type Baz = T; LL | | } | |_^ From 07ad64f70fb0c28f6efa107d147e36a07f48610d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 29 Jun 2019 00:30:35 +0200 Subject: [PATCH 0393/1250] Add tests for #62211 --- .../defaults-unsound-62211-1.rs | 62 +++++++++++++ .../defaults-unsound-62211-1.stderr | 93 +++++++++++++++++++ .../defaults-unsound-62211-2.rs | 62 +++++++++++++ .../defaults-unsound-62211-2.stderr | 93 +++++++++++++++++++ 4 files changed, 310 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-1.rs create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-1.stderr create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-2.rs create mode 100644 src/test/ui/associated-types/defaults-unsound-62211-2.stderr diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs new file mode 100644 index 00000000000..aa7beca0047 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -0,0 +1,62 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness, demonstrated here as a use-after-free. + +// compile-fail + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref} +}; + + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied + + Deref + //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied + + AddAssign<&'static str> + //~^ ERROR cannot add-assign `&'static str` to `Self` + + From + + Display = Self; + //~^ ERROR `Self` doesn't implement `std::fmt::Display` + + // We said the Output type was Copy, so we can Copy it freely! + fn unchecked_copy(other: &Self::Output) -> Self::Output { + (*other) + } + + fn make_origin(s: Self) -> Self::Output { + s.into() + } +} + +impl UncheckedCopy for T {} +//~^ ERROR `T` doesn't implement `std::fmt::Display` +//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied +//~| ERROR cannot add-assign `&'static str` to `T` +//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied + +fn bug(origin: T) { + let origin = T::make_origin(origin); + let mut copy = T::unchecked_copy(&origin); + + // assert we indeed have 2 strings pointing to the same buffer. + assert_eq!(origin.as_ptr(), copy.as_ptr()); + + // Drop the origin. Any use of `copy` is UB. + drop(origin); + + copy += "This is invalid!"; + println!("{}", copy); +} + +fn main() { + bug(String::from("hello!")); +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr new file mode 100644 index 00000000000..417edd873ec --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -0,0 +1,93 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:20:18 + | +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | + = help: consider adding a `where Self: std::marker::Copy` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-1.rs:24:7 + | +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:22:7 + | +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | + = help: consider adding a `where Self: std::ops::Deref` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:27:7 + | +LL | + Display = Self; + | ^^^^^^^ `Self` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Self` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = help: consider adding a `where Self: std::fmt::Display` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-1.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `T` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = help: consider adding a `where T: std::fmt::Display` bound + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | + = help: consider adding a `where T: std::ops::Deref` bound + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` + = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-1.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs new file mode 100644 index 00000000000..ce12bd48587 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -0,0 +1,62 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/62211 +//! +//! The old implementation of defaults did not check whether the provided +//! default actually fulfills all bounds on the assoc. type, leading to +//! unsoundness and ICEs, the latter being demonstrated here. + +// compile-fail + +#![feature(associated_type_defaults)] + +use std::{ + fmt::Display, + ops::{AddAssign, Deref} +}; + + +trait UncheckedCopy: Sized { + // This Output is said to be Copy. Yet we default to Self + // and it's accepted, not knowing if Self ineed is Copy + type Output: Copy + //~^ ERROR the trait bound `Self: std::marker::Copy` is not satisfied + + Deref + //~^ ERROR the trait bound `Self: std::ops::Deref` is not satisfied + + AddAssign<&'static str> + //~^ ERROR cannot add-assign `&'static str` to `Self` + + From + + Display = Self; + //~^ ERROR `Self` doesn't implement `std::fmt::Display` + + // We said the Output type was Copy, so we can Copy it freely! + fn unchecked_copy(other: &Self::Output) -> Self::Output { + (*other) + } + + fn make_origin(s: Self) -> Self::Output { + s.into() + } +} + +impl UncheckedCopy for T {} +//~^ ERROR `T` doesn't implement `std::fmt::Display` +//~| ERROR the trait bound `T: std::ops::Deref` is not satisfied +//~| ERROR cannot add-assign `&'static str` to `T` +//~| ERROR the trait bound `T: std::marker::Copy` is not satisfied + +fn bug(origin: T) { + let origin = T::make_origin(origin); + let mut copy = T::unchecked_copy(&origin); + + // assert we indeed have 2 strings pointing to the same buffer. + assert_eq!(origin.as_ptr(), copy.as_ptr()); + + // Drop the origin. Any use of `copy` is UB. + drop(origin); + + copy += "This is invalid!"; + println!("{}", copy); +} + +fn main() { + bug(()); +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr new file mode 100644 index 00000000000..a1ce1f6db31 --- /dev/null +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -0,0 +1,93 @@ +error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:20:18 + | +LL | type Output: Copy + | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | + = help: consider adding a `where Self: std::marker::Copy` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: cannot add-assign `&'static str` to `Self` + --> $DIR/defaults-unsound-62211-2.rs:24:7 + | +LL | + AddAssign<&'static str> + | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` + = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:22:7 + | +LL | + Deref + | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | + = help: consider adding a `where Self: std::ops::Deref` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `Self` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:27:7 + | +LL | + Display = Self; + | ^^^^^^^ `Self` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `Self` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = help: consider adding a `where Self: std::fmt::Display` bound +note: required by `UncheckedCopy` + --> $DIR/defaults-unsound-62211-2.rs:17:1 + | +LL | trait UncheckedCopy: Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: `T` doesn't implement `std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | + = help: the trait `std::fmt::Display` is not implemented for `T` + = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = help: consider adding a `where T: std::fmt::Display` bound + +error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | + = help: consider adding a `where T: std::ops::Deref` bound + +error[E0277]: cannot add-assign `&'static str` to `T` + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | + = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` + = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound + +error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied + --> $DIR/defaults-unsound-62211-2.rs:40:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | + = help: consider adding a `where T: std::marker::Copy` bound + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0277`. From fead45815c626f5086e7e24ae6014fdfd104bff9 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 12:37:41 +0200 Subject: [PATCH 0394/1250] Fix tests after rebase --- src/test/ui/associated-const/defaults-cyclic-fail.stderr | 2 +- src/test/ui/associated-const/defaults-not-assumed-fail.stderr | 2 +- src/test/ui/associated-types/issue-54182-2.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr index 4e595199091..dee4620cdf6 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -10,7 +10,7 @@ note: ...which requires const-evaluating `Tr::B`... LL | const B: u8 = Self::A; | ^^^^^^^ = note: ...which again requires const-evaluating `Tr::A`, completing the cycle -note: cycle used when processing `main` +note: cycle used when const-evaluating `main` --> $DIR/defaults-cyclic-fail.rs:16:16 | LL | assert_eq!(<() as Tr>::A, 0); diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr index aac1765c4b2..365ad322410 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -6,7 +6,7 @@ LL | const B: u8 = Self::A + 1; | | | attempt to add with overflow | - = note: #[deny(const_err)] on by default + = note: `#[deny(const_err)]` on by default error[E0080]: evaluation of constant expression failed --> $DIR/defaults-not-assumed-fail.rs:33:5 diff --git a/src/test/ui/associated-types/issue-54182-2.rs b/src/test/ui/associated-types/issue-54182-2.rs index f55f4809780..c88c7663136 100644 --- a/src/test/ui/associated-types/issue-54182-2.rs +++ b/src/test/ui/associated-types/issue-54182-2.rs @@ -1,4 +1,4 @@ -// compile-pass +// check-pass // Before RFC 2532, normalizing a defaulted assoc. type didn't work at all, // unless the impl in question overrides that type, which makes the default From 485111c48e79e2b41381ff6d4f3301a38b5a167d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 13:40:27 +0200 Subject: [PATCH 0395/1250] Add regression tests for issues --- .../associated-const/defaults-cyclic-pass.rs | 3 +- .../associated-types/defaults-cyclic-pass.rs | 21 +++++--------- .../defaults-in-other-trait-items-pass.rs | 22 ++++++++++++++ .../defaults-unsound-62211-1.rs | 3 ++ .../defaults-unsound-62211-1.stderr | 24 +++++++-------- .../defaults-unsound-62211-2.rs | 3 ++ .../defaults-unsound-62211-2.stderr | 24 +++++++-------- src/test/ui/associated-types/issue-32350.rs | 29 +++++++++++++++++++ src/test/ui/associated-types/issue-41868.rs | 23 +++++++++++++++ src/test/ui/associated-types/issue-43924.rs | 15 ++++++++++ .../ui/associated-types/issue-43924.stderr | 27 +++++++++++++++++ src/test/ui/associated-types/issue-47385.rs | 16 ++++++++++ src/test/ui/associated-types/issue-63593.rs | 11 +++++++ .../ui/associated-types/issue-63593.stderr | 23 +++++++++++++++ 14 files changed, 206 insertions(+), 38 deletions(-) create mode 100644 src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs create mode 100644 src/test/ui/associated-types/issue-32350.rs create mode 100644 src/test/ui/associated-types/issue-41868.rs create mode 100644 src/test/ui/associated-types/issue-43924.rs create mode 100644 src/test/ui/associated-types/issue-43924.stderr create mode 100644 src/test/ui/associated-types/issue-47385.rs create mode 100644 src/test/ui/associated-types/issue-63593.rs create mode 100644 src/test/ui/associated-types/issue-63593.stderr diff --git a/src/test/ui/associated-const/defaults-cyclic-pass.rs b/src/test/ui/associated-const/defaults-cyclic-pass.rs index 1de733cfc37..82105f25f92 100644 --- a/src/test/ui/associated-const/defaults-cyclic-pass.rs +++ b/src/test/ui/associated-const/defaults-cyclic-pass.rs @@ -6,7 +6,8 @@ trait Tr { const B: u8 = Self::A; } -// This impl is *allowed* unless its assoc. consts are used +// This impl is *allowed* unless its assoc. consts are used, matching the +// behavior without defaults. impl Tr for () {} // Overriding either constant breaks the cycle diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs index 618a2038507..74a0cfa6b73 100644 --- a/src/test/ui/associated-types/defaults-cyclic-pass.rs +++ b/src/test/ui/associated-types/defaults-cyclic-pass.rs @@ -2,21 +2,16 @@ #![feature(associated_type_defaults)] +// Having a cycle in assoc. type defaults is okay, as long as there's no impl +// that retains it. trait Tr { - type Item = u8; - type Container = Vec; + type A = Self::B; + type B = Self::A; } -impl Tr for () {} - -impl Tr for u16 { - type Item = u16; +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; } -fn main() { - let _container: <() as Tr>::Container = Vec::::new(); - let _item: <() as Tr>::Item = 0u8; - - let _container: ::Container = Vec::::new(); - let _item: ::Item = 0u16; -} +fn main() {} diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs new file mode 100644 index 00000000000..618a2038507 --- /dev/null +++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -0,0 +1,22 @@ +// check-pass + +#![feature(associated_type_defaults)] + +trait Tr { + type Item = u8; + type Container = Vec; +} + +impl Tr for () {} + +impl Tr for u16 { + type Item = u16; +} + +fn main() { + let _container: <() as Tr>::Container = Vec::::new(); + let _item: <() as Tr>::Item = 0u8; + + let _container: ::Container = Vec::::new(); + let _item: ::Item = 0u16; +} diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index aa7beca0047..37d52ed16b6 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -3,6 +3,9 @@ //! The old implementation of defaults did not check whether the provided //! default actually fulfills all bounds on the assoc. type, leading to //! unsoundness, demonstrated here as a use-after-free. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 // compile-fail diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 417edd873ec..0cad08f6752 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:20:18 + --> $DIR/defaults-unsound-62211-1.rs:23:18 | LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:24:7 + --> $DIR/defaults-unsound-62211-1.rs:27:7 | LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -20,26 +20,26 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:22:7 + --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:27:7 + --> $DIR/defaults-unsound-62211-1.rs:30:7 | LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter @@ -48,13 +48,13 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:17:1 + --> $DIR/defaults-unsound-62211-1.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter @@ -64,7 +64,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` @@ -72,7 +72,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::Deref` bound error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ no implementation for `T += &'static str` @@ -81,7 +81,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:40:9 + --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index ce12bd48587..d042a1478a3 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -3,6 +3,9 @@ //! The old implementation of defaults did not check whether the provided //! default actually fulfills all bounds on the assoc. type, leading to //! unsoundness and ICEs, the latter being demonstrated here. +//! +//! Note that the underlying cause of this is still not yet fixed. +//! See: https://github.com/rust-lang/rust/issues/33017 // compile-fail diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index a1ce1f6db31..3a57f7df055 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,18 +1,18 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:20:18 + --> $DIR/defaults-unsound-62211-2.rs:23:18 | LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:24:7 + --> $DIR/defaults-unsound-62211-2.rs:27:7 | LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -20,26 +20,26 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:22:7 + --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:27:7 + --> $DIR/defaults-unsound-62211-2.rs:30:7 | LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter @@ -48,13 +48,13 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:17:1 + --> $DIR/defaults-unsound-62211-2.rs:20:1 | LL | trait UncheckedCopy: Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter @@ -64,7 +64,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` @@ -72,7 +72,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::Deref` bound error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ no implementation for `T += &'static str` @@ -81,7 +81,7 @@ LL | impl UncheckedCopy for T {} = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:40:9 + --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` diff --git a/src/test/ui/associated-types/issue-32350.rs b/src/test/ui/associated-types/issue-32350.rs new file mode 100644 index 00000000000..bda21eb0e0a --- /dev/null +++ b/src/test/ui/associated-types/issue-32350.rs @@ -0,0 +1,29 @@ +// check-pass + +// This is another instance of the "normalizations don't work" issue with +// defaulted associated types. + +#![feature(associated_type_defaults)] + +pub trait Emitter<'a> { + type Ctxt: 'a; + type CtxtBrw: 'a = &'a Self::Ctxt; + + fn get_cx(&'a self) -> Self::CtxtBrw; +} + +struct MyCtxt; + +struct MyEmitter { + ctxt: MyCtxt +} + +impl <'a> Emitter<'a> for MyEmitter { + type Ctxt = MyCtxt; + + fn get_cx(&'a self) -> &'a MyCtxt { + &self.ctxt + } +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-41868.rs b/src/test/ui/associated-types/issue-41868.rs new file mode 100644 index 00000000000..52bbd1f5d28 --- /dev/null +++ b/src/test/ui/associated-types/issue-41868.rs @@ -0,0 +1,23 @@ +// check-pass + +// Defaulted assoc. types should normalize properly in impls that don't +// override them. + +#![feature(associated_type_defaults)] + +pub struct Foo; + +pub trait CanDecode: Sized { + type Output = Self; + fn read(rdr: &mut Foo) -> Option; +} + +impl CanDecode for u8 { + fn read(rdr: &mut Foo) -> Option { Some(42) } +} + +impl CanDecode for u16 { + fn read(rdr: &mut Foo) -> Option { Some(17) } +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-43924.rs b/src/test/ui/associated-types/issue-43924.rs new file mode 100644 index 00000000000..26f1183c6bd --- /dev/null +++ b/src/test/ui/associated-types/issue-43924.rs @@ -0,0 +1,15 @@ +#![feature(associated_type_defaults)] + +// This used to cause an ICE because assoc. type defaults weren't properly +// type-checked. + +trait Foo { + type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied +} + +impl Foo for () {} //~ error: not satisfied +impl Foo for () {} //~ error: not satisfied + +fn main() { + assert_eq!(<() as Foo>::Out::default().to_string(), "false"); +} diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr new file mode 100644 index 00000000000..67a963b5013 --- /dev/null +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -0,0 +1,27 @@ +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:7:15 + | +LL | type Out: Default + ToString + ?Sized = dyn ToString; + | ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + | +note: required by `Foo` + --> $DIR/issue-43924.rs:6:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:10:6 + | +LL | impl Foo for () {} + | ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + +error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied + --> $DIR/issue-43924.rs:11:6 + | +LL | impl Foo for () {} + | ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/issue-47385.rs b/src/test/ui/associated-types/issue-47385.rs new file mode 100644 index 00000000000..d43d674e9c3 --- /dev/null +++ b/src/test/ui/associated-types/issue-47385.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(associated_type_defaults)] + +pub struct Foo; + +pub trait Bar: From<::Input> { + type Input = Self; +} + +impl Bar for Foo { + // Will compile with explicit type: + // type Input = Self; +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-63593.rs b/src/test/ui/associated-types/issue-63593.rs new file mode 100644 index 00000000000..1452467f373 --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.rs @@ -0,0 +1,11 @@ +#![feature(associated_type_defaults)] + +// Tests that `Self` is not assumed to implement `Sized` when used as an +// associated type default. + +trait Inner {} + +trait MyTrait { + type This = Self; //~ error: size for values of type `Self` cannot be known + fn something>(i: I); +} diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr new file mode 100644 index 00000000000..ea462eac9b4 --- /dev/null +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -0,0 +1,23 @@ +error[E0601]: `main` function not found in crate `issue_63593` + | + = note: consider adding a `main` function to `$DIR/issue-63593.rs` + +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/issue-63593.rs:9:5 + | +LL | type This = Self; + | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit + = help: consider adding a `where Self: std::marker::Sized` bound +note: required by `MyTrait` + --> $DIR/issue-63593.rs:8:1 + | +LL | trait MyTrait { + | ^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0601. +For more information about an error, try `rustc --explain E0277`. From 1f61f36849249b5333c74f63d54d2f8bfe30ad59 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Thu, 29 Aug 2019 14:11:55 +0200 Subject: [PATCH 0396/1250] Add comment about the shallow subst rule --- src/librustc_typeck/check/wfcheck.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 9f1ae37da1a..e39beb547d1 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -482,6 +482,9 @@ fn check_associated_type_defaults( /// substitution forces the trait to add a `B: Clone` bound to be accepted, /// which means that an `impl` can replace any default without breaking /// others. + /// + /// Note that this isn't needed for soundness: The defaults would still be + /// checked in any impl that doesn't override them. struct DefaultNormalizer<'tcx> { tcx: TyCtxt<'tcx>, map: FxHashMap, Ty<'tcx>>, From fd28614cb799b762880b25b976760ddd0c530e92 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 01:15:22 +0200 Subject: [PATCH 0397/1250] Add regression test for #26681 --- src/test/ui/associated-types/issue-26681.rs | 20 +++++++++++++++++++ .../ui/associated-types/issue-26681.stderr | 12 +++++++++++ 2 files changed, 32 insertions(+) create mode 100644 src/test/ui/associated-types/issue-26681.rs create mode 100644 src/test/ui/associated-types/issue-26681.stderr diff --git a/src/test/ui/associated-types/issue-26681.rs b/src/test/ui/associated-types/issue-26681.rs new file mode 100644 index 00000000000..a0a8c86d949 --- /dev/null +++ b/src/test/ui/associated-types/issue-26681.rs @@ -0,0 +1,20 @@ +#![feature(associated_type_defaults)] + +// This is a partial regression test for #26681, which used to fail to resolve +// `Self` in the assoc. constant, and now fails with a type mismatch because +// `Self::Fv` cannot be assumed to equal `u8` inside the trait. + +trait Foo { + type Bar; +} + +impl Foo for u8 { + type Bar = (); +} + +trait Baz { + type Fv: Foo = u8; + const C: ::Bar = 6665; //~ error: mismatched types +} + +fn main() {} diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr new file mode 100644 index 00000000000..27175a247fa --- /dev/null +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/issue-26681.rs:17:39 + | +LL | const C: ::Bar = 6665; + | ^^^^ expected associated type, found integer + | + = note: expected type `<::Fv as Foo>::Bar` + found type `{integer}` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From c96452074027479cec7d93cad8a8688577ec3cf1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 16:52:02 +0200 Subject: [PATCH 0398/1250] Update tests after compiletest changes --- .../defaults-suitability.stderr | 93 ++++++------------- .../defaults-unsound-62211-1.stderr | 32 +++---- .../defaults-unsound-62211-2.stderr | 32 +++---- .../ui/associated-types/issue-43924.stderr | 8 +- src/test/ui/associated-types/issue-54182-1.rs | 4 +- src/test/ui/associated-types/issue-63593.rs | 2 + .../ui/associated-types/issue-63593.stderr | 16 +--- 7 files changed, 63 insertions(+), 124 deletions(-) diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 9a7febeb62d..dd45c9e4436 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,154 +1,119 @@ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:17:14 | +LL | trait Tr { + | -------- required by `Tr` LL | type Ty: Clone = NotClone; | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | -note: required by `Tr` - --> $DIR/defaults-suitability.rs:16:1 - | -LL | trait Tr { - | ^^^^^^^^ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:22:27 | LL | trait Tr2 where Self::Ty: Clone { - | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | -note: required by `Tr2` - --> $DIR/defaults-suitability.rs:22:1 - | -LL | trait Tr2 where Self::Ty: Clone { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | --------------------------^^^^^ + | | | + | | the trait `std::clone::Clone` is not implemented for `NotClone` + | required by `Tr2` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:35:15 | +LL | trait Foo { + | ------------ required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | = help: consider adding a `where T: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` -note: required by `Foo` - --> $DIR/defaults-suitability.rs:34:1 - | -LL | trait Foo { - | ^^^^^^^^^^^^ error[E0277]: the trait bound `(): Foo` is not satisfied --> $DIR/defaults-suitability.rs:41:17 | +LL | trait Bar: Sized { + | ---------------- required by `Bar` +LL | // `(): Foo` might hold for some possible impls but not all. LL | type Assoc: Foo = (); | ^^^^^^^^^ the trait `Foo` is not implemented for `()` - | -note: required by `Bar` - --> $DIR/defaults-suitability.rs:39:1 - | -LL | trait Bar: Sized { - | ^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NotClone: IsU8` is not satisfied --> $DIR/defaults-suitability.rs:61:18 | -LL | Self::Assoc: IsU8, - | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` - | -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, LL | | LL | | Self::Assoc: IsU8, + | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `NotClone` ... | LL | | type Assoc = NotClone; LL | | } - | |_^ + | |_- required by `D` error[E0277]: the trait bound `bool: IsU8` is not satisfied --> $DIR/defaults-suitability.rs:63:11 | -LL | bool: IsU8, - | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` - | -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, LL | | LL | | Self::Assoc: IsU8, +LL | | +LL | | bool: IsU8, + | | ^^^^^^^^^^^^^^^^^ the trait `IsU8` is not implemented for `bool` ... | LL | | type Assoc = NotClone; LL | | } - | |_^ + | |_- required by `D` error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:59:23 | -LL | Vec: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` - | - = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` -note: required by `D` - --> $DIR/defaults-suitability.rs:58:1 - | LL | / trait D where LL | | Vec: Clone, + | | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` LL | | LL | | Self::Assoc: IsU8, ... | LL | | type Assoc = NotClone; LL | | } - | |_^ + | |_- required by `D` + | + = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:74:15 | +LL | trait Foo2 { + | ------------- required by `Foo2` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo2` - --> $DIR/defaults-suitability.rs:73:1 - | -LL | trait Foo2 { - | ^^^^^^^^^^^^^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:83:15 | +LL | trait Foo25 { + | --------------------- required by `Foo25` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` -note: required by `Foo25` - --> $DIR/defaults-suitability.rs:82:1 - | -LL | trait Foo25 { - | ^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:92:16 | -LL | Self::Baz: Clone, - | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` - | - = help: consider adding a `where T: std::clone::Clone` bound -note: required by `Foo3` - --> $DIR/defaults-suitability.rs:90:1 - | LL | / trait Foo3 where LL | | Self::Bar: Clone, LL | | Self::Baz: Clone, + | | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` LL | | ... | LL | | type Baz = T; LL | | } - | |_^ + | |_- required by `Foo3` + | + = help: consider adding a `where T: std::clone::Clone` bound error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/defaults-suitability.rs:29:5 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 0cad08f6752..e8eb085b791 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,57 +1,49 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:23:18 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:27:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:25:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:30:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-1.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:43:9 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 3a57f7df055..a0b5d6b9cbb 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,57 +1,49 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:23:18 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` | = help: consider adding a `where Self: std::marker::Copy` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:27:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:25:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` | = help: consider adding a `where Self: std::ops::Deref` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:30:7 | +LL | trait UncheckedCopy: Sized { + | -------------------------- required by `UncheckedCopy` +... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead = help: consider adding a `where Self: std::fmt::Display` bound -note: required by `UncheckedCopy` - --> $DIR/defaults-unsound-62211-2.rs:20:1 - | -LL | trait UncheckedCopy: Sized { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:43:9 diff --git a/src/test/ui/associated-types/issue-43924.stderr b/src/test/ui/associated-types/issue-43924.stderr index 67a963b5013..75a5b3f3551 100644 --- a/src/test/ui/associated-types/issue-43924.stderr +++ b/src/test/ui/associated-types/issue-43924.stderr @@ -1,14 +1,10 @@ error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied --> $DIR/issue-43924.rs:7:15 | +LL | trait Foo { + | -------------------------------- required by `Foo` LL | type Out: Default + ToString + ?Sized = dyn ToString; | ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)` - | -note: required by `Foo` - --> $DIR/issue-43924.rs:6:1 - | -LL | trait Foo { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied --> $DIR/issue-43924.rs:10:6 diff --git a/src/test/ui/associated-types/issue-54182-1.rs b/src/test/ui/associated-types/issue-54182-1.rs index 3e10f3fb7df..1a1e98cbac2 100644 --- a/src/test/ui/associated-types/issue-54182-1.rs +++ b/src/test/ui/associated-types/issue-54182-1.rs @@ -21,12 +21,12 @@ macro_rules! overload { } fn main() { - let r: () = overload!(42, true); + let () = overload!(42, true); let r: f32 = overload!("Hello world", 13.0); assert_eq!(r, 13.0); - let r: () = overload!(42, true, 42.5); + let () = overload!(42, true, 42.5); let r: i32 = overload!("Hello world", 13.0, 42); assert_eq!(r, 42); diff --git a/src/test/ui/associated-types/issue-63593.rs b/src/test/ui/associated-types/issue-63593.rs index 1452467f373..8dbc24c0673 100644 --- a/src/test/ui/associated-types/issue-63593.rs +++ b/src/test/ui/associated-types/issue-63593.rs @@ -9,3 +9,5 @@ trait MyTrait { type This = Self; //~ error: size for values of type `Self` cannot be known fn something>(i: I); } + +fn main() {} diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index ea462eac9b4..37dd52980d9 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -1,23 +1,15 @@ -error[E0601]: `main` function not found in crate `issue_63593` - | - = note: consider adding a `main` function to `$DIR/issue-63593.rs` - error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/issue-63593.rs:9:5 | +LL | trait MyTrait { + | ------------- required by `MyTrait` LL | type This = Self; | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit = help: consider adding a `where Self: std::marker::Sized` bound -note: required by `MyTrait` - --> $DIR/issue-63593.rs:8:1 - | -LL | trait MyTrait { - | ^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to previous error -Some errors have detailed explanations: E0277, E0601. -For more information about an error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0277`. From 3f03d95bb0e7d2421e1809aa1d69c9c38871092f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 17:31:40 +0200 Subject: [PATCH 0399/1250] Improve associated-types-overridden-default.rs Check that the resulting assoc. types are as expected --- .../associated-types/associated-types-overridden-default.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/ui/associated-types/associated-types-overridden-default.rs b/src/test/ui/associated-types/associated-types-overridden-default.rs index 72c30df0b3d..3e12c922896 100644 --- a/src/test/ui/associated-types/associated-types-overridden-default.rs +++ b/src/test/ui/associated-types/associated-types-overridden-default.rs @@ -16,4 +16,7 @@ impl Tr for () { type Assoc = (); } -fn main() {} +fn main() { + let _: <() as Tr>::Assoc = (); + let _: <() as Tr>::Assoc2 = (); +} From f40879408cb055fc078912ca226ac0a41ddb61ce Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 17:59:37 +0200 Subject: [PATCH 0400/1250] Improve defaults-in-other-trait-items-pass --- .../defaults-in-other-trait-items-pass.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs index 618a2038507..a3bfcd8efe2 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs +++ b/src/test/ui/associated-types/defaults-in-other-trait-items-pass.rs @@ -13,10 +13,25 @@ impl Tr for u16 { type Item = u16; } +impl Tr for String { + type Container = String; +} + +impl Tr for usize { + type Item = u32; + type Container = Vec<()>; +} + fn main() { let _container: <() as Tr>::Container = Vec::::new(); let _item: <() as Tr>::Item = 0u8; let _container: ::Container = Vec::::new(); let _item: ::Item = 0u16; + + let _container: ::Container = String::new(); + let _item: ::Item = 0u8; + + let _container: ::Container = Vec::<()>::new(); + let _item: ::Item = 0u32; } From fbcd136b655c2743d3a8c3aa87e460ac38d57046 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 01:18:37 +0200 Subject: [PATCH 0401/1250] Improve the cycle tests --- ...clic-fail.rs => defaults-cyclic-fail-1.rs} | 16 +++++- .../defaults-cyclic-fail-1.stderr | 33 +++++++++++ .../defaults-cyclic-fail-2.rs | 49 ++++++++++++++++ .../defaults-cyclic-fail-2.stderr | 33 +++++++++++ .../defaults-cyclic-fail.stderr | 21 ------- .../defaults-cyclic-pass-1.rs | 56 +++++++++++++++++++ .../defaults-cyclic-pass-2.rs | 56 +++++++++++++++++++ .../associated-types/defaults-cyclic-pass.rs | 17 ------ 8 files changed, 240 insertions(+), 41 deletions(-) rename src/test/ui/associated-types/{defaults-cyclic-fail.rs => defaults-cyclic-fail-1.rs} (65%) create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-1.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-2.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-fail-2.stderr delete mode 100644 src/test/ui/associated-types/defaults-cyclic-fail.stderr create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass-1.rs create mode 100644 src/test/ui/associated-types/defaults-cyclic-pass-2.rs delete mode 100644 src/test/ui/associated-types/defaults-cyclic-pass.rs diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.rs b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs similarity index 65% rename from src/test/ui/associated-types/defaults-cyclic-fail.rs rename to src/test/ui/associated-types/defaults-cyclic-fail-1.rs index ab66fe0b52e..71ac914ef57 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.rs @@ -15,6 +15,10 @@ impl Tr for u8 { type A = u8; } +impl Tr for u16 { + type B = (); +} + impl Tr for u32 { type A = (); type B = u8; @@ -28,8 +32,14 @@ impl Tr for bool { } // (the error is shown twice for some reason) +impl Tr for usize { +//~^ ERROR overflow evaluating the requirement + type B = &'static Self::A; + //~^ ERROR overflow evaluating the requirement +} + fn main() { - // Check that the overridden type propagates to the other - let _a: ::A = 0u8; - let _b: ::B = 0u8; + // We don't check that the types project correctly because the cycle errors stop compilation + // before `main` is type-checked. + // `defaults-cyclic-pass-1.rs` does this. } diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr new file mode 100644 index 00000000000..4f28a50701a --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -0,0 +1,33 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail-1.rs:12:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:30:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:37:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-1.rs:32:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-1.rs:39:5 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs new file mode 100644 index 00000000000..2f2e84c6000 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -0,0 +1,49 @@ +// compile-fail + +#![feature(associated_type_defaults)] + +// A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults. + +// Having a cycle in assoc. type defaults is okay... +trait Tr { + type A = Vec; + type B = Box; +} + +// ...but is an error in any impl that doesn't override at least one of the defaults +impl Tr for () {} +//~^ ERROR overflow evaluating the requirement + +// As soon as at least one is redefined, it works: +impl Tr for u8 { + type A = u8; +} + +impl Tr for u16 { + type B = (); +} + +impl Tr for u32 { + type A = (); + type B = u8; +} + +// ...but only if this actually breaks the cycle +impl Tr for bool { +//~^ ERROR overflow evaluating the requirement + type A = Box; + //~^ ERROR overflow evaluating the requirement +} +// (the error is shown twice for some reason) + +impl Tr for usize { +//~^ ERROR overflow evaluating the requirement + type B = &'static Self::A; + //~^ ERROR overflow evaluating the requirement +} + +fn main() { + // We don't check that the types project correctly because the cycle errors stop compilation + // before `main` is type-checked. + // `defaults-cyclic-pass-2.rs` does this. +} diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr new file mode 100644 index 00000000000..bbc130f11f7 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -0,0 +1,33 @@ +error[E0275]: overflow evaluating the requirement `<() as Tr>::B` + --> $DIR/defaults-cyclic-fail-2.rs:14:6 + | +LL | impl Tr for () {} + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:32:6 + | +LL | impl Tr for bool { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:39:6 + | +LL | impl Tr for usize { + | ^^ + +error[E0275]: overflow evaluating the requirement `::B` + --> $DIR/defaults-cyclic-fail-2.rs:34:5 + | +LL | type A = Box; + | ^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::A` + --> $DIR/defaults-cyclic-fail-2.rs:41:5 + | +LL | type B = &'static Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail.stderr b/src/test/ui/associated-types/defaults-cyclic-fail.stderr deleted file mode 100644 index dd0e5c2ef42..00000000000 --- a/src/test/ui/associated-types/defaults-cyclic-fail.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail.rs:10:6 - | -LL | impl Tr for () {} - | ^^ - -error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail.rs:24:6 - | -LL | impl Tr for bool { - | ^^ - -error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail.rs:26:5 - | -LL | type A = Box; - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0275`. diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-1.rs b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs new file mode 100644 index 00000000000..97c6e5bade2 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass-1.rs @@ -0,0 +1,56 @@ +// check-pass + +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay, as long as there's no impl +// that retains it. +trait Tr { + type A = Self::B; + type B = Self::A; + + fn f(); +} + +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = 0u8; + let _: Self::B = 0u8; + } +} + +impl Tr for String { + type B = (); + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = (); + let _: Self::B = (); + } +} + +impl Tr for () { + type A = Vec<()>; + type B = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = 0u8; + } +} + +fn main() { + // Check that both impls now have the right types (seen from outside the impls) + let _: ::A = 0u8; + let _: ::B = 0u8; + + let _: ::A = (); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-pass-2.rs b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs new file mode 100644 index 00000000000..69315a02210 --- /dev/null +++ b/src/test/ui/associated-types/defaults-cyclic-pass-2.rs @@ -0,0 +1,56 @@ +// check-pass + +#![feature(associated_type_defaults)] + +// Having a cycle in assoc. type defaults is okay, as long as there's no impl +// that retains it. +trait Tr { + type A = Vec; + type B = Box; + + fn f(); +} + +// An impl has to break the cycle to be accepted. +impl Tr for u8 { + type A = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = 0u8; + let _: Self::B = Box::new(0u8); + } +} + +impl Tr for String { + type B = (); + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = (); + } +} + +impl Tr for () { + type A = Vec<()>; + type B = u8; + + fn f() { + // Check that the type propagates as expected (seen from inside the impl) + let _: Self::A = Vec::<()>::new(); + let _: Self::B = 0u8; + } +} + +fn main() { + // Check that both impls now have the right types (seen from outside the impls) + let _: ::A = 0u8; + let _: ::B = Box::new(0u8); + + let _: ::A = Vec::<()>::new(); + let _: ::B = (); + + let _: <() as Tr>::A = Vec::<()>::new(); + let _: <() as Tr>::B = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-cyclic-pass.rs b/src/test/ui/associated-types/defaults-cyclic-pass.rs deleted file mode 100644 index 74a0cfa6b73..00000000000 --- a/src/test/ui/associated-types/defaults-cyclic-pass.rs +++ /dev/null @@ -1,17 +0,0 @@ -// check-pass - -#![feature(associated_type_defaults)] - -// Having a cycle in assoc. type defaults is okay, as long as there's no impl -// that retains it. -trait Tr { - type A = Self::B; - type B = Self::A; -} - -// An impl has to break the cycle to be accepted. -impl Tr for u8 { - type A = u8; -} - -fn main() {} From c8da9ee50af722385e673e79c466fb3abcb75697 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 22:02:44 +0200 Subject: [PATCH 0402/1250] Improve specialization test --- .../defaults-specialization.rs | 36 ++++++++++- .../defaults-specialization.stderr | 61 ++++++++++++++++--- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index e3a5db0960c..833981fc8e3 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -7,7 +7,10 @@ trait Tr { type Ty = u8; - fn make() -> Self::Ty; + fn make() -> Self::Ty { + 0u8 + //~^ error: mismatched types + } } struct A(T); @@ -61,4 +64,33 @@ impl Tr for D { fn make() -> u8 { 255 } } -fn main() {} +struct E(T); +impl Tr for E { + default fn make() -> Self::Ty { panic!(); } +} + +// This impl specializes and sets `Ty`, it can rely on `Ty=String`. +impl Tr for E { + type Ty = String; + + fn make() -> String { String::new() } +} + +fn main() { + // Test that we can assume the right set of assoc. types from outside the impl + + // This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait. + // cf. https://github.com/rust-lang/rust/issues/48515 + //let _: as Tr>::Ty = 0u8; + //let _: as Tr>::Ty = 0u8; + + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + let _: as Tr>::Ty = 0u8; //~ error: mismatched types + let _: as Tr>::Ty = true; //~ error: mismatched types + + let _: as Tr>::Ty = true; + + let _: as Tr>::Ty = 0u8; + let _: as Tr>::Ty = 0u8; +} diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 2b2adfdb7c9..bd0fd7166f6 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,7 +1,7 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:17:18 + --> $DIR/defaults-specialization.rs:20:18 | -LL | fn make() -> Self::Ty; +LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> u8 { 0 } @@ -11,9 +11,9 @@ LL | fn make() -> u8 { 0 } found type `fn() -> u8` error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:33:18 + --> $DIR/defaults-specialization.rs:36:18 | -LL | fn make() -> Self::Ty; +LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> bool { true } @@ -23,7 +23,18 @@ LL | fn make() -> bool { true } found type `fn() -> bool` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:24:29 + --> $DIR/defaults-specialization.rs:11:9 + | +LL | fn make() -> Self::Ty { + | -------- expected `::Ty` because of return type +LL | 0u8 + | ^^^ expected associated type, found u8 + | + = note: expected type `::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:27:29 | LL | fn make() -> Self::Ty { 0u8 } | -------- ^^^ expected associated type, found u8 @@ -34,7 +45,7 @@ LL | fn make() -> Self::Ty { 0u8 } found type `u8` error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:42:29 + --> $DIR/defaults-specialization.rs:45:29 | LL | fn make() -> Self::Ty { true } | -------- ^^^^ expected associated type, found bool @@ -44,7 +55,43 @@ LL | fn make() -> Self::Ty { true } = note: expected type ` as Tr>::Ty` found type `bool` -error: aborting due to 4 previous errors +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:87:32 + | +LL | let _: as Tr>::Ty = 0u8; + | ^^^ expected associated type, found u8 + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:88:32 + | +LL | let _: as Tr>::Ty = true; + | ^^^^ expected associated type, found bool + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:89:33 + | +LL | let _: as Tr>::Ty = 0u8; + | ^^^ expected associated type, found u8 + | + = note: expected type ` as Tr>::Ty` + found type `u8` + +error[E0308]: mismatched types + --> $DIR/defaults-specialization.rs:90:33 + | +LL | let _: as Tr>::Ty = true; + | ^^^^ expected associated type, found bool + | + = note: expected type ` as Tr>::Ty` + found type `bool` + +error: aborting due to 9 previous errors Some errors have detailed explanations: E0053, E0308. For more information about an error, try `rustc --explain E0053`. From 24ec364713daad4f5014a0921c3dbc1b59ade1ac Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Sep 2019 22:07:01 +0200 Subject: [PATCH 0403/1250] Test mixed default and non-default --- .../ui/associated-types/defaults-mixed.rs | 36 +++++++++++++++++++ .../ui/associated-types/defaults-mixed.stderr | 21 +++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/test/ui/associated-types/defaults-mixed.rs create mode 100644 src/test/ui/associated-types/defaults-mixed.stderr diff --git a/src/test/ui/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs new file mode 100644 index 00000000000..7601ab71e4a --- /dev/null +++ b/src/test/ui/associated-types/defaults-mixed.rs @@ -0,0 +1,36 @@ +// compile-fail + +#![feature(associated_type_defaults)] + +// Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly. + +trait Trait { + type Foo = u8; + type Bar; +} + +// `Bar` must be specified +impl Trait for () {} +//~^ error: not all trait items implemented, missing: `Bar` + +impl Trait for bool { +//~^ error: not all trait items implemented, missing: `Bar` + type Foo = (); +} + +impl Trait for u8 { + type Bar = (); +} + +impl Trait for u16 { + type Foo = String; + type Bar = bool; +} + +fn main() { + let _: ::Foo = 0u8; + let _: ::Bar = (); + + let _: ::Foo = String::new(); + let _: ::Bar = true; +} diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr new file mode 100644 index 00000000000..2d31d1dbdfe --- /dev/null +++ b/src/test/ui/associated-types/defaults-mixed.stderr @@ -0,0 +1,21 @@ +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:13:1 + | +LL | type Bar; + | --------- `Bar` from trait +... +LL | impl Trait for () {} + | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error[E0046]: not all trait items implemented, missing: `Bar` + --> $DIR/defaults-mixed.rs:16:1 + | +LL | type Bar; + | --------- `Bar` from trait +... +LL | impl Trait for bool { + | ^^^^^^^^^^^^^^^^^^^ missing `Bar` in implementation + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0046`. From f94eaeaf736e19b9249eb690a381202bcc5065b3 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Tue, 8 Oct 2019 01:14:45 +0200 Subject: [PATCH 0404/1250] Fix rebase damage --- src/librustc_typeck/check/wfcheck.rs | 2 +- .../defaults-in-other-trait-items.rs | 4 +- .../defaults-in-other-trait-items.stderr | 2 +- .../defaults-specialization.rs | 1 + .../defaults-specialization.stderr | 80 ++++++++++++------- .../defaults-suitability.stderr | 22 ++--- .../defaults-unsound-62211-1.stderr | 28 +++---- .../defaults-unsound-62211-2.stderr | 28 +++---- .../ui/associated-types/issue-26681.stderr | 6 +- .../ui/associated-types/issue-63593.stderr | 1 - 10 files changed, 95 insertions(+), 79 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e39beb547d1..a6189a34664 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -496,7 +496,7 @@ fn check_associated_type_defaults( } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - match t.sty { + match t.kind { ty::Projection(proj_ty) => { if let Some(default) = self.map.get(&proj_ty) { default diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.rs b/src/test/ui/associated-types/defaults-in-other-trait-items.rs index 0455997b168..9f2e8aca477 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.rs +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.rs @@ -10,7 +10,7 @@ trait Tr { //~^ ERROR mismatched types //~| NOTE expected associated type, found `()` //~| NOTE expected associated type `::A` - //~| NOTE consider constraining + //~| NOTE consider constraining the associated type //~| NOTE for more information, visit } } @@ -38,7 +38,7 @@ trait AssocConst { //~^ ERROR mismatched types //~| NOTE expected associated type, found `u8` //~| NOTE expected associated type `::Ty` - //~| NOTE consider constraining + //~| NOTE consider constraining the associated type //~| NOTE for more information, visit } diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr index 9ecfe49c2b5..b759276d248 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -10,7 +10,7 @@ LL | let () = p; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-in-other-trait-items.rs:37:25 + --> $DIR/defaults-in-other-trait-items.rs:39:25 | LL | const C: Self::Ty = 0u8; | ^^^ expected associated type, found `u8` diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index 833981fc8e3..cb0d231bfcd 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -66,6 +66,7 @@ impl Tr for D { struct E(T); impl Tr for E { + default type Ty = bool; default fn make() -> Self::Ty { panic!(); } } diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index bd0fd7166f6..9b10940cbc4 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -5,10 +5,12 @@ LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> u8 { 0 } - | ^^ expected associated type, found u8 + | ^^ expected associated type, found `u8` | - = note: expected type `fn() -> as Tr>::Ty` - found type `fn() -> u8` + = note: expected fn pointer `fn() -> as Tr>::Ty` + found fn pointer `fn() -> u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0053]: method `make` has an incompatible type for trait --> $DIR/defaults-specialization.rs:36:18 @@ -17,10 +19,12 @@ LL | fn make() -> Self::Ty { | -------- type in trait ... LL | fn make() -> bool { true } - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type `fn() -> as Tr>::Ty` - found type `fn() -> bool` + = note: expected fn pointer `fn() -> as Tr>::Ty` + found fn pointer `fn() -> bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:11:9 @@ -28,68 +32,82 @@ error[E0308]: mismatched types LL | fn make() -> Self::Ty { | -------- expected `::Ty` because of return type LL | 0u8 - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type `::Ty` - found type `u8` + = note: expected associated type `::Ty` + found type `u8` + = note: consider constraining the associated type `::Ty` to `u8` or calling a method that returns `::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:27:29 | LL | fn make() -> Self::Ty { 0u8 } - | -------- ^^^ expected associated type, found u8 + | -------- ^^^ expected associated type, found `u8` | | | expected ` as Tr>::Ty` because of return type | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:45:29 | LL | fn make() -> Self::Ty { true } - | -------- ^^^^ expected associated type, found bool + | -------- ^^^^ expected associated type, found `bool` | | | expected ` as Tr>::Ty` because of return type | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:87:32 + --> $DIR/defaults-specialization.rs:88:32 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:88:32 + --> $DIR/defaults-specialization.rs:89:32 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:89:33 + --> $DIR/defaults-specialization.rs:90:33 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found u8 + | ^^^ expected associated type, found `u8` | - = note: expected type ` as Tr>::Ty` - found type `u8` + = note: expected associated type ` as Tr>::Ty` + found type `u8` + = note: consider constraining the associated type ` as Tr>::Ty` to `u8` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:90:33 + --> $DIR/defaults-specialization.rs:91:33 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found bool + | ^^^^ expected associated type, found `bool` | - = note: expected type ` as Tr>::Ty` - found type `bool` + = note: expected associated type ` as Tr>::Ty` + found type `bool` + = note: consider constraining the associated type ` as Tr>::Ty` to `bool` or calling a method that returns ` as Tr>::Ty` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to 9 previous errors diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index dd45c9e4436..861f178fd19 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -19,11 +19,13 @@ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:35:15 | LL | trait Foo { - | ------------ required by `Foo` + | ------------ + | | | + | | help: consider restricting this bound: `T: std::clone::Clone` + | required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | - = help: consider adding a `where T: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `(): Foo` is not satisfied @@ -82,22 +84,24 @@ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not --> $DIR/defaults-suitability.rs:74:15 | LL | trait Foo2 { - | ------------- required by `Foo2` + | -------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` + | | + | required by `Foo2` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:83:15 | LL | trait Foo25 { - | --------------------- required by `Foo25` + | ---------------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` + | | + | required by `Foo25` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | - = help: consider adding a `where >::Baz: std::clone::Clone` bound = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied @@ -106,14 +110,14 @@ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied LL | / trait Foo3 where LL | | Self::Bar: Clone, LL | | Self::Baz: Clone, - | | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` + | | ^^^^^ - help: consider further restricting type parameter `T`: `, T: std::clone::Clone` + | | | + | | the trait `std::clone::Clone` is not implemented for `T` LL | | ... | LL | | type Baz = T; LL | | } | |_- required by `Foo3` - | - = help: consider adding a `where T: std::clone::Clone` bound error[E0277]: the size for values of type `[u8]` cannot be known at compilation time --> $DIR/defaults-suitability.rs:29:5 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index e8eb085b791..35164c4f3d3 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -6,8 +6,6 @@ LL | trait UncheckedCopy: Sized { ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` - | - = help: consider adding a `where Self: std::marker::Copy` bound error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:27:7 @@ -19,7 +17,6 @@ LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` - = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:25:7 @@ -29,8 +26,6 @@ LL | trait UncheckedCopy: Sized { ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` - | - = help: consider adding a `where Self: std::ops::Deref` bound error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:30:7 @@ -43,42 +38,43 @@ LL | + Display = Self; | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = help: consider adding a `where Self: std::fmt::Display` bound error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | | + | help: consider restricting this bound: `T: std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `T` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | - = help: consider adding a `where T: std::ops::Deref` bound + | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::ops::Deref` error[E0277]: cannot add-assign `&'static str` to `T` --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | | + | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` - = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound + | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::marker::Copy` error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index a0b5d6b9cbb..af66ee117a3 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -6,8 +6,6 @@ LL | trait UncheckedCopy: Sized { ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` - | - = help: consider adding a `where Self: std::marker::Copy` bound error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:27:7 @@ -19,7 +17,6 @@ LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` - = help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:25:7 @@ -29,8 +26,6 @@ LL | trait UncheckedCopy: Sized { ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` - | - = help: consider adding a `where Self: std::ops::Deref` bound error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:30:7 @@ -43,42 +38,43 @@ LL | + Display = Self; | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = help: consider adding a `where Self: std::fmt::Display` bound error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter + | | + | help: consider restricting this bound: `T: std::fmt::Display` | = help: the trait `std::fmt::Display` is not implemented for `T` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead - = help: consider adding a `where T: std::fmt::Display` bound error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | - = help: consider adding a `where T: std::ops::Deref` bound + | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::ops::Deref` error[E0277]: cannot add-assign `&'static str` to `T` --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` + | | + | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` - = help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:43:9 | LL | impl UncheckedCopy for T {} - | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | - = help: consider adding a `where T: std::marker::Copy` bound + | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | | + | help: consider restricting this bound: `T: std::marker::Copy` error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/issue-26681.stderr b/src/test/ui/associated-types/issue-26681.stderr index 27175a247fa..da10933df92 100644 --- a/src/test/ui/associated-types/issue-26681.stderr +++ b/src/test/ui/associated-types/issue-26681.stderr @@ -4,8 +4,10 @@ error[E0308]: mismatched types LL | const C: ::Bar = 6665; | ^^^^ expected associated type, found integer | - = note: expected type `<::Fv as Foo>::Bar` - found type `{integer}` + = note: expected associated type `<::Fv as Foo>::Bar` + found type `{integer}` + = note: consider constraining the associated type `<::Fv as Foo>::Bar` to `{integer}` or calling a method that returns `<::Fv as Foo>::Bar` + = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error: aborting due to previous error diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index 37dd52980d9..c27800f5a3f 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -8,7 +8,6 @@ LL | type This = Self; | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit - = help: consider adding a `where Self: std::marker::Sized` bound error: aborting due to previous error From 708f053807a0844d8d772d14a9d636b232ec5f90 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 24 Nov 2019 16:39:04 +0100 Subject: [PATCH 0405/1250] Add test for #65774 Closes #65774 --- src/test/ui/associated-types/issue-65774-1.rs | 57 +++++++++++++++++++ .../ui/associated-types/issue-65774-1.stderr | 17 ++++++ src/test/ui/associated-types/issue-65774-2.rs | 57 +++++++++++++++++++ .../ui/associated-types/issue-65774-2.stderr | 17 ++++++ 4 files changed, 148 insertions(+) create mode 100644 src/test/ui/associated-types/issue-65774-1.rs create mode 100644 src/test/ui/associated-types/issue-65774-1.stderr create mode 100644 src/test/ui/associated-types/issue-65774-2.rs create mode 100644 src/test/ui/associated-types/issue-65774-2.stderr diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs new file mode 100644 index 00000000000..e087da5d0ef --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -0,0 +1,57 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } +//~^ ERROR the trait bound `T: MyDisplay` is not satisfied + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + // writer.my_write(valref) + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + closure(valref); + } +} + +fn create() -> &'static dyn ProcessType { + let input: Option<&mut Process> = None; + let process: &mut Process = input.unwrap(); + process +} + +pub fn main() { + create(); +} diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr new file mode 100644 index 00000000000..559136be705 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-1.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-1.rs:10:21 + | +LL | trait MPU { + | --------- required by `MPU` +LL | type MpuConfig: MyDisplay = T; + | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-1.rs:16:6 + | +LL | impl MPU for S { } + | ^^^ the trait `MyDisplay` is not implemented for `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs new file mode 100644 index 00000000000..fba41fc0af7 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -0,0 +1,57 @@ +#![feature(associated_type_defaults)] + +trait MyDisplay { fn method(&self) { } } + +impl<'a, T: MyDisplay> MyDisplay for &'a mut T { } + +struct T; + +trait MPU { + type MpuConfig: MyDisplay = T; + //~^ ERROR the trait bound `T: MyDisplay` is not satisfied +} + +struct S; + +impl MPU for S { } +//~^ ERROR the trait bound `T: MyDisplay` is not satisfied + +trait MyWrite { + fn my_write(&self, _: &dyn MyDisplay) { } +} + +trait ProcessType { + fn process_detail_fmt(&self, _: &mut dyn MyWrite); +} + +struct Process; + +impl ProcessType for Process { + fn process_detail_fmt(&self, writer: &mut dyn MyWrite) + { + + let mut val: Option<::MpuConfig> = None; + let valref: &mut ::MpuConfig = val.as_mut().unwrap(); + + // // This causes a different ICE (but its similar if you squint right): + // // + // // `Unimplemented` selecting `Binder()` during codegen + // + writer.my_write(valref) + + // This one causes the ICE: + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + /*let closure = |config: &mut ::MpuConfig| writer.my_write(&config); + closure(valref);*/ + } +} + +fn create() -> &'static dyn ProcessType { + let input: Option<&mut Process> = None; + let process: &mut Process = input.unwrap(); + process +} + +pub fn main() { + create(); +} diff --git a/src/test/ui/associated-types/issue-65774-2.stderr b/src/test/ui/associated-types/issue-65774-2.stderr new file mode 100644 index 00000000000..cb515964226 --- /dev/null +++ b/src/test/ui/associated-types/issue-65774-2.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-2.rs:10:21 + | +LL | trait MPU { + | --------- required by `MPU` +LL | type MpuConfig: MyDisplay = T; + | ^^^^^^^^^ the trait `MyDisplay` is not implemented for `T` + +error[E0277]: the trait bound `T: MyDisplay` is not satisfied + --> $DIR/issue-65774-2.rs:16:6 + | +LL | impl MPU for S { } + | ^^^ the trait `MyDisplay` is not implemented for `T` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. From a01846f0c37d705f527e39dbeac3f886d72c1a50 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 24 Nov 2019 17:08:48 +0100 Subject: [PATCH 0406/1250] appease tidy --- src/test/ui/associated-types/issue-65774-1.rs | 3 ++- src/test/ui/associated-types/issue-65774-2.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/ui/associated-types/issue-65774-1.rs b/src/test/ui/associated-types/issue-65774-1.rs index e087da5d0ef..0ffd6cc2cf2 100644 --- a/src/test/ui/associated-types/issue-65774-1.rs +++ b/src/test/ui/associated-types/issue-65774-1.rs @@ -40,7 +40,8 @@ impl ProcessType for Process { // writer.my_write(valref) // This one causes the ICE: - // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) let closure = |config: &mut ::MpuConfig| writer.my_write(&config); closure(valref); } diff --git a/src/test/ui/associated-types/issue-65774-2.rs b/src/test/ui/associated-types/issue-65774-2.rs index fba41fc0af7..31e203a81d3 100644 --- a/src/test/ui/associated-types/issue-65774-2.rs +++ b/src/test/ui/associated-types/issue-65774-2.rs @@ -40,7 +40,8 @@ impl ProcessType for Process { writer.my_write(valref) // This one causes the ICE: - // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), depth=1),Unimplemented) + // FulfillmentError(Obligation(predicate=Binder(TraitPredicate()), + // depth=1),Unimplemented) /*let closure = |config: &mut ::MpuConfig| writer.my_write(&config); closure(valref);*/ } From ec501903994911892bb43c388564326b70b7104b Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Dec 2019 13:34:52 +0100 Subject: [PATCH 0407/1250] Bless test output --- .../defaults-specialization.stderr | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 9b10940cbc4..15146d1a9c0 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -69,7 +69,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:88:32 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found `u8` + | ----------------- ^^^ expected associated type, found `u8` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `u8` @@ -80,7 +82,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:89:32 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found `bool` + | ----------------- ^^^^ expected associated type, found `bool` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `bool` @@ -91,7 +95,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:90:33 | LL | let _: as Tr>::Ty = 0u8; - | ^^^ expected associated type, found `u8` + | ------------------ ^^^ expected associated type, found `u8` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `u8` @@ -102,7 +108,9 @@ error[E0308]: mismatched types --> $DIR/defaults-specialization.rs:91:33 | LL | let _: as Tr>::Ty = true; - | ^^^^ expected associated type, found `bool` + | ------------------ ^^^^ expected associated type, found `bool` + | | + | expected due to this | = note: expected associated type ` as Tr>::Ty` found type `bool` From 232c1f331c8703f6484e29b8da1cec9bb67f443e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 5 Jan 2020 01:04:18 +0100 Subject: [PATCH 0408/1250] Format code --- src/librustc_typeck/check/wfcheck.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index a6189a34664..b2169413f46 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -435,23 +435,18 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { /// /// Assuming the defaults are used, check that all predicates (bounds on the /// assoc type and where clauses on the trait) hold. -fn check_associated_type_defaults( - fcx: &FnCtxt<'_, '_>, - trait_def_id: DefId, -) { +fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { let tcx = fcx.tcx; let substs = InternalSubsts::identity_for_item(tcx, trait_def_id); // For all assoc. types with defaults, build a map from // `>::Assoc` to the default type. - let map = tcx.associated_items(trait_def_id) + let map = tcx + .associated_items(trait_def_id) .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` - let proj = ty::ProjectionTy { - substs, - item_def_id: item.def_id, - }; + let proj = ty::ProjectionTy { substs, item_def_id: item.def_id }; let default_ty = tcx.type_of(item.def_id); debug!("assoc. type default mapping: {} -> {}", proj, default_ty); Some((proj, default_ty)) From 9930e1ff0a889631f853a31838121600cea2b400 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 5 Jan 2020 02:12:16 +0100 Subject: [PATCH 0409/1250] Fix tests that fail with `--emit metadata` --- .../ui/associated-const/defaults-cyclic-fail.rs | 4 ++-- .../associated-const/defaults-cyclic-fail.stderr | 14 ++++++++++++-- .../associated-const/defaults-not-assumed-fail.rs | 2 +- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.rs b/src/test/ui/associated-const/defaults-cyclic-fail.rs index 0f54d67574d..9b899ee316a 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.rs +++ b/src/test/ui/associated-const/defaults-cyclic-fail.rs @@ -1,9 +1,9 @@ -// compile-fail +// build-fail // Cyclic assoc. const defaults don't error unless *used* trait Tr { const A: u8 = Self::B; - //~^ ERROR cycle detected when const-evaluating `Tr::A` + //~^ ERROR cycle detected when const-evaluating + checking `Tr::A` const B: u8 = Self::A; } diff --git a/src/test/ui/associated-const/defaults-cyclic-fail.stderr b/src/test/ui/associated-const/defaults-cyclic-fail.stderr index dee4620cdf6..940182d4aa6 100644 --- a/src/test/ui/associated-const/defaults-cyclic-fail.stderr +++ b/src/test/ui/associated-const/defaults-cyclic-fail.stderr @@ -1,15 +1,25 @@ -error[E0391]: cycle detected when const-evaluating `Tr::A` +error[E0391]: cycle detected when const-evaluating + checking `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:5 + | +LL | const A: u8 = Self::B; + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating `Tr::A`... --> $DIR/defaults-cyclic-fail.rs:5:19 | LL | const A: u8 = Self::B; | ^^^^^^^ +note: ...which requires const-evaluating + checking `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:5 | +LL | const B: u8 = Self::A; + | ^^^^^^^^^^^^^^^^^^^^^^ note: ...which requires const-evaluating `Tr::B`... --> $DIR/defaults-cyclic-fail.rs:8:19 | LL | const B: u8 = Self::A; | ^^^^^^^ - = note: ...which again requires const-evaluating `Tr::A`, completing the cycle + = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle note: cycle used when const-evaluating `main` --> $DIR/defaults-cyclic-fail.rs:16:16 | diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs index 27435ef34a0..5a0704231ad 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -1,4 +1,4 @@ -// compile-fail +// build-fail trait Tr { const A: u8 = 255; From 4d4da926f2633de5da22e2aef7f693c3505aa206 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 15 Feb 2020 12:33:39 +0100 Subject: [PATCH 0410/1250] Fix rebase damage --- src/librustc_typeck/check/wfcheck.rs | 1 + .../defaults-not-assumed-fail.rs | 1 + .../defaults-not-assumed-fail.stderr | 12 ++++- .../defaults-cyclic-fail-1.stderr | 10 ++-- .../defaults-cyclic-fail-2.rs | 2 - .../defaults-cyclic-fail-2.stderr | 10 ++-- .../defaults-in-other-trait-items.stderr | 2 +- .../ui/associated-types/defaults-mixed.rs | 2 - .../ui/associated-types/defaults-mixed.stderr | 4 +- .../defaults-specialization.rs | 2 - .../defaults-specialization.stderr | 18 +++---- .../associated-types/defaults-suitability.rs | 2 - .../defaults-suitability.stderr | 42 ++++++++------- .../defaults-unsound-62211-1.rs | 2 - .../defaults-unsound-62211-1.stderr | 54 ++++++++++++------- .../defaults-unsound-62211-2.rs | 2 - .../defaults-unsound-62211-2.stderr | 54 ++++++++++++------- 17 files changed, 126 insertions(+), 94 deletions(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index b2169413f46..58820dcb381 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -443,6 +443,7 @@ fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { // `>::Assoc` to the default type. let map = tcx .associated_items(trait_def_id) + .iter() .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.rs b/src/test/ui/associated-const/defaults-not-assumed-fail.rs index 5a0704231ad..d7a48cbd63e 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.rs +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.rs @@ -32,6 +32,7 @@ fn main() { assert_eq!(<() as Tr>::A, 255); assert_eq!(<() as Tr>::B, 0); // causes the error above //~^ ERROR evaluation of constant expression failed + //~| ERROR erroneous constant used assert_eq!(::A, 254); assert_eq!(::B, 255); diff --git a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr index 365ad322410..fe3721a9109 100644 --- a/src/test/ui/associated-const/defaults-not-assumed-fail.stderr +++ b/src/test/ui/associated-const/defaults-not-assumed-fail.stderr @@ -16,8 +16,16 @@ LL | assert_eq!(<() as Tr>::B, 0); // causes the error above | | | referenced constant has errors | - = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 2 previous errors +error: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr index 4f28a50701a..6a8526f6aad 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-1.stderr @@ -1,29 +1,29 @@ error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail-1.rs:12:6 + --> $DIR/defaults-cyclic-fail-1.rs:10:6 | LL | impl Tr for () {} | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:30:6 + --> $DIR/defaults-cyclic-fail-1.rs:28:6 | LL | impl Tr for bool { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:37:6 + --> $DIR/defaults-cyclic-fail-1.rs:35:6 | LL | impl Tr for usize { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-1.rs:32:5 + --> $DIR/defaults-cyclic-fail-1.rs:30:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `::A` - --> $DIR/defaults-cyclic-fail-1.rs:39:5 + --> $DIR/defaults-cyclic-fail-1.rs:37:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs index 2f2e84c6000..05091e3f498 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.rs +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.rs @@ -1,5 +1,3 @@ -// compile-fail - #![feature(associated_type_defaults)] // A more complex version of `defaults-cyclic-fail-1.rs`, with non-trivial defaults. diff --git a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr index bbc130f11f7..78772df9638 100644 --- a/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr +++ b/src/test/ui/associated-types/defaults-cyclic-fail-2.stderr @@ -1,29 +1,29 @@ error[E0275]: overflow evaluating the requirement `<() as Tr>::B` - --> $DIR/defaults-cyclic-fail-2.rs:14:6 + --> $DIR/defaults-cyclic-fail-2.rs:12:6 | LL | impl Tr for () {} | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:32:6 + --> $DIR/defaults-cyclic-fail-2.rs:30:6 | LL | impl Tr for bool { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:39:6 + --> $DIR/defaults-cyclic-fail-2.rs:37:6 | LL | impl Tr for usize { | ^^ error[E0275]: overflow evaluating the requirement `::B` - --> $DIR/defaults-cyclic-fail-2.rs:34:5 + --> $DIR/defaults-cyclic-fail-2.rs:32:5 | LL | type A = Box; | ^^^^^^^^^^^^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `::A` - --> $DIR/defaults-cyclic-fail-2.rs:41:5 + --> $DIR/defaults-cyclic-fail-2.rs:39:5 | LL | type B = &'static Self::A; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr index b759276d248..9ecfe49c2b5 100644 --- a/src/test/ui/associated-types/defaults-in-other-trait-items.stderr +++ b/src/test/ui/associated-types/defaults-in-other-trait-items.stderr @@ -10,7 +10,7 @@ LL | let () = p; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-in-other-trait-items.rs:39:25 + --> $DIR/defaults-in-other-trait-items.rs:37:25 | LL | const C: Self::Ty = 0u8; | ^^^ expected associated type, found `u8` diff --git a/src/test/ui/associated-types/defaults-mixed.rs b/src/test/ui/associated-types/defaults-mixed.rs index 7601ab71e4a..c91b8de39f5 100644 --- a/src/test/ui/associated-types/defaults-mixed.rs +++ b/src/test/ui/associated-types/defaults-mixed.rs @@ -1,5 +1,3 @@ -// compile-fail - #![feature(associated_type_defaults)] // Tests that a trait with one defaulted and one non-defaulted assoc. type behaves properly. diff --git a/src/test/ui/associated-types/defaults-mixed.stderr b/src/test/ui/associated-types/defaults-mixed.stderr index 2d31d1dbdfe..69ddd5f2326 100644 --- a/src/test/ui/associated-types/defaults-mixed.stderr +++ b/src/test/ui/associated-types/defaults-mixed.stderr @@ -1,5 +1,5 @@ error[E0046]: not all trait items implemented, missing: `Bar` - --> $DIR/defaults-mixed.rs:13:1 + --> $DIR/defaults-mixed.rs:11:1 | LL | type Bar; | --------- `Bar` from trait @@ -8,7 +8,7 @@ LL | impl Trait for () {} | ^^^^^^^^^^^^^^^^^ missing `Bar` in implementation error[E0046]: not all trait items implemented, missing: `Bar` - --> $DIR/defaults-mixed.rs:16:1 + --> $DIR/defaults-mixed.rs:14:1 | LL | type Bar; | --------- `Bar` from trait diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs index cb0d231bfcd..d0ed718b839 100644 --- a/src/test/ui/associated-types/defaults-specialization.rs +++ b/src/test/ui/associated-types/defaults-specialization.rs @@ -1,7 +1,5 @@ //! Tests the interaction of associated type defaults and specialization. -// compile-fail - #![feature(associated_type_defaults, specialization)] trait Tr { diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr index 15146d1a9c0..1dd536ec636 100644 --- a/src/test/ui/associated-types/defaults-specialization.stderr +++ b/src/test/ui/associated-types/defaults-specialization.stderr @@ -1,5 +1,5 @@ error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:20:18 + --> $DIR/defaults-specialization.rs:18:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -13,7 +13,7 @@ LL | fn make() -> u8 { 0 } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0053]: method `make` has an incompatible type for trait - --> $DIR/defaults-specialization.rs:36:18 + --> $DIR/defaults-specialization.rs:34:18 | LL | fn make() -> Self::Ty { | -------- type in trait @@ -27,7 +27,7 @@ LL | fn make() -> bool { true } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:11:9 + --> $DIR/defaults-specialization.rs:9:9 | LL | fn make() -> Self::Ty { | -------- expected `::Ty` because of return type @@ -40,7 +40,7 @@ LL | 0u8 = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:27:29 + --> $DIR/defaults-specialization.rs:25:29 | LL | fn make() -> Self::Ty { 0u8 } | -------- ^^^ expected associated type, found `u8` @@ -53,7 +53,7 @@ LL | fn make() -> Self::Ty { 0u8 } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:45:29 + --> $DIR/defaults-specialization.rs:43:29 | LL | fn make() -> Self::Ty { true } | -------- ^^^^ expected associated type, found `bool` @@ -66,7 +66,7 @@ LL | fn make() -> Self::Ty { true } = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:88:32 + --> $DIR/defaults-specialization.rs:86:32 | LL | let _: as Tr>::Ty = 0u8; | ----------------- ^^^ expected associated type, found `u8` @@ -79,7 +79,7 @@ LL | let _: as Tr>::Ty = 0u8; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:89:32 + --> $DIR/defaults-specialization.rs:87:32 | LL | let _: as Tr>::Ty = true; | ----------------- ^^^^ expected associated type, found `bool` @@ -92,7 +92,7 @@ LL | let _: as Tr>::Ty = true; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:90:33 + --> $DIR/defaults-specialization.rs:88:33 | LL | let _: as Tr>::Ty = 0u8; | ------------------ ^^^ expected associated type, found `u8` @@ -105,7 +105,7 @@ LL | let _: as Tr>::Ty = 0u8; = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html error[E0308]: mismatched types - --> $DIR/defaults-specialization.rs:91:33 + --> $DIR/defaults-specialization.rs:89:33 | LL | let _: as Tr>::Ty = true; | ------------------ ^^^^ expected associated type, found `bool` diff --git a/src/test/ui/associated-types/defaults-suitability.rs b/src/test/ui/associated-types/defaults-suitability.rs index 5a128e56bcb..2be01cba105 100644 --- a/src/test/ui/associated-types/defaults-suitability.rs +++ b/src/test/ui/associated-types/defaults-suitability.rs @@ -6,8 +6,6 @@ //! (eg. `type Assoc: Clone = NotClone`), and also against where clauses on //! the trait itself when possible -// compile-fail - #![feature(associated_type_defaults)] struct NotClone; diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 861f178fd19..60e1821b300 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:17:14 + --> $DIR/defaults-suitability.rs:15:14 | LL | trait Tr { | -------- required by `Tr` @@ -7,7 +7,7 @@ LL | type Ty: Clone = NotClone; | ^^^^^ the trait `std::clone::Clone` is not implemented for `NotClone` error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:22:27 + --> $DIR/defaults-suitability.rs:20:27 | LL | trait Tr2 where Self::Ty: Clone { | --------------------------^^^^^ @@ -16,20 +16,22 @@ LL | trait Tr2 where Self::Ty: Clone { | required by `Tr2` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:35:15 + --> $DIR/defaults-suitability.rs:33:15 | LL | trait Foo { - | ------------ - | | | - | | help: consider restricting this bound: `T: std::clone::Clone` - | required by `Foo` + | ------------ required by `Foo` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` | +help: consider restricting this type parameter with `T: std::clone::Clone` + --> $DIR/defaults-suitability.rs:32:11 + | +LL | trait Foo { + | ^ = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `(): Foo` is not satisfied - --> $DIR/defaults-suitability.rs:41:17 + --> $DIR/defaults-suitability.rs:39:17 | LL | trait Bar: Sized { | ---------------- required by `Bar` @@ -38,7 +40,7 @@ LL | type Assoc: Foo = (); | ^^^^^^^^^ the trait `Foo` is not implemented for `()` error[E0277]: the trait bound `NotClone: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:61:18 + --> $DIR/defaults-suitability.rs:59:18 | LL | / trait D where LL | | Vec: Clone, @@ -51,7 +53,7 @@ LL | | } | |_- required by `D` error[E0277]: the trait bound `bool: IsU8` is not satisfied - --> $DIR/defaults-suitability.rs:63:11 + --> $DIR/defaults-suitability.rs:61:11 | LL | / trait D where LL | | Vec: Clone, @@ -66,7 +68,7 @@ LL | | } | |_- required by `D` error[E0277]: the trait bound `NotClone: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:59:23 + --> $DIR/defaults-suitability.rs:57:23 | LL | / trait D where LL | | Vec: Clone, @@ -81,7 +83,7 @@ LL | | } = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:74:15 + --> $DIR/defaults-suitability.rs:72:15 | LL | trait Foo2 { | -------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` @@ -93,7 +95,7 @@ LL | type Bar: Clone = Vec; = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:83:15 + --> $DIR/defaults-suitability.rs:81:15 | LL | trait Foo25 { | ---------------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` @@ -105,22 +107,26 @@ LL | type Bar: Clone = Vec; = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied - --> $DIR/defaults-suitability.rs:92:16 + --> $DIR/defaults-suitability.rs:90:16 | LL | / trait Foo3 where LL | | Self::Bar: Clone, LL | | Self::Baz: Clone, - | | ^^^^^ - help: consider further restricting type parameter `T`: `, T: std::clone::Clone` - | | | - | | the trait `std::clone::Clone` is not implemented for `T` + | | ^^^^^ the trait `std::clone::Clone` is not implemented for `T` LL | | ... | LL | | type Baz = T; LL | | } | |_- required by `Foo3` + | +help: consider restricting this type parameter with `where T: std::clone::Clone` + --> $DIR/defaults-suitability.rs:88:12 + | +LL | trait Foo3 where + | ^ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/defaults-suitability.rs:29:5 + --> $DIR/defaults-suitability.rs:27:5 | LL | type Ty = Vec<[u8]>; | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.rs b/src/test/ui/associated-types/defaults-unsound-62211-1.rs index 37d52ed16b6..c8b4734d6ed 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.rs @@ -7,8 +7,6 @@ //! Note that the underlying cause of this is still not yet fixed. //! See: https://github.com/rust-lang/rust/issues/33017 -// compile-fail - #![feature(associated_type_defaults)] use std::{ diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 35164c4f3d3..9c4a1260139 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:23:18 + --> $DIR/defaults-unsound-62211-1.rs:21:18 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -8,7 +8,7 @@ LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-1.rs:27:7 + --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -19,7 +19,7 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:25:7 + --> $DIR/defaults-unsound-62211-1.rs:23:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -28,7 +28,7 @@ LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:30:7 + --> $DIR/defaults-unsound-62211-1.rs:28:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -40,41 +40,55 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | | - | help: consider restricting this bound: `T: std::fmt::Display` + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `T` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting this type parameter with `T: std::fmt::Display` + --> $DIR/defaults-unsound-62211-1.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::ops::Deref` + --> $DIR/defaults-unsound-62211-1.rs:41:6 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::ops::Deref` + | ^ error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | | - | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` +help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>` + --> $DIR/defaults-unsound-62211-1.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-1.rs:43:9 + --> $DIR/defaults-unsound-62211-1.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/defaults-unsound-62211-1.rs:41:6 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^ error: aborting due to 8 previous errors diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.rs b/src/test/ui/associated-types/defaults-unsound-62211-2.rs index d042a1478a3..aa343e759a8 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.rs +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.rs @@ -7,8 +7,6 @@ //! Note that the underlying cause of this is still not yet fixed. //! See: https://github.com/rust-lang/rust/issues/33017 -// compile-fail - #![feature(associated_type_defaults)] use std::{ diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index af66ee117a3..4602fbc99fa 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:23:18 + --> $DIR/defaults-unsound-62211-2.rs:21:18 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -8,7 +8,7 @@ LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` error[E0277]: cannot add-assign `&'static str` to `Self` - --> $DIR/defaults-unsound-62211-2.rs:27:7 + --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -19,7 +19,7 @@ LL | + AddAssign<&'static str> = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:25:7 + --> $DIR/defaults-unsound-62211-2.rs:23:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -28,7 +28,7 @@ LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` error[E0277]: `Self` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:30:7 + --> $DIR/defaults-unsound-62211-2.rs:28:7 | LL | trait UncheckedCopy: Sized { | -------------------------- required by `UncheckedCopy` @@ -40,41 +40,55 @@ LL | + Display = Self; = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead error[E0277]: `T` doesn't implement `std::fmt::Display` - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter - | | - | help: consider restricting this bound: `T: std::fmt::Display` + | ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `T` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider restricting this type parameter with `T: std::fmt::Display` + --> $DIR/defaults-unsound-62211-2.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::ops::Deref` + --> $DIR/defaults-unsound-62211-2.rs:41:6 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::ops::Deref` + | ^ error[E0277]: cannot add-assign `&'static str` to `T` - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ no implementation for `T += &'static str` - | | - | help: consider restricting this bound: `T: std::ops::AddAssign<&'static str>` + | ^^^^^^^^^^^^^ no implementation for `T += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `T` +help: consider restricting this type parameter with `T: std::ops::AddAssign<&'static str>` + --> $DIR/defaults-unsound-62211-2.rs:41:6 + | +LL | impl UncheckedCopy for T {} + | ^ error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied - --> $DIR/defaults-unsound-62211-2.rs:43:9 + --> $DIR/defaults-unsound-62211-2.rs:41:9 + | +LL | impl UncheckedCopy for T {} + | ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` + | +help: consider restricting this type parameter with `T: std::marker::Copy` + --> $DIR/defaults-unsound-62211-2.rs:41:6 | LL | impl UncheckedCopy for T {} - | - ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T` - | | - | help: consider restricting this bound: `T: std::marker::Copy` + | ^ error: aborting due to 8 previous errors From af2931bdfef3cbb977ebb639e70ed09a1b8afdd8 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 19:43:03 +0100 Subject: [PATCH 0411/1250] Mark E0399 test as obsolete --- src/librustc_error_codes/error_codes/E0399.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md index 71482c3ca64..55e1774d9ca 100644 --- a/src/librustc_error_codes/error_codes/E0399.md +++ b/src/librustc_error_codes/error_codes/E0399.md @@ -1,9 +1,11 @@ +Note: This error code is no longer emitted by the compiler. + You implemented a trait, overriding one or more of its associated types but did not reimplement its default methods. Example of erroneous code: -```compile_fail,E0399 +```ignore #![feature(associated_type_defaults)] pub trait Foo { @@ -20,7 +22,7 @@ impl Foo for i32 { To fix this, add an implementation for each default method from the trait: -``` +```ignore #![feature(associated_type_defaults)] pub trait Foo { From 1a0e2001bca6cbb3fc8496b83d5f847e11f459e6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 21 Feb 2020 20:45:16 +0100 Subject: [PATCH 0412/1250] fix miri and bootstrap interaction --- src/bootstrap/test.rs | 4 +++- src/tools/miri | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f939f79e4f4..4cfda606c4b 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -388,6 +388,8 @@ impl Step for Miri { cargo.env("XARGO_RUST_SRC", builder.src.join("src")); // Debug things. cargo.env("RUST_BACKTRACE", "1"); + // Overwrite bootstrap's `rustc` wrapper overwriting our flags. + cargo.env("RUSTC_DEBUG_ASSERTIONS", "true"); // Let cargo-miri know where xargo ended up. cargo.env("XARGO", builder.out.join("bin").join("xargo")); @@ -397,7 +399,7 @@ impl Step for Miri { } // # Determine where Miri put its sysroot. - // To this end, we run `cargo miri setup --env` and capture the output. + // To this end, we run `cargo miri setup --print-sysroot` and capture the output. // (We do this separately from the above so that when the setup actually // happens we get some output.) // We re-use the `cargo` from above. diff --git a/src/tools/miri b/src/tools/miri index 5b8462066d9..a3dad216eea 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 5b8462066d99511a5ca119cbd3a1443ccf675714 +Subproject commit a3dad216eeab5be4ffb050afb9ab2b2c67ee4513 From c60583163a9401382bda1ddcad4d3c377539866d Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 21:46:15 +0100 Subject: [PATCH 0413/1250] Fix rebase fallout --- src/librustc_typeck/check/wfcheck.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 58820dcb381..2061c4f8c9c 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -443,7 +443,7 @@ fn check_associated_type_defaults(fcx: &FnCtxt<'_, '_>, trait_def_id: DefId) { // `>::Assoc` to the default type. let map = tcx .associated_items(trait_def_id) - .iter() + .in_definition_order() .filter_map(|item| { if item.kind == ty::AssocKind::Type && item.defaultness.has_value() { // `>::Assoc` From 6cc268b9efcfa6d74e20b0c95e715cb05f41b19e Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 21 Feb 2020 21:46:30 +0100 Subject: [PATCH 0414/1250] Mark E0399.md as obsolete --- src/librustc_error_codes/error_codes/E0399.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0399.md b/src/librustc_error_codes/error_codes/E0399.md index 55e1774d9ca..6ea6054b417 100644 --- a/src/librustc_error_codes/error_codes/E0399.md +++ b/src/librustc_error_codes/error_codes/E0399.md @@ -1,11 +1,11 @@ -Note: This error code is no longer emitted by the compiler. +#### Note: this error code is no longer emitted by the compiler You implemented a trait, overriding one or more of its associated types but did not reimplement its default methods. Example of erroneous code: -```ignore +``` #![feature(associated_type_defaults)] pub trait Foo { @@ -22,7 +22,7 @@ impl Foo for i32 { To fix this, add an implementation for each default method from the trait: -```ignore +``` #![feature(associated_type_defaults)] pub trait Foo { From 11530ded3249a82aef513733f040a7f734b16b4c Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 21 Feb 2020 13:17:19 -0800 Subject: [PATCH 0415/1250] Update cargo --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index e02974078a6..e57bd02999c 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit e02974078a692d7484f510eaec0e88d1b6cc0203 +Subproject commit e57bd02999c9f40d52116e0beca7d1dccb0643de From 38a22b8130f6466352bca53d5020c44cd648326a Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 21 Feb 2020 14:49:51 +0100 Subject: [PATCH 0416/1250] Fix error message Bless tests --- .../hair/pattern/check_match.rs | 2 +- ...can-live-while-the-other-survives-1.stderr | 4 +- ...t-by-move-and-ref-inverse-promotion.stderr | 2 +- ...orrowck-pat-by-move-and-ref-inverse.stderr | 50 +++++++++---------- .../borrowck-pat-ref-mut-twice.stderr | 8 +-- ...inding-modes-both-sides-independent.stderr | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 651f2f70d9b..3dfe826ad2a 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -659,7 +659,7 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pat<'_ }); if !conflicts_ref.is_empty() { let occurs_because = format!( - "move occurs because `{}` has type `{}` which does implement the `Copy` trait", + "move occurs because `{}` has type `{}` which does not implement the `Copy` trait", name, tables.node_type(pat.hir_id), ); diff --git a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr index 026747c212a..f2186b9298e 100644 --- a/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr +++ b/src/test/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr @@ -15,7 +15,7 @@ LL | Some(_z @ ref _y) => {} | | | | | value borrowed here after move | value moved into `_z` here - | move occurs because `_z` has type `X` which does implement the `Copy` trait + | move occurs because `_z` has type `X` which does not implement the `Copy` trait error: cannot move out of value because it is borrowed --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:29:14 @@ -34,7 +34,7 @@ LL | Some(_z @ ref mut _y) => {} | | | | | value borrowed here after move | value moved into `_z` here - | move occurs because `_z` has type `X` which does implement the `Copy` trait + | move occurs because `_z` has type `X` which does not implement the `Copy` trait error[E0382]: borrow of moved value --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:21:19 diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr index 91fdfd4f2ab..54900e958c2 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr @@ -6,7 +6,7 @@ LL | let a @ ref b = U; | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `main::U` which does implement the `Copy` trait + | move occurs because `a` has type `main::U` which does not implement the `Copy` trait error: aborting due to previous error diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr index ec86692dc69..f819e671436 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr @@ -6,7 +6,7 @@ LL | let a @ ref b = U; | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `main::U` which does implement the `Copy` trait + | move occurs because `a` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9 @@ -17,7 +17,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + | move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:14 @@ -27,7 +27,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::U` which does implement the `Copy` trait + | move occurs because `b` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:33 @@ -37,7 +37,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (U, U); | | | | | value borrowed here after move | value moved into `d` here - | move occurs because `d` has type `main::U` which does implement the `Copy` trait + | move occurs because `d` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9 @@ -48,7 +48,7 @@ LL | let a @ [ref mut b, ref c] = [U, U]; | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + | move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:41:9 @@ -58,7 +58,7 @@ LL | let a @ ref b = u(); | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `main::U` which does implement the `Copy` trait + | move occurs because `a` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:9 @@ -69,7 +69,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + | move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:14 @@ -79,7 +79,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::U` which does implement the `Copy` trait + | move occurs because `b` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:44:33 @@ -89,7 +89,7 @@ LL | let a @ (mut b @ ref mut c, d @ ref e) = (u(), u()); | | | | | value borrowed here after move | value moved into `d` here - | move occurs because `d` has type `main::U` which does implement the `Copy` trait + | move occurs because `d` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:51:9 @@ -100,7 +100,7 @@ LL | let a @ [ref mut b, ref c] = [u(), u()]; | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + | move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:56:9 @@ -110,7 +110,7 @@ LL | a @ Some(ref b) => {} | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9 @@ -121,7 +121,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:19 @@ -131,7 +131,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::U` which does implement the `Copy` trait + | move occurs because `b` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:38 @@ -141,7 +141,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | | | value borrowed here after move | value moved into `d` here - | move occurs because `d` has type `main::U` which does implement the `Copy` trait + | move occurs because `d` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:71:9 @@ -152,7 +152,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:77:9 @@ -162,7 +162,7 @@ LL | a @ Some(ref b) => {} | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:9 @@ -173,7 +173,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option<(main::U, main::U)>` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:19 @@ -183,7 +183,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::U` which does implement the `Copy` trait + | move occurs because `b` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:83:38 @@ -193,7 +193,7 @@ LL | a @ Some((mut b @ ref mut c, d @ ref e)) => {} | | | | | value borrowed here after move | value moved into `d` here - | move occurs because `d` has type `main::U` which does implement the `Copy` trait + | move occurs because `d` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:93:9 @@ -204,7 +204,7 @@ LL | mut a @ Some([ref b, ref mut c]) => {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does implement the `Copy` trait + | move occurs because `a` has type `std::option::Option<[main::U; 2]>` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11 @@ -214,7 +214,7 @@ LL | fn f1(a @ ref b: U) {} | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `main::U` which does implement the `Copy` trait + | move occurs because `a` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:11 @@ -225,7 +225,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + | move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:20 @@ -235,7 +235,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::U` which does implement the `Copy` trait + | move occurs because `b` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:18:31 @@ -245,7 +245,7 @@ LL | fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {} | | | | | value borrowed here after move | value moved into `d` here - | move occurs because `d` has type `main::U` which does implement the `Copy` trait + | move occurs because `d` has type `main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:25:11 @@ -256,7 +256,7 @@ LL | fn f3(a @ [ref mut b, ref c]: [U; 2]) {} | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `[main::U; 2]` which does implement the `Copy` trait + | move occurs because `a` has type `[main::U; 2]` which does not implement the `Copy` trait error[E0382]: borrow of moved value --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:22 diff --git a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr index 4e96c6e1669..e74f227b5e4 100644 --- a/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr +++ b/src/test/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr @@ -96,7 +96,7 @@ LL | let a @ (ref mut b, ref mut c) = (U, U); | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `(main::U, main::U)` which does implement the `Copy` trait + | move occurs because `a` has type `(main::U, main::U)` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9 @@ -108,7 +108,7 @@ LL | let a @ (b, [c, d]) = &mut val; // Same as ^-- | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `&mut (main::U, [main::U; 2])` which does implement the `Copy` trait + | move occurs because `a` has type `&mut (main::U, [main::U; 2])` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:74:9 @@ -118,7 +118,7 @@ LL | let a @ &mut ref mut b = &mut U; | | | | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `&mut main::U` which does implement the `Copy` trait + | move occurs because `a` has type `&mut main::U` which does not implement the `Copy` trait error: borrow of moved value --> $DIR/borrowck-pat-ref-mut-twice.rs:77:9 @@ -129,7 +129,7 @@ LL | let a @ &mut (ref mut b, ref mut c) = &mut (U, U); | | | value borrowed here after move | | value borrowed here after move | value moved into `a` here - | move occurs because `a` has type `&mut (main::U, main::U)` which does implement the `Copy` trait + | move occurs because `a` has type `&mut (main::U, main::U)` which does not implement the `Copy` trait error: cannot borrow value as mutable more than once at a time --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9 diff --git a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr index 697a8b96e63..19e815a1ae8 100644 --- a/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr +++ b/src/test/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr @@ -33,7 +33,7 @@ LL | Ok(ref a @ b) | Err(b @ ref a) => { | | | | | value borrowed here after move | value moved into `b` here - | move occurs because `b` has type `main::NotCopy` which does implement the `Copy` trait + | move occurs because `b` has type `main::NotCopy` which does not implement the `Copy` trait error: cannot move out of value because it is borrowed --> $DIR/default-binding-modes-both-sides-independent.rs:44:9 From 9f3dfd29a21f1bdc26720703f79d3fabdc7471de Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 21 Feb 2020 23:00:27 +0100 Subject: [PATCH 0417/1250] parse: allow `type Foo: Ord` syntactically. --- src/librustc_ast_lowering/item.rs | 18 ++--- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_ast_passes/ast_validation.rs | 7 ++ src/librustc_ast_passes/feature_gate.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 16 ++--- src/librustc_parse/parser/item.rs | 32 ++++----- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_resolve/late.rs | 2 +- src/librustc_save_analysis/dump_visitor.rs | 9 ++- src/librustc_save_analysis/sig.rs | 7 +- src/libsyntax/ast.rs | 4 +- src/libsyntax/mut_visit.rs | 5 +- src/libsyntax/visit.rs | 7 +- src/test/ui/parser/bounds-lifetime-where.rs | 2 +- .../ui/parser/bounds-lifetime-where.stderr | 4 +- .../item-free-type-bounds-semantic-fail.rs | 20 ++++++ ...item-free-type-bounds-semantic-fail.stderr | 67 +++++++++++++++++++ .../item-free-type-bounds-syntactic-pass.rs | 13 ++++ 18 files changed, 160 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/parser/item-free-type-bounds-semantic-fail.rs create mode 100644 src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr create mode 100644 src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index ad7221b16b2..1a19fab0265 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -297,28 +297,28 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)), ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)), - ItemKind::TyAlias(ref ty, ref generics) => match ty.kind.opaque_top_hack() { + ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() { None => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); hir::ItemKind::TyAlias(ty, generics) } Some(bounds) => { + let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc); let ty = hir::OpaqueTy { - generics: self.lower_generics( - generics, - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc), - ), - bounds: self.lower_param_bounds( - bounds, - ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc), - ), + generics: self.lower_generics(generics, ctx()), + bounds: self.lower_param_bounds(bounds, ctx()), impl_trait_fn: None, origin: hir::OpaqueTyOrigin::TypeAlias, }; hir::ItemKind::OpaqueTy(ty) } }, + ItemKind::TyAlias(ref generics, _, None) => { + let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err)); + let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); + hir::ItemKind::TyAlias(ty, generics) + } ItemKind::Enum(ref enum_definition, ref generics) => hir::ItemKind::Enum( hir::EnumDef { variants: self.arena.alloc_from_iter( diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index ac4ca30382f..9bb46009fe6 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) | ItemKind::Enum(_, ref generics) - | ItemKind::TyAlias(_, ref generics) + | ItemKind::TyAlias(ref generics, ..) | ItemKind::Trait(_, _, ref generics, ..) => { let def_id = self.lctx.resolver.definitions().local_def_id(item.id); let count = generics diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 1194269e0ee..a9844a7059e 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -969,6 +969,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let msg = "free static item without body"; self.error_item_without_body(item.span, "static", msg, " = ;"); } + ItemKind::TyAlias(_, ref bounds, ref body) => { + if body.is_none() { + let msg = "free type alias without body"; + self.error_item_without_body(item.span, "type", msg, " = ;"); + } + self.check_type_no_bounds(bounds, "this context"); + } _ => {} } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 3c924847a73..5bddae0d49e 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, decl_macro, i.span, msg); } - ast::ItemKind::TyAlias(ref ty, ..) => self.check_impl_trait(&ty), + ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty), _ => {} } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 27cef8502a1..9b7bb574946 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1185,18 +1185,10 @@ impl<'a> State<'a> { self.s.word(ga.asm.to_string()); self.end(); } - ast::ItemKind::TyAlias(ref ty, ref generics) => { - self.head(visibility_qualified(&item.vis, "type")); - self.print_ident(item.ident); - self.print_generic_params(&generics.params); - self.end(); // end the inner ibox - - self.print_where_clause(&generics.where_clause); - self.s.space(); - self.word_space("="); - self.print_type(ty); - self.s.word(";"); - self.end(); // end the outer ibox + ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + let def = ast::Defaultness::Final; + let ty = ty.as_deref(); + self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def); } ast::ItemKind::Enum(ref enum_definition, ref params) => { self.print_enum_def(enum_definition, params, item.ident, item.span, &item.vis); diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 4dcde2f92db..328cf11c532 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -156,8 +156,7 @@ impl<'a> Parser<'a> { self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM - let (ident, ty, generics) = self.parse_type_alias()?; - (ident, ItemKind::TyAlias(ty, generics)) + self.parse_type_alias()? } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? @@ -676,7 +675,10 @@ impl<'a> Parser<'a> { vis: &Visibility, ) -> PResult<'a, (Ident, AssocItemKind)> { if self.eat_keyword(kw::Type) { - self.parse_assoc_ty() + match self.parse_type_alias()? { + (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))), + _ => unreachable!(), + } } else if self.check_fn_front_matter() { let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?; Ok((ident, AssocItemKind::Fn(sig, generics, body))) @@ -700,10 +702,12 @@ impl<'a> Parser<'a> { } } - /// Parses the following grammar: - /// - /// AssocTy = Ident ["<"...">"] [":" [GenericBounds]] ["where" ...] ["=" Ty] - fn parse_assoc_ty(&mut self) -> PResult<'a, (Ident, AssocItemKind)> { + /// Parses a `type` alias with the following grammar: + /// ``` + /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ; + /// ``` + /// The `"type"` has already been eaten. + fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -715,7 +719,7 @@ impl<'a> Parser<'a> { let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; - Ok((ident, AssocItemKind::TyAlias(generics, bounds, default))) + Ok((ident, ItemKind::TyAlias(generics, bounds, default))) } /// Parses a `UseTree`. @@ -989,18 +993,6 @@ impl<'a> Parser<'a> { P(Ty { kind: TyKind::Infer, span: id.span, id: ast::DUMMY_NODE_ID }) } - /// Parses the grammar: - /// Ident ["<"...">"] ["where" ...] ("=" | ":") Ty ";" - fn parse_type_alias(&mut self) -> PResult<'a, (Ident, P, Generics)> { - let ident = self.parse_ident()?; - let mut tps = self.parse_generics()?; - tps.where_clause = self.parse_where_clause()?; - self.expect(&token::Eq)?; - let ty = self.parse_ty()?; - self.expect_semi()?; - Ok((ident, ty, tps)) - } - /// Parses an enum declaration. fn parse_item_enum(&mut self) -> PResult<'a, ItemInfo> { let id = self.parse_ident()?; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 1f622b80e8e..383bfe18fd0 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -718,8 +718,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // These items live in the type namespace. - ItemKind::TyAlias(ref ty, _) => { - let def_kind = match ty.kind.opaque_top_hack() { + ItemKind::TyAlias(_, _, ref ty) => { + let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => DefKind::TyAlias, Some(_) => DefKind::OpaqueTy, }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 73601cd2ee7..74628e6e5a0 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("(resolving item) resolving {} ({:?})", name, item.kind); match item.kind { - ItemKind::TyAlias(_, ref generics) | ItemKind::Fn(_, ref generics, _) => { + ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_item(this, item) }); diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index db7733e7241..53dd6d28f89 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1311,12 +1311,15 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.process_mod(item); visit::walk_mod(self, m); } - TyAlias(ref ty, ref ty_params) => { + TyAlias(ref ty_params, _, ref ty) => { let qualname = format!( "::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) ); - let value = ty_to_string(&ty); + let value = match ty { + Some(ty) => ty_to_string(&ty), + None => "_".to_string(), + }; if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); let id = id_from_node_id(item.id, &self.save_ctxt); @@ -1341,7 +1344,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { ); } - self.visit_ty(&ty); + walk_list!(self, visit_ty, ty); self.process_generic_params(ty_params, &qualname, item.id); } Mac(_) => (), diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index a2c61db4b7c..2c07ed0571b 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -423,12 +423,15 @@ impl Sig for ast::Item { Ok(Signature { text, defs, refs: vec![] }) } - ast::ItemKind::TyAlias(ref ty, ref generics) => { + ast::ItemKind::TyAlias(ref generics, _, ref ty) => { let text = "type ".to_owned(); let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?; sig.text.push_str(" = "); - let ty = ty.make(offset + sig.text.len(), id, scx)?; + let ty = match ty { + Some(ty) => ty.make(offset + sig.text.len(), id, scx)?, + None => Err("Ty")?, + }; sig.text.push_str(&ty.text); sig.text.push(';'); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 9ae3010a0f6..849950e939a 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2524,7 +2524,7 @@ pub enum ItemKind { /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. - TyAlias(P, Generics), + TyAlias(Generics, GenericBounds, Option>), /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. @@ -2594,7 +2594,7 @@ impl ItemKind { pub fn generics(&self) -> Option<&Generics> { match self { Self::Fn(_, generics, _) - | Self::TyAlias(_, generics) + | Self::TyAlias(generics, ..) | Self::Enum(_, generics) | Self::Struct(_, generics) | Self::Union(_, generics) diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 92f20b719f8..02f790dfbb4 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -902,9 +902,10 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { ItemKind::Mod(m) => vis.visit_mod(m), ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(_ga) => {} - ItemKind::TyAlias(ty, generics) => { - vis.visit_ty(ty); + ItemKind::TyAlias(generics, bounds, ty) => { vis.visit_generics(generics); + visit_bounds(bounds, vis); + visit_opt(ty, |ty| vis.visit_ty(ty)); } ItemKind::Enum(EnumDef { variants }, generics) => { variants.flat_map_in_place(|variant| vis.flat_map_variant(variant)); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index dedd42fe0f6..bd35918dba7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -312,9 +312,10 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga), - ItemKind::TyAlias(ref typ, ref generics) => { - visitor.visit_ty(typ); - visitor.visit_generics(generics) + ItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + visitor.visit_generics(generics); + walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_ty, ty); } ItemKind::Enum(ref enum_definition, ref generics) => { visitor.visit_generics(generics); diff --git a/src/test/ui/parser/bounds-lifetime-where.rs b/src/test/ui/parser/bounds-lifetime-where.rs index acb04e7859b..e60cc153e67 100644 --- a/src/test/ui/parser/bounds-lifetime-where.rs +++ b/src/test/ui/parser/bounds-lifetime-where.rs @@ -5,6 +5,6 @@ type A where 'a:, = u8; // OK type A where 'a: 'b + 'c = u8; // OK type A where = u8; // OK type A where 'a: 'b + = u8; // OK -type A where , = u8; //~ ERROR expected one of `=`, lifetime, or type, found `,` +type A where , = u8; //~ ERROR expected one of `;`, `=`, lifetime, or type, found `,` fn main() {} diff --git a/src/test/ui/parser/bounds-lifetime-where.stderr b/src/test/ui/parser/bounds-lifetime-where.stderr index 05cebd6d351..950fa46c66b 100644 --- a/src/test/ui/parser/bounds-lifetime-where.stderr +++ b/src/test/ui/parser/bounds-lifetime-where.stderr @@ -1,8 +1,8 @@ -error: expected one of `=`, lifetime, or type, found `,` +error: expected one of `;`, `=`, lifetime, or type, found `,` --> $DIR/bounds-lifetime-where.rs:8:14 | LL | type A where , = u8; - | ^ expected one of `=`, lifetime, or type + | ^ expected one of `;`, `=`, lifetime, or type error: aborting due to previous error diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs new file mode 100644 index 00000000000..9db4111fbab --- /dev/null +++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.rs @@ -0,0 +1,20 @@ +fn main() {} + +fn semantics() { + type A: Ord; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR free type alias without body + type B: Ord = u8; + //~^ ERROR bounds on `type`s in this context have no effect + type C: Ord where 'static: 'static = u8; + //~^ ERROR bounds on `type`s in this context have no effect + type D<_T>: Ord; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR free type alias without body + type E<_T>: Ord = u8; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR type parameter `_T` is unused + type F<_T>: Ord where 'static: 'static = u8; + //~^ ERROR bounds on `type`s in this context have no effect + //~| ERROR type parameter `_T` is unused +} diff --git a/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr new file mode 100644 index 00000000000..1b086512891 --- /dev/null +++ b/src/test/ui/parser/item-free-type-bounds-semantic-fail.stderr @@ -0,0 +1,67 @@ +error: free type alias without body + --> $DIR/item-free-type-bounds-semantic-fail.rs:4:5 + | +LL | type A: Ord; + | ^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:4:13 + | +LL | type A: Ord; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:7:13 + | +LL | type B: Ord = u8; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:9:13 + | +LL | type C: Ord where 'static: 'static = u8; + | ^^^ + +error: free type alias without body + --> $DIR/item-free-type-bounds-semantic-fail.rs:11:5 + | +LL | type D<_T>: Ord; + | ^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the type: `= ;` + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:11:17 + | +LL | type D<_T>: Ord; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:14:17 + | +LL | type E<_T>: Ord = u8; + | ^^^ + +error: bounds on `type`s in this context have no effect + --> $DIR/item-free-type-bounds-semantic-fail.rs:17:17 + | +LL | type F<_T>: Ord where 'static: 'static = u8; + | ^^^ + +error[E0091]: type parameter `_T` is unused + --> $DIR/item-free-type-bounds-semantic-fail.rs:14:12 + | +LL | type E<_T>: Ord = u8; + | ^^ unused type parameter + +error[E0091]: type parameter `_T` is unused + --> $DIR/item-free-type-bounds-semantic-fail.rs:17:12 + | +LL | type F<_T>: Ord where 'static: 'static = u8; + | ^^ unused type parameter + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0091`. diff --git a/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs new file mode 100644 index 00000000000..58fc926d08f --- /dev/null +++ b/src/test/ui/parser/item-free-type-bounds-syntactic-pass.rs @@ -0,0 +1,13 @@ +// check-pass + +fn main() {} + +#[cfg(FALSE)] +fn syntax() { + type A: Ord; + type B: Ord = u8; + type C: Ord where 'static: 'static = u8; + type D<_T>: Ord; + type E<_T>: Ord = u8; + type F<_T>: Ord where 'static: 'static = u8; +} From fa73b617c23a529b1ad966a9814961f1cbc78f6c Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 21 Feb 2020 16:01:48 -0800 Subject: [PATCH 0418/1250] clean things up --- src/librustc_expand/expand.rs | 8 +++++++- src/librustc_lint/builtin.rs | 29 +++++++---------------------- src/librustc_lint/context.rs | 5 +++++ src/librustc_session/lint.rs | 1 + src/librustc_session/parse.rs | 19 +++++++++++++++++++ src/test/ui/useless-comment.rs | 4 ++-- src/test/ui/useless-comment.stderr | 11 +++++++---- 7 files changed, 48 insertions(+), 29 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 3c720271e4b..0c87d3fe8fc 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -14,6 +14,7 @@ use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_parse::DirectoryOwnership; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::source_map::respan; @@ -1093,7 +1094,12 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { } if attr.doc_str().is_some() { - self.cx.parse_sess.buffer_lint(&UNUSED_DOC_COMMENTS, attr.span, ast::CRATE_NODE_ID, "yep, it's unused"); + self.cx.parse_sess.buffer_lint_with_diagnostic( + &UNUSED_DOC_COMMENTS, + attr.span, + ast::CRATE_NODE_ID, + "unused doc comment", + BuiltinLintDiagnostics::UnusedDocComment(attr.span)); } } } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index c0eee7e05c8..705097d4644 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -744,7 +744,6 @@ trait UnusedDocCommentExt { cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, - is_macro_expansion: bool, attrs: &[ast::Attribute], ); } @@ -755,7 +754,6 @@ impl UnusedDocCommentExt for UnusedDocComment { cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, - is_macro_expansion: bool, attrs: &[ast::Attribute], ) { let mut attrs = attrs.into_iter().peekable(); @@ -783,12 +781,6 @@ impl UnusedDocCommentExt for UnusedDocComment { node_span, format!("rustdoc does not generate documentation for {}", node_kind), ); - if is_macro_expansion { - err.help( - "to document an item produced by a macro, \ - the macro must produce the documentation as part of its expansion", - ); - } err.emit(); }); } @@ -797,31 +789,24 @@ impl UnusedDocCommentExt for UnusedDocComment { } impl EarlyLintPass for UnusedDocComment { - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) { - if let ast::ItemKind::Mac(..) = item.kind { - self.warn_if_doc(cx, item.span, "macro expansions", true, &item.attrs); - } - } - fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { - let (kind, is_macro_expansion) = match stmt.kind { - ast::StmtKind::Local(..) => ("statements", false), - ast::StmtKind::Item(..) => ("inner items", false), - ast::StmtKind::Mac(..) => ("macro expansions", true), + let kind = match stmt.kind { + ast::StmtKind::Local(..) => "statements", + ast::StmtKind::Item(..) => "inner items", // expressions will be reported by `check_expr`. - ast::StmtKind::Semi(..) | ast::StmtKind::Expr(..) => return, + ast::StmtKind::Semi(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Mac(..) => return, }; - self.warn_if_doc(cx, stmt.span, kind, is_macro_expansion, stmt.kind.attrs()); + self.warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs()); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { let arm_span = arm.pat.span.with_hi(arm.body.span.hi()); - self.warn_if_doc(cx, arm_span, "match arms", false, &arm.attrs); + self.warn_if_doc(cx, arm_span, "match arms", &arm.attrs); } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - self.warn_if_doc(cx, expr.span, "expressions", false, &expr.attrs); + self.warn_if_doc(cx, expr.span, "expressions", &expr.attrs); } } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 8e8beefa72f..adad1198b09 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -565,6 +565,11 @@ pub trait LintContext: Sized { BuiltinLintDiagnostics::DeprecatedMacro(suggestion, span) => { stability::deprecation_suggestion(&mut db, suggestion, span) } + BuiltinLintDiagnostics::UnusedDocComment(span) => { + db.span_label(span, "rustdoc does not generate documentation for macros"); + db.help("to document an item produced by a macro, \ + the macro must produce the documentation as part of its expansion"); + } } // Rewrap `db`, and pass control to the user. decorate(LintDiagnosticBuilder::new(db)); diff --git a/src/librustc_session/lint.rs b/src/librustc_session/lint.rs index 983dfb19919..6d4f1ff5b48 100644 --- a/src/librustc_session/lint.rs +++ b/src/librustc_session/lint.rs @@ -190,6 +190,7 @@ pub enum BuiltinLintDiagnostics { UnusedImports(String, Vec<(Span, String)>), RedundantImport(Vec<(Span, bool)>, Ident), DeprecatedMacro(Option, Span), + UnusedDocComment(Span), } /// Lints that are buffered up early on in the `Session` before the diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 6a4871b6da0..30888e343ed 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -176,6 +176,25 @@ impl ParseSess { }); } + pub fn buffer_lint_with_diagnostic( + &self, + lint: &'static Lint, + span: impl Into, + node_id: NodeId, + msg: &str, + diagnostic: BuiltinLintDiagnostics, + ) { + self.buffered_lints.with_lock(|buffered_lints| { + buffered_lints.push(BufferedEarlyLint { + span: span.into(), + node_id, + msg: msg.into(), + lint_id: LintId::of(lint), + diagnostic, + }); + }); + } + /// Extend an error with a suggestion to wrap an expression with parentheses to allow the /// parser to continue parsing the following operation as part of the same expression. pub fn expr_parentheses_needed( diff --git a/src/test/ui/useless-comment.rs b/src/test/ui/useless-comment.rs index d13db2f8f78..7d2e5ab6f2b 100644 --- a/src/test/ui/useless-comment.rs +++ b/src/test/ui/useless-comment.rs @@ -6,7 +6,7 @@ macro_rules! mac { () => {} } -/// foo //~ ERROR yep, it's unused +/// foo //~ ERROR unused doc comment mac!(); fn foo() { @@ -29,7 +29,7 @@ fn foo() { #[doc = "bar"] //~ ERROR unused doc comment 3; - /// bar //~ ERROR yep, it's unused + /// bar //~ ERROR unused doc comment mac!(); let x = /** comment */ 47; //~ ERROR unused doc comment diff --git a/src/test/ui/useless-comment.stderr b/src/test/ui/useless-comment.stderr index 76b37cfec71..92817321a88 100644 --- a/src/test/ui/useless-comment.stderr +++ b/src/test/ui/useless-comment.stderr @@ -1,20 +1,23 @@ -error: yep, it's unused +error: unused doc comment --> $DIR/useless-comment.rs:9:1 | LL | /// foo - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macros | note: the lint level is defined here --> $DIR/useless-comment.rs:3:9 | LL | #![deny(unused_doc_comments)] | ^^^^^^^^^^^^^^^^^^^ + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion -error: yep, it's unused +error: unused doc comment --> $DIR/useless-comment.rs:32:5 | LL | /// bar - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ rustdoc does not generate documentation for macros + | + = help: to document an item produced by a macro, the macro must produce the documentation as part of its expansion error: unused doc comment --> $DIR/useless-comment.rs:13:5 From 2a504878c3d1f80581e6b202490e10fe199914da Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 20 Jan 2020 22:16:42 +0000 Subject: [PATCH 0419/1250] Return whether `check_generic_arg_count` finds an error --- src/librustc_typeck/astconv.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 78c05a51e4f..599fb7c57f7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -402,10 +402,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.emit(); - ( - provided > required, // `suppress_error` - potential_assoc_types, - ) + (true, potential_assoc_types) }; if reported_late_bound_region_err.is_none() From d232acdb398c5837f2c95ffe6c38970059451445 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 20 Jan 2020 23:59:17 +0000 Subject: [PATCH 0420/1250] Report all errors in `check_generic_arg_count` --- src/librustc_typeck/astconv.rs | 147 +++++++++--------- .../generic/generic-arg-mismatch-recover.rs | 1 - .../generic-arg-mismatch-recover.stderr | 18 +-- 3 files changed, 81 insertions(+), 85 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 599fb7c57f7..5c9178ff66d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -287,7 +287,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { position: GenericArgPosition, has_self: bool, infer_args: bool, - ) -> (bool, Option>) { + ) -> (bool, Vec) { // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. // that lifetimes will proceed types. So it suffices to check the number of each generic // arguments in order to validate them with respect to the generic parameters. @@ -341,104 +341,110 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } - let check_kind_count = |kind, required, permitted, provided, offset| { - debug!( - "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}", - kind, required, permitted, provided, offset - ); - // We enforce the following: `required` <= `provided` <= `permitted`. - // For kinds without defaults (e.g.., lifetimes), `required == permitted`. - // For other kinds (i.e., types), `permitted` may be greater than `required`. - if required <= provided && provided <= permitted { - return (reported_late_bound_region_err.unwrap_or(false), None); - } - - // Unfortunately lifetime and type parameter mismatches are typically styled - // differently in diagnostics, which means we have a few cases to consider here. - let (bound, quantifier) = if required != permitted { - if provided < required { - (required, "at least ") - } else { - // provided > permitted - (permitted, "at most ") + let check_kind_count = + |kind, required, permitted, provided, offset, unexpected_spans: &mut Vec| { + debug!( + "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}", + kind, required, permitted, provided, offset + ); + // We enforce the following: `required` <= `provided` <= `permitted`. + // For kinds without defaults (e.g.., lifetimes), `required == permitted`. + // For other kinds (i.e., types), `permitted` may be greater than `required`. + if required <= provided && provided <= permitted { + return false; } - } else { - (required, "") - }; - let mut potential_assoc_types: Option> = None; - let (spans, label) = if required == permitted && provided > permitted { - // In the case when the user has provided too many arguments, - // we want to point to the unexpected arguments. - let spans: Vec = args.args[offset + permitted..offset + provided] - .iter() - .map(|arg| arg.span()) - .collect(); - potential_assoc_types = Some(spans.clone()); - (spans, format!("unexpected {} argument", kind)) - } else { - ( - vec![span], - format!( - "expected {}{} {} argument{}", - quantifier, - bound, - kind, - pluralize!(bound), + // Unfortunately lifetime and type parameter mismatches are typically styled + // differently in diagnostics, which means we have a few cases to consider here. + let (bound, quantifier) = if required != permitted { + if provided < required { + (required, "at least ") + } else { + // provided > permitted + (permitted, "at most ") + } + } else { + (required, "") + }; + + let (spans, label) = if required == permitted && provided > permitted { + // In the case when the user has provided too many arguments, + // we want to point to the unexpected arguments. + let spans: Vec = args.args[offset + permitted..offset + provided] + .iter() + .map(|arg| arg.span()) + .collect(); + unexpected_spans.extend(spans.clone()); + (spans, format!("unexpected {} argument", kind)) + } else { + ( + vec![span], + format!( + "expected {}{} {} argument{}", + quantifier, + bound, + kind, + pluralize!(bound), + ), + ) + }; + + let mut err = tcx.sess.struct_span_err_with_code( + spans.clone(), + &format!( + "wrong number of {} arguments: expected {}{}, found {}", + kind, quantifier, bound, provided, ), - ) - }; + DiagnosticId::Error("E0107".into()), + ); + for span in spans { + err.span_label(span, label.as_str()); + } + err.emit(); - let mut err = tcx.sess.struct_span_err_with_code( - spans.clone(), - &format!( - "wrong number of {} arguments: expected {}{}, found {}", - kind, quantifier, bound, provided, - ), - DiagnosticId::Error("E0107".into()), - ); - for span in spans { - err.span_label(span, label.as_str()); - } - err.emit(); + true + }; - (true, potential_assoc_types) - }; + let mut arg_count_mismatch = reported_late_bound_region_err.unwrap_or(false); + let mut unexpected_spans = vec![]; if reported_late_bound_region_err.is_none() && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes) { - check_kind_count( + arg_count_mismatch |= check_kind_count( "lifetime", param_counts.lifetimes, param_counts.lifetimes, arg_counts.lifetimes, 0, + &mut unexpected_spans, ); } // FIXME(const_generics:defaults) if !infer_args || arg_counts.consts > param_counts.consts { - check_kind_count( + arg_count_mismatch |= check_kind_count( "const", param_counts.consts, param_counts.consts, arg_counts.consts, arg_counts.lifetimes + arg_counts.types, + &mut unexpected_spans, ); } // Note that type errors are currently be emitted *after* const errors. if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize { - check_kind_count( + arg_count_mismatch |= check_kind_count( "type", param_counts.types - defaults.types - has_self as usize, param_counts.types - has_self as usize, arg_counts.types, arg_counts.lifetimes, - ) - } else { - (reported_late_bound_region_err.unwrap_or(false), None) + &mut unexpected_spans, + ); } + + (arg_count_mismatch, unexpected_spans) } /// Creates the relevant generic argument substitutions @@ -627,7 +633,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - ) -> (SubstsRef<'tcx>, Vec>, Option>) { + ) -> (SubstsRef<'tcx>, Vec>, Vec) { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). @@ -922,7 +928,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, - ) -> Option> { + ) -> Vec { let trait_def_id = trait_ref.trait_def_id(); debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); @@ -968,6 +974,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { "instantiate_poly_trait_ref({:?}, bounds={:?}) -> {:?}", trait_ref, bounds, poly_trait_ref ); + potential_assoc_types } @@ -996,7 +1003,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { constness: Constness, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, - ) -> Option> { + ) -> Vec { self.instantiate_poly_trait_ref_inner( &poly_trait_ref.trait_ref, poly_trait_ref.span, @@ -1085,7 +1092,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, - ) -> (SubstsRef<'tcx>, Vec>, Option>) { + ) -> (SubstsRef<'tcx>, Vec>, Vec) { debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); @@ -1436,7 +1443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { dummy_self, &mut bounds, ); - potential_assoc_types.extend(cur_potential_assoc_types.into_iter().flatten()); + potential_assoc_types.extend(cur_potential_assoc_types.into_iter()); } // Expand trait aliases recursively and check that only one regular (non-auto) trait diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.rs b/src/test/ui/generic/generic-arg-mismatch-recover.rs index f4e15fbebce..3e5e2e601f5 100644 --- a/src/test/ui/generic/generic-arg-mismatch-recover.rs +++ b/src/test/ui/generic/generic-arg-mismatch-recover.rs @@ -4,7 +4,6 @@ struct Bar<'a>(&'a ()); fn main() { Foo::<'static, 'static, ()>(&0); //~ ERROR wrong number of lifetime arguments - //~^ ERROR mismatched types Bar::<'static, 'static, ()>(&()); //~ ERROR wrong number of lifetime arguments //~^ ERROR wrong number of type arguments diff --git a/src/test/ui/generic/generic-arg-mismatch-recover.stderr b/src/test/ui/generic/generic-arg-mismatch-recover.stderr index 4b86212e486..99adb352685 100644 --- a/src/test/ui/generic/generic-arg-mismatch-recover.stderr +++ b/src/test/ui/generic/generic-arg-mismatch-recover.stderr @@ -4,28 +4,18 @@ error[E0107]: wrong number of lifetime arguments: expected 1, found 2 LL | Foo::<'static, 'static, ()>(&0); | ^^^^^^^ unexpected lifetime argument -error[E0308]: mismatched types - --> $DIR/generic-arg-mismatch-recover.rs:6:33 - | -LL | Foo::<'static, 'static, ()>(&0); - | ^^ expected `()`, found integer - | - = note: expected reference `&'static ()` - found reference `&{integer}` - error[E0107]: wrong number of lifetime arguments: expected 1, found 2 - --> $DIR/generic-arg-mismatch-recover.rs:9:20 + --> $DIR/generic-arg-mismatch-recover.rs:8:20 | LL | Bar::<'static, 'static, ()>(&()); | ^^^^^^^ unexpected lifetime argument error[E0107]: wrong number of type arguments: expected 0, found 1 - --> $DIR/generic-arg-mismatch-recover.rs:9:29 + --> $DIR/generic-arg-mismatch-recover.rs:8:29 | LL | Bar::<'static, 'static, ()>(&()); | ^^ unexpected type argument -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0107, E0308. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0107`. From 9939de24ac3580acfb92670f9bd568f90052340b Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 21 Jan 2020 20:46:21 +0000 Subject: [PATCH 0421/1250] Correct passing of `generic_args` to `create_substs_for_generic_args` --- src/librustc_typeck/astconv.rs | 9 ++++++++- src/librustc_typeck/check/method/confirm.rs | 11 ++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 5c9178ff66d..a1440c3e289 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -693,7 +693,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty.is_some(), self_ty, // Provide the generic args, and whether types should be inferred. - |_| (Some(generic_args), infer_args), + |did| { + if did == def_id { + (Some(generic_args), infer_args) + } else { + // The last component of this tuple is unimportant. + (None, false) + } + }, // Provide substitutions for parameters for which (valid) arguments have been provided. |param, arg| match (¶m.kind, arg) { (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 17842be9a43..04cbee8c940 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -314,9 +314,14 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { false, None, // Provide the generic args, and whether types should be inferred. - |_| { - // The last argument of the returned tuple here is unimportant. - if let Some(ref data) = seg.args { (Some(data), false) } else { (None, false) } + |def_id| { + // The last component of the returned tuple here is unimportant. + if def_id == pick.item.def_id { + if let Some(ref data) = seg.args { + return (Some(data), false); + } + } + (None, false) }, // Provide substitutions for parameters for which (valid) arguments have been provided. |param, arg| match (¶m.kind, arg) { From 750e673491114cd8454f1715ce1fda8dd02b7ac0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 21 Jan 2020 22:36:17 +0000 Subject: [PATCH 0422/1250] Report late-bound region lint as error in `check_generic_arg_count` --- src/librustc_typeck/astconv.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a1440c3e289..1e5e00445cc 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -313,9 +313,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present. - let mut reported_late_bound_region_err = None; + let mut reported_late_bound_region_err = false; if !infer_lifetimes { if let Some(span_late) = def.has_late_bound_regions { + reported_late_bound_region_err = true; let msg = "cannot specify lifetime arguments explicitly \ if late bound lifetime parameters are present"; let note = "the late bound lifetime parameter is introduced here"; @@ -326,7 +327,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); err.emit(); - reported_late_bound_region_err = Some(true); } else { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); @@ -336,7 +336,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { multispan, |lint| lint.build(msg).emit(), ); - reported_late_bound_region_err = Some(false); } } } @@ -405,10 +404,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { true }; - let mut arg_count_mismatch = reported_late_bound_region_err.unwrap_or(false); + let mut arg_count_mismatch = reported_late_bound_region_err; let mut unexpected_spans = vec![]; - if reported_late_bound_region_err.is_none() + if !reported_late_bound_region_err && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes) { arg_count_mismatch |= check_kind_count( From 039045c49bec06f3a42aed90d3bc94520d92514e Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 21 Jan 2020 23:07:07 +0000 Subject: [PATCH 0423/1250] Move generic arg / param validation to `create_substs_for_generic_args` --- src/librustc_ast_passes/ast_validation.rs | 80 ++++-------------- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0747.md | 10 +++ src/librustc_typeck/astconv.rs | 83 ++++++++++++++++--- src/librustc_typeck/check/method/confirm.rs | 3 +- src/librustc_typeck/check/mod.rs | 1 + src/librustc_typeck/collect.rs | 2 +- .../const-arg-type-arg-misordered.rs | 10 +++ .../const-arg-type-arg-misordered.stderr | 17 ++++ .../const-param-after-const-literal-arg.rs | 10 +++ ...const-param-after-const-literal-arg.stderr | 8 ++ .../const-param-before-other-params.rs | 1 + .../const-param-before-other-params.stderr | 12 ++- src/test/ui/parser/issue-14303-fncall.rs | 2 +- src/test/ui/parser/issue-14303-fncall.stderr | 7 +- src/test/ui/parser/issue-14303-path.rs | 2 +- src/test/ui/parser/issue-14303-path.stderr | 7 +- src/test/ui/suggestions/suggest-move-types.rs | 8 +- .../ui/suggestions/suggest-move-types.stderr | 21 ++--- .../ui/traits/trait-object-vs-lifetime.rs | 2 +- .../ui/traits/trait-object-vs-lifetime.stderr | 15 ++-- 21 files changed, 192 insertions(+), 110 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0747.md create mode 100644 src/test/ui/const-generics/const-arg-type-arg-misordered.rs create mode 100644 src/test/ui/const-generics/const-arg-type-arg-misordered.stderr create mode 100644 src/test/ui/const-generics/const-param-after-const-literal-arg.rs create mode 100644 src/test/ui/const-generics/const-param-after-const-literal-arg.stderr diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 1194269e0ee..d55efeda3c1 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -594,23 +594,15 @@ impl<'a> AstValidator<'a> { } } -enum GenericPosition { - Param, - Arg, -} - -fn validate_generics_order<'a>( +fn validate_generic_param_order<'a>( sess: &Session, handler: &rustc_errors::Handler, generics: impl Iterator, Span, Option)>, - pos: GenericPosition, span: Span, ) { let mut max_param: Option = None; let mut out_of_order = FxHashMap::default(); let mut param_idents = vec![]; - let mut found_type = false; - let mut found_const = false; for (kind, bounds, span, ident) in generics { if let Some(ident) = ident { @@ -624,11 +616,6 @@ fn validate_generics_order<'a>( } Some(_) | None => *max_param = Some(kind), }; - match kind { - ParamKindOrd::Type => found_type = true, - ParamKindOrd::Const => found_const = true, - _ => {} - } } let mut ordered_params = "<".to_string(); @@ -651,42 +638,26 @@ fn validate_generics_order<'a>( } ordered_params += ">"; - let pos_str = match pos { - GenericPosition::Param => "parameter", - GenericPosition::Arg => "argument", - }; - for (param_ord, (max_param, spans)) in &out_of_order { - let mut err = handler.struct_span_err( - spans.clone(), - &format!( - "{} {pos}s must be declared prior to {} {pos}s", - param_ord, - max_param, - pos = pos_str, - ), - ); - if let GenericPosition::Param = pos { - err.span_suggestion( - span, + let mut err = + handler.struct_span_err( + spans.clone(), &format!( - "reorder the {}s: lifetimes, then types{}", - pos_str, - if sess.features_untracked().const_generics { ", then consts" } else { "" }, + "{} parameters must be declared prior to {} parameters", + param_ord, max_param, ), - ordered_params.clone(), - Applicability::MachineApplicable, ); - } + err.span_suggestion( + span, + &format!( + "reorder the parameters: lifetimes, then types{}", + if sess.features_untracked().const_generics { ", then consts" } else { "" }, + ), + ordered_params.clone(), + Applicability::MachineApplicable, + ); err.emit(); } - - // FIXME(const_generics): we shouldn't have to abort here at all, but we currently get ICEs - // if we don't. Const parameters and type parameters can currently conflict if they - // are out-of-order. - if !out_of_order.is_empty() && found_type && found_const { - FatalError.raise(); - } } impl<'a> Visitor<'a> for AstValidator<'a> { @@ -1000,24 +971,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match *generic_args { GenericArgs::AngleBracketed(ref data) => { walk_list!(self, visit_generic_arg, &data.args); - validate_generics_order( - self.session, - self.err_handler(), - data.args.iter().map(|arg| { - ( - match arg { - GenericArg::Lifetime(..) => ParamKindOrd::Lifetime, - GenericArg::Type(..) => ParamKindOrd::Type, - GenericArg::Const(..) => ParamKindOrd::Const, - }, - None, - arg.span(), - None, - ) - }), - GenericPosition::Arg, - generic_args.span(), - ); // Type bindings such as `Item = impl Debug` in `Iterator` // are allowed to contain nested `impl Trait`. @@ -1054,7 +1007,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } - validate_generics_order( + validate_generic_param_order( self.session, self.err_handler(), generics.params.iter().map(|param| { @@ -1069,7 +1022,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }; (kind, Some(&*param.bounds), param.ident.span, ident) }), - GenericPosition::Param, generics.span, ); diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index ba43b29538d..91a7b6c8958 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -417,6 +417,7 @@ E0743: include_str!("./error_codes/E0743.md"), E0744: include_str!("./error_codes/E0744.md"), E0745: include_str!("./error_codes/E0745.md"), E0746: include_str!("./error_codes/E0746.md"), +E0747: include_str!("./error_codes/E0747.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0747.md b/src/librustc_error_codes/error_codes/E0747.md new file mode 100644 index 00000000000..45b2dfd9e2b --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0747.md @@ -0,0 +1,10 @@ +Generic arguments must be provided in the same order as the corresponding generic +parameters are declared. + +Erroneous code example: + +```compile_fail,E0747 +struct S<'a, T>(&'a T); + +type X = S<(), 'static>; // error: the type argument is provided before the lifetime argument +``` diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 1e5e00445cc..4ef732a7662 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -481,6 +481,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, + arg_count_mismatch: bool, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( @@ -504,7 +505,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // methods in `subst.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut substs: SmallVec<[subst::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); - // Iterate over each segment of the path. while let Some((def_id, defs)) = stack.pop() { let mut params = defs.params.iter().peekable(); @@ -541,6 +541,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable(); + let arg_kind = |arg| match arg { + &GenericArg::Lifetime(_) => "lifetime", + &GenericArg::Type(_) => "type", + &GenericArg::Const(_) => "constant", + }; + + // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. + // If we later encounter a lifetime, we know that the arguments were provided in the + // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be + // inferred, so we can use it for diagnostics later. + let mut force_infer_lt = None; + loop { // We're going to iterate through the generic arguments that the user // provided, matching them with the generic parameters we expect. @@ -561,28 +573,74 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We expected a lifetime argument, but got a type or const // argument. That means we're inferring the lifetimes. substs.push(inferred_kind(None, param, infer_args)); + force_infer_lt = Some(arg); params.next(); } - (_, _) => { + (_, kind) => { // We expected one kind of parameter, but the user provided - // another. This is an error, but we need to handle it - // gracefully so we can report sensible errors. - // In this case, we're simply going to infer this argument. - args.next(); + // another. This is an error. However, if we already know that + // the arguments don't match up with the parameters, we won't issue + // an additional error, as the user already knows what's wrong. + if !arg_count_mismatch { + let param_kind = match kind { + GenericParamDefKind::Lifetime => "lifetime", + GenericParamDefKind::Type { .. } => "type", + GenericParamDefKind::Const => "constant", + }; + struct_span_err!( + tcx.sess, + arg.span(), + E0747, + "{} provided when a {} was expected", + arg_kind(arg), + param_kind, + ) + .emit(); + } + + // We've reported the error, but we want to make sure that this + // problem doesn't bubble down and create additional, irrelevant + // errors. In this case, we're simply going to ignore the argument + // and any following arguments. The rest of the parameters will be + // inferred. + while args.next().is_some() {} } } } - (Some(_), None) => { + (Some(&arg), None) => { // We should never be able to reach this point with well-formed input. - // Getting to this point means the user supplied more arguments than - // there are parameters. - args.next(); + // There are two situations in which we can encounter this issue. + // + // 1. The number of arguments is incorrect. In this case, an error + // will already have been emitted, and we can ignore it. This case + // also occurs when late-bound lifetime parameters are present, yet + // the lifetime arguments have also been explicitly specified by the + // user. + // 2. We've inferred some lifetimes, which have been provided later (i.e. + // after a type or const). We want to throw an error in this case. + + if !arg_count_mismatch { + let kind = arg_kind(arg); + assert_eq!(kind, "lifetime"); + let provided = + force_infer_lt.expect("lifetimes ought to have been inferred"); + struct_span_err!( + tcx.sess, + provided.span(), + E0747, + "{} provided when a {} was expected", + arg_kind(provided), + kind, + ) + .emit(); + } + + break; } (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. substs.push(inferred_kind(Some(&substs), param, infer_args)); - args.next(); params.next(); } (None, None) => break, @@ -658,7 +716,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_none() && parent_substs.is_empty()); } - let (_, potential_assoc_types) = Self::check_generic_arg_count( + let (arg_count_mismatch, potential_assoc_types) = Self::check_generic_arg_count( tcx, span, &generic_params, @@ -691,6 +749,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs, self_ty.is_some(), self_ty, + arg_count_mismatch, // Provide the generic args, and whether types should be inferred. |did| { if did == def_id { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 04cbee8c940..e3fde9159cc 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // If they were not explicitly supplied, just construct fresh // variables. let generics = self.tcx.generics_of(pick.item.def_id); - AstConv::check_generic_arg_count_for_call( + let arg_count_mismatch = AstConv::check_generic_arg_count_for_call( self.tcx, self.span, &generics, &seg, true, // `is_method_call` ); @@ -313,6 +313,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { parent_substs, false, None, + arg_count_mismatch, // Provide the generic args, and whether types should be inferred. |def_id| { // The last component of the returned tuple here is unimportant. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4f6eb20e6eb..989f98682f9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5520,6 +5520,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, + !infer_args_for_err.is_empty(), // Provide the generic args, and whether types should be inferred. |def_id| { if let Some(&PathSeg(_, index)) = diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 70586be0d04..3bdec71d3dc 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1269,7 +1269,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { let object_lifetime_defaults = tcx.object_lifetime_defaults(hir_id); - // Now create the real type parameters. + // Now create the real type and const parameters. let type_start = own_start - has_self as u32 + params.len() as u32; let mut i = 0; params.extend(ast_generics.params.iter().filter_map(|param| { diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs new file mode 100644 index 00000000000..f024eb6a957 --- /dev/null +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs @@ -0,0 +1,10 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +type Array = [T; N]; + +fn foo() -> Array { //~ ERROR constant provided when a type was expected + unimplemented!() +} + +fn main() {} diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr new file mode 100644 index 00000000000..225e1cd547e --- /dev/null +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-arg-type-arg-misordered.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0747]: constant provided when a type was expected + --> $DIR/const-arg-type-arg-misordered.rs:6:35 + | +LL | fn foo() -> Array { + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs new file mode 100644 index 00000000000..683bcc867c7 --- /dev/null +++ b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs @@ -0,0 +1,10 @@ +// check-pass + +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +struct Foo; + +impl Foo<1, A> {} // ok + +fn main() {} diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr b/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr new file mode 100644 index 00000000000..a949a6ec9ff --- /dev/null +++ b/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr @@ -0,0 +1,8 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-param-after-const-literal-arg.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index 5bdbfd8ff1f..2c81681b85e 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -1,4 +1,5 @@ #![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index 87622f7e500..fccf732de4c 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -1,14 +1,22 @@ error: lifetime parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:3:21 + --> $DIR/const-param-before-other-params.rs:4:21 | LL | fn bar(_: &'a ()) { | --------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const X: ()>` error: type parameters must be declared prior to const parameters - --> $DIR/const-param-before-other-params.rs:7:21 + --> $DIR/const-param-before-other-params.rs:8:21 | LL | fn foo(_: &T) { | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-param-before-other-params.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-14303-fncall.rs b/src/test/ui/parser/issue-14303-fncall.rs index 39694198cdb..46ece84d69e 100644 --- a/src/test/ui/parser/issue-14303-fncall.rs +++ b/src/test/ui/parser/issue-14303-fncall.rs @@ -11,7 +11,7 @@ fn foo<'a, 'b>(start: &'a usize, end: &'a usize) { let _x = (*start..*end) .map(|x| S { a: start, b: end }) .collect::>>(); - //~^ ERROR lifetime arguments must be declared prior to type arguments + //~^ ERROR type provided when a lifetime was expected } fn main() {} diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr index 8ef9f1a1a6c..cdda0d001c7 100644 --- a/src/test/ui/parser/issue-14303-fncall.stderr +++ b/src/test/ui/parser/issue-14303-fncall.stderr @@ -1,8 +1,9 @@ -error: lifetime arguments must be declared prior to type arguments - --> $DIR/issue-14303-fncall.rs:13:29 +error[E0747]: type provided when a lifetime was expected + --> $DIR/issue-14303-fncall.rs:13:26 | LL | .collect::>>(); - | ^^ + | ^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/parser/issue-14303-path.rs b/src/test/ui/parser/issue-14303-path.rs index 386d19859e4..89ef914aba2 100644 --- a/src/test/ui/parser/issue-14303-path.rs +++ b/src/test/ui/parser/issue-14303-path.rs @@ -8,6 +8,6 @@ mod foo { } fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} -//~^ ERROR lifetime arguments must be declared prior to type arguments +//~^ ERROR type provided when a lifetime was expected fn main() {} diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr index 19f2995ebee..841e63ecbe9 100644 --- a/src/test/ui/parser/issue-14303-path.stderr +++ b/src/test/ui/parser/issue-14303-path.stderr @@ -1,8 +1,9 @@ -error: lifetime arguments must be declared prior to type arguments - --> $DIR/issue-14303-path.rs:10:40 +error[E0747]: type provided when a lifetime was expected + --> $DIR/issue-14303-path.rs:10:37 | LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} - | ^^ ^^ + | ^ error: aborting due to previous error +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/suggestions/suggest-move-types.rs b/src/test/ui/suggestions/suggest-move-types.rs index 890950ea08c..6505a97de6e 100644 --- a/src/test/ui/suggestions/suggest-move-types.rs +++ b/src/test/ui/suggestions/suggest-move-types.rs @@ -33,7 +33,7 @@ struct A> { //~ ERROR associated type bindings must be declar struct Al<'a, T, M: OneWithLifetime> { //~^ ERROR associated type bindings must be declared after generic parameters -//~^^ ERROR lifetime arguments must be declared prior to type arguments +//~^^ ERROR type provided when a lifetime was expected m: M, t: &'a T, } @@ -47,7 +47,7 @@ struct B> { //~ ERROR associated ty struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { //~^ ERROR associated type bindings must be declared after generic parameters -//~^^ ERROR lifetime arguments must be declared prior to type arguments +//~^^ ERROR type provided when a lifetime was expected m: M, t: &'a T, u: &'b U, @@ -63,7 +63,7 @@ struct C> { //~ ERROR associated ty struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { //~^ ERROR associated type bindings must be declared after generic parameters -//~^^ ERROR lifetime arguments must be declared prior to type arguments +//~^^ ERROR lifetime provided when a type was expected m: M, t: &'a T, u: &'b U, @@ -79,7 +79,7 @@ struct D> { //~ ERROR associated ty struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { //~^ ERROR associated type bindings must be declared after generic parameters -//~^^ ERROR lifetime arguments must be declared prior to type arguments +//~^^ ERROR lifetime provided when a type was expected m: M, t: &'a T, u: &'b U, diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index 552fb78cd3f..07ad1a31508 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -74,29 +74,30 @@ LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime $DIR/suggest-move-types.rs:34:46 +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:34:43 | LL | struct Al<'a, T, M: OneWithLifetime> { - | ^^ + | ^ -error: lifetime arguments must be declared prior to type arguments - --> $DIR/suggest-move-types.rs:48:80 +error[E0747]: type provided when a lifetime was expected + --> $DIR/suggest-move-types.rs:48:71 | LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { - | ^^ ^^ ^^ + | ^ -error: lifetime arguments must be declared prior to type arguments +error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:64:56 | LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { - | ^^ ^^ ^^ + | ^^ -error: lifetime arguments must be declared prior to type arguments +error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:80:56 | LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { - | ^^ ^^ ^^ + | ^^ error: aborting due to 12 previous errors +For more information about this error, try `rustc --explain E0747`. diff --git a/src/test/ui/traits/trait-object-vs-lifetime.rs b/src/test/ui/traits/trait-object-vs-lifetime.rs index e0ff7349483..e885cd2f68a 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.rs +++ b/src/test/ui/traits/trait-object-vs-lifetime.rs @@ -12,6 +12,6 @@ fn main() { //~^ ERROR wrong number of lifetime arguments: expected 1, found 2 //~| ERROR wrong number of type arguments: expected 1, found 0 let _: S; - //~^ ERROR lifetime arguments must be declared prior to type arguments + //~^ ERROR type provided when a lifetime was expected //~| ERROR at least one trait is required for an object type } diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr index be1958770a4..d1e5a65c0ad 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr @@ -1,9 +1,3 @@ -error: lifetime arguments must be declared prior to type arguments - --> $DIR/trait-object-vs-lifetime.rs:14:29 - | -LL | let _: S; - | ^^^^^^^ - error[E0224]: at least one trait is required for an object type --> $DIR/trait-object-vs-lifetime.rs:9:23 | @@ -28,6 +22,13 @@ error[E0224]: at least one trait is required for an object type LL | let _: S; | ^^^^^^^^^^^^^ +error[E0747]: type provided when a lifetime was expected + --> $DIR/trait-object-vs-lifetime.rs:14:14 + | +LL | let _: S; + | ^^^^^^^^^^^^^ + error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0107`. +Some errors have detailed explanations: E0107, E0747. +For more information about an error, try `rustc --explain E0107`. From c9b7b1f73b8d256a0885506d8e7e76cd35067318 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 22 Jan 2020 01:43:24 +0000 Subject: [PATCH 0424/1250] Refactor `create_substs_for_generic_args` a little --- src/librustc/ty/mod.rs | 10 ++++ src/librustc/ty/structural_impls.rs | 7 +-- src/librustc_error_codes/error_codes/E0747.md | 7 +-- src/librustc_hir/hir.rs | 8 +++ src/librustc_typeck/astconv.rs | 52 ++++++++----------- 5 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a195c944ff2..54c0a267fe7 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -931,6 +931,16 @@ pub enum GenericParamDefKind { Const, } +impl GenericParamDefKind { + pub fn descr(&self) -> &'static str { + match self { + GenericParamDefKind::Lifetime => "lifetime", + GenericParamDefKind::Type { .. } => "type", + GenericParamDefKind::Const => "constant", + } + } +} + #[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] pub struct GenericParamDef { pub name: Symbol, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 59dd41e9d56..388afc15c85 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -19,12 +19,7 @@ use std::sync::Arc; impl fmt::Debug for ty::GenericParamDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let type_name = match self.kind { - ty::GenericParamDefKind::Lifetime => "Lifetime", - ty::GenericParamDefKind::Type { .. } => "Type", - ty::GenericParamDefKind::Const => "Const", - }; - write!(f, "{}({}, {:?}, {})", type_name, self.name, self.def_id, self.index) + write!(f, "{}({}, {:?}, {})", self.kind.descr(), self.name, self.def_id, self.index) } } diff --git a/src/librustc_error_codes/error_codes/E0747.md b/src/librustc_error_codes/error_codes/E0747.md index 45b2dfd9e2b..9bdfb5ef0bc 100644 --- a/src/librustc_error_codes/error_codes/E0747.md +++ b/src/librustc_error_codes/error_codes/E0747.md @@ -1,10 +1,11 @@ -Generic arguments must be provided in the same order as the corresponding generic -parameters are declared. +Generic arguments must be provided in the same order as the corresponding +generic parameters are declared. Erroneous code example: ```compile_fail,E0747 struct S<'a, T>(&'a T); -type X = S<(), 'static>; // error: the type argument is provided before the lifetime argument +type X = S<(), 'static>; // error: the type argument is provided before the + // lifetime argument ``` diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 8496a6ed23b..4a6871e0232 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -298,6 +298,14 @@ impl GenericArg<'_> { _ => false, } } + + pub fn descr(&self) -> &'static str { + match self { + GenericArg::Lifetime(_) => "lifetime", + GenericArg::Type(_) => "type", + GenericArg::Const(_) => "constant", + } + } } #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 4ef732a7662..a590a942e42 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -12,7 +12,7 @@ use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc::session::parse::feature_err; +use rustc::session::{parse::feature_err, Session}; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -446,6 +446,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { (arg_count_mismatch, unexpected_spans) } + /// Report an error that a generic argument did not match the generic parameter that was + /// expected. + fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static str) { + struct_span_err!( + sess, + arg.span(), + E0747, + "{} provided when a {} was expected", + arg.descr(), + kind, + ) + .emit(); + } + /// Creates the relevant generic argument substitutions /// corresponding to a set of generic parameters. This is a /// rather complex function. Let us try to explain the role @@ -541,12 +555,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut args = generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable(); - let arg_kind = |arg| match arg { - &GenericArg::Lifetime(_) => "lifetime", - &GenericArg::Type(_) => "type", - &GenericArg::Const(_) => "constant", - }; - // If we encounter a type or const when we expect a lifetime, we infer the lifetimes. // If we later encounter a lifetime, we know that the arguments were provided in the // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be @@ -582,20 +590,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // the arguments don't match up with the parameters, we won't issue // an additional error, as the user already knows what's wrong. if !arg_count_mismatch { - let param_kind = match kind { - GenericParamDefKind::Lifetime => "lifetime", - GenericParamDefKind::Type { .. } => "type", - GenericParamDefKind::Const => "constant", - }; - struct_span_err!( - tcx.sess, - arg.span(), - E0747, - "{} provided when a {} was expected", - arg_kind(arg), - param_kind, - ) - .emit(); + Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); } // We've reported the error, but we want to make sure that this @@ -607,6 +602,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } } + (Some(&arg), None) => { // We should never be able to reach this point with well-formed input. // There are two situations in which we can encounter this issue. @@ -620,29 +616,23 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // after a type or const). We want to throw an error in this case. if !arg_count_mismatch { - let kind = arg_kind(arg); + let kind = arg.descr(); assert_eq!(kind, "lifetime"); let provided = force_infer_lt.expect("lifetimes ought to have been inferred"); - struct_span_err!( - tcx.sess, - provided.span(), - E0747, - "{} provided when a {} was expected", - arg_kind(provided), - kind, - ) - .emit(); + Self::generic_arg_mismatch_err(tcx.sess, provided, kind); } break; } + (None, Some(¶m)) => { // If there are fewer arguments than parameters, it means // we're inferring the remaining arguments. substs.push(inferred_kind(Some(&substs), param, infer_args)); params.next(); } + (None, None) => break, } } From dff64eb4b6b6a1cd2ae4e122b70a632f52f1dada Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 23 Jan 2020 00:41:33 +0000 Subject: [PATCH 0425/1250] Make return value of `check_generic_arg_count` semantically clearer --- src/librustc/ty/mod.rs | 2 +- src/librustc/ty/structural_impls.rs | 6 ------ src/librustc_typeck/astconv.rs | 20 ++++++++++++-------- src/librustc_typeck/check/method/confirm.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 7 ++++--- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 54c0a267fe7..7df1383f86a 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -941,7 +941,7 @@ impl GenericParamDefKind { } } -#[derive(Clone, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Debug, RustcEncodable, RustcDecodable, HashStable)] pub struct GenericParamDef { pub name: Symbol, pub def_id: DefId, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 388afc15c85..03ff1b8a317 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -17,12 +17,6 @@ use std::fmt; use std::rc::Rc; use std::sync::Arc; -impl fmt::Debug for ty::GenericParamDef { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}({}, {:?}, {})", self.kind.descr(), self.name, self.def_id, self.index) - } -} - impl fmt::Debug for ty::TraitDef { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { ty::tls::with(|tcx| { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a590a942e42..b3131c159a6 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -132,6 +132,10 @@ enum GenericArgPosition { MethodCall, } +/// A marker denoting that the generic arguments that were +/// provided did not match the respective generic parameters. +pub struct GenericArgCountMismatch; + impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ast_region_to_region( &self, @@ -262,7 +266,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def: &ty::Generics, seg: &hir::PathSegment<'_>, is_method_call: bool, - ) -> bool { + ) -> Result<(), GenericArgCountMismatch> { let empty_args = hir::GenericArgs::none(); let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def); Self::check_generic_arg_count( @@ -287,7 +291,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { position: GenericArgPosition, has_self: bool, infer_args: bool, - ) -> (bool, Vec) { + ) -> (Result<(), GenericArgCountMismatch>, Vec) { // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. // that lifetimes will proceed types. So it suffices to check the number of each generic // arguments in order to validate them with respect to the generic parameters. @@ -443,7 +447,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ); } - (arg_count_mismatch, unexpected_spans) + (if arg_count_mismatch { Err(GenericArgCountMismatch) } else { Ok(()) }, unexpected_spans) } /// Report an error that a generic argument did not match the generic parameter that was @@ -495,7 +499,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, - arg_count_mismatch: bool, + arg_count_correct: Result<(), GenericArgCountMismatch>, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( @@ -589,7 +593,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // another. This is an error. However, if we already know that // the arguments don't match up with the parameters, we won't issue // an additional error, as the user already knows what's wrong. - if !arg_count_mismatch { + if arg_count_correct.is_ok() { Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); } @@ -615,7 +619,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // 2. We've inferred some lifetimes, which have been provided later (i.e. // after a type or const). We want to throw an error in this case. - if !arg_count_mismatch { + if arg_count_correct.is_ok() { let kind = arg.descr(); assert_eq!(kind, "lifetime"); let provided = @@ -706,7 +710,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_none() && parent_substs.is_empty()); } - let (arg_count_mismatch, potential_assoc_types) = Self::check_generic_arg_count( + let (arg_count_correct, potential_assoc_types) = Self::check_generic_arg_count( tcx, span, &generic_params, @@ -739,7 +743,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs, self_ty.is_some(), self_ty, - arg_count_mismatch, + arg_count_correct, // Provide the generic args, and whether types should be inferred. |did| { if did == def_id { diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index e3fde9159cc..38773abeef2 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -299,7 +299,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { // If they were not explicitly supplied, just construct fresh // variables. let generics = self.tcx.generics_of(pick.item.def_id); - let arg_count_mismatch = AstConv::check_generic_arg_count_for_call( + let arg_count_correct = AstConv::check_generic_arg_count_for_call( self.tcx, self.span, &generics, &seg, true, // `is_method_call` ); @@ -313,7 +313,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { parent_substs, false, None, - arg_count_mismatch, + arg_count_correct, // Provide the generic args, and whether types should be inferred. |def_id| { // The last component of the returned tuple here is unimportant. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 989f98682f9..426ba0ddaaa 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -87,7 +87,7 @@ mod upvar; mod wfcheck; pub mod writeback; -use crate::astconv::{AstConv, PathSeg}; +use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg}; use crate::middle::lang_items; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; @@ -5454,7 +5454,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // checking here. let suppress_errors = AstConv::check_generic_arg_count_for_call( tcx, span, &generics, &seg, false, // `is_method_call` - ); + ) + .is_err(); if suppress_errors { infer_args_for_err.insert(index); self.set_tainted_by_errors(); // See issue #53251. @@ -5520,7 +5521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, - !infer_args_for_err.is_empty(), + if infer_args_for_err.is_empty() { Ok(()) } else { Err(GenericArgCountMismatch) }, // Provide the generic args, and whether types should be inferred. |def_id| { if let Some(&PathSeg(_, index)) = From 104131c9d487c943d962f4d88490aa7bcf2fa2de Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 25 Jan 2020 00:49:43 +0000 Subject: [PATCH 0426/1250] Use `Result` instead of `bool` throughout --- src/librustc_typeck/astconv.rs | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index b3131c159a6..ae8dbfe9c39 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -317,10 +317,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present. - let mut reported_late_bound_region_err = false; + let mut explicit_lifetimes = Ok(()); if !infer_lifetimes { if let Some(span_late) = def.has_late_bound_regions { - reported_late_bound_region_err = true; + explicit_lifetimes = Err(GenericArgCountMismatch); let msg = "cannot specify lifetime arguments explicitly \ if late bound lifetime parameters are present"; let note = "the late bound lifetime parameter is introduced here"; @@ -354,7 +354,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // For kinds without defaults (e.g.., lifetimes), `required == permitted`. // For other kinds (i.e., types), `permitted` may be greater than `required`. if required <= provided && provided <= permitted { - return false; + return Ok(()); } // Unfortunately lifetime and type parameter mismatches are typically styled @@ -405,49 +405,49 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.emit(); - true + Err(GenericArgCountMismatch) }; - let mut arg_count_mismatch = reported_late_bound_region_err; + let mut arg_count_correct = explicit_lifetimes; let mut unexpected_spans = vec![]; - if !reported_late_bound_region_err + if arg_count_correct.is_ok() && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes) { - arg_count_mismatch |= check_kind_count( + arg_count_correct = arg_count_correct.and(check_kind_count( "lifetime", param_counts.lifetimes, param_counts.lifetimes, arg_counts.lifetimes, 0, &mut unexpected_spans, - ); + )); } // FIXME(const_generics:defaults) if !infer_args || arg_counts.consts > param_counts.consts { - arg_count_mismatch |= check_kind_count( + arg_count_correct = arg_count_correct.and(check_kind_count( "const", param_counts.consts, param_counts.consts, arg_counts.consts, arg_counts.lifetimes + arg_counts.types, &mut unexpected_spans, - ); + )); } // Note that type errors are currently be emitted *after* const errors. if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize { - arg_count_mismatch |= check_kind_count( + arg_count_correct = arg_count_correct.and(check_kind_count( "type", param_counts.types - defaults.types - has_self as usize, param_counts.types - has_self as usize, arg_counts.types, arg_counts.lifetimes, &mut unexpected_spans, - ); + )); } - (if arg_count_mismatch { Err(GenericArgCountMismatch) } else { Ok(()) }, unexpected_spans) + (arg_count_correct, unexpected_spans) } /// Report an error that a generic argument did not match the generic parameter that was From 33143fd756f3765daa00809da2d1f66b5d3ac9fc Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 25 Jan 2020 22:28:31 +0000 Subject: [PATCH 0427/1250] Be explicit about whether `GenericArgCountMismatch` arose from a fatal error --- src/librustc_typeck/astconv.rs | 8 +++++--- src/librustc_typeck/check/mod.rs | 16 ++++++++++------ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ae8dbfe9c39..42613532655 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -134,7 +134,8 @@ enum GenericArgPosition { /// A marker denoting that the generic arguments that were /// provided did not match the respective generic parameters. -pub struct GenericArgCountMismatch; +/// The field indicates whether a fatal error was reported (`Some`), or just a lint (`None`). +pub struct GenericArgCountMismatch(pub Option); impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ast_region_to_region( @@ -320,7 +321,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut explicit_lifetimes = Ok(()); if !infer_lifetimes { if let Some(span_late) = def.has_late_bound_regions { - explicit_lifetimes = Err(GenericArgCountMismatch); let msg = "cannot specify lifetime arguments explicitly \ if late bound lifetime parameters are present"; let note = "the late bound lifetime parameter is introduced here"; @@ -328,10 +328,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if position == GenericArgPosition::Value && arg_counts.lifetimes != param_counts.lifetimes { + explicit_lifetimes = Err(GenericArgCountMismatch(Some(ErrorReported))); let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); err.emit(); } else { + explicit_lifetimes = Err(GenericArgCountMismatch(None)); let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); tcx.struct_span_lint_hir( @@ -405,7 +407,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.emit(); - Err(GenericArgCountMismatch) + Err(GenericArgCountMismatch(Some(ErrorReported))) }; let mut arg_count_correct = explicit_lifetimes; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 426ba0ddaaa..daedeafbcc3 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5452,11 +5452,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. - let suppress_errors = AstConv::check_generic_arg_count_for_call( - tcx, span, &generics, &seg, false, // `is_method_call` - ) - .is_err(); - if suppress_errors { + if let Err(GenericArgCountMismatch(Some(ErrorReported))) = + AstConv::check_generic_arg_count_for_call( + tcx, span, &generics, &seg, false, // `is_method_call` + ) + { infer_args_for_err.insert(index); self.set_tainted_by_errors(); // See issue #53251. } @@ -5521,7 +5521,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, - if infer_args_for_err.is_empty() { Ok(()) } else { Err(GenericArgCountMismatch) }, + if infer_args_for_err.is_empty() { + Ok(()) + } else { + Err(GenericArgCountMismatch(Some(ErrorReported))) + }, // Provide the generic args, and whether types should be inferred. |def_id| { if let Some(&PathSeg(_, index)) = From b44b4ca60257d80a431b4c1aceb3c1e09fb8389e Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 21 Feb 2020 16:46:14 -0800 Subject: [PATCH 0428/1250] rustfmt you cruel mistress --- src/librustc_expand/expand.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 0c87d3fe8fc..ab372a41e69 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -14,8 +14,8 @@ use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_parse::DirectoryOwnership; -use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; +use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::source_map::respan; use rustc_span::symbol::{sym, Symbol}; @@ -1099,7 +1099,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { attr.span, ast::CRATE_NODE_ID, "unused doc comment", - BuiltinLintDiagnostics::UnusedDocComment(attr.span)); + BuiltinLintDiagnostics::UnusedDocComment(attr.span), + ); } } } From 88d6ab84c94dceebeb21cf98eef7e3e89acb69c7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 22 Feb 2020 12:24:05 +0100 Subject: [PATCH 0429/1250] move const_eval.rs into the module folder --- src/librustc_mir/{const_eval.rs => const_eval/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/librustc_mir/{const_eval.rs => const_eval/mod.rs} (100%) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval/mod.rs similarity index 100% rename from src/librustc_mir/const_eval.rs rename to src/librustc_mir/const_eval/mod.rs From 76fb26b8c2ad48a8194dceb06073b636ca7ae6d6 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 22 Feb 2020 01:55:35 +0000 Subject: [PATCH 0430/1250] Add invalid argument spans to `GenericArgCountMismatch` --- src/librustc_ast_passes/ast_validation.rs | 2 +- src/librustc_typeck/astconv.rs | 72 ++++++++++++--------- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/mod.rs | 8 +-- 4 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index d55efeda3c1..25455ff629b 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -8,7 +8,7 @@ use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{error_code, struct_span_err, Applicability, FatalError}; +use rustc_errors::{error_code, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY; use rustc_session::lint::LintBuffer; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 42613532655..9a80452aef3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -134,8 +134,12 @@ enum GenericArgPosition { /// A marker denoting that the generic arguments that were /// provided did not match the respective generic parameters. -/// The field indicates whether a fatal error was reported (`Some`), or just a lint (`None`). -pub struct GenericArgCountMismatch(pub Option); +pub struct GenericArgCountMismatch { + /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`). + pub reported: Option, + /// A list of spans of arguments provided that were not valid. + pub invalid_args: Vec, +} impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pub fn ast_region_to_region( @@ -279,7 +283,6 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { def.parent.is_none() && def.has_self, // `has_self` seg.infer_args || suppress_mismatch, // `infer_args` ) - .0 } /// Checks that the correct number of generic arguments have been provided. @@ -292,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { position: GenericArgPosition, has_self: bool, infer_args: bool, - ) -> (Result<(), GenericArgCountMismatch>, Vec) { + ) -> Result<(), GenericArgCountMismatch> { // At this stage we are guaranteed that the generic arguments are in the correct order, e.g. // that lifetimes will proceed types. So it suffices to check the number of each generic // arguments in order to validate them with respect to the generic parameters. @@ -328,12 +331,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if position == GenericArgPosition::Value && arg_counts.lifetimes != param_counts.lifetimes { - explicit_lifetimes = Err(GenericArgCountMismatch(Some(ErrorReported))); + explicit_lifetimes = Err(true); let mut err = tcx.sess.struct_span_err(span, msg); err.span_note(span_late, note); err.emit(); } else { - explicit_lifetimes = Err(GenericArgCountMismatch(None)); + explicit_lifetimes = Err(false); let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); tcx.struct_span_lint_hir( @@ -407,7 +410,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } err.emit(); - Err(GenericArgCountMismatch(Some(ErrorReported))) + Err(true) }; let mut arg_count_correct = explicit_lifetimes; @@ -416,40 +419,46 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if arg_count_correct.is_ok() && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes) { - arg_count_correct = arg_count_correct.and(check_kind_count( + arg_count_correct = check_kind_count( "lifetime", param_counts.lifetimes, param_counts.lifetimes, arg_counts.lifetimes, 0, &mut unexpected_spans, - )); + ) + .and(arg_count_correct); } // FIXME(const_generics:defaults) if !infer_args || arg_counts.consts > param_counts.consts { - arg_count_correct = arg_count_correct.and(check_kind_count( + arg_count_correct = check_kind_count( "const", param_counts.consts, param_counts.consts, arg_counts.consts, arg_counts.lifetimes + arg_counts.types, &mut unexpected_spans, - )); + ) + .and(arg_count_correct); } // Note that type errors are currently be emitted *after* const errors. if !infer_args || arg_counts.types > param_counts.types - defaults.types - has_self as usize { - arg_count_correct = arg_count_correct.and(check_kind_count( + arg_count_correct = check_kind_count( "type", param_counts.types - defaults.types - has_self as usize, param_counts.types - has_self as usize, arg_counts.types, arg_counts.lifetimes, &mut unexpected_spans, - )); + ) + .and(arg_count_correct); } - (arg_count_correct, unexpected_spans) + arg_count_correct.map_err(|reported_err| GenericArgCountMismatch { + reported: if reported_err { Some(ErrorReported) } else { None }, + invalid_args: unexpected_spans, + }) } /// Report an error that a generic argument did not match the generic parameter that was @@ -501,7 +510,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs: &[subst::GenericArg<'tcx>], has_self: bool, self_ty: Option>, - arg_count_correct: Result<(), GenericArgCountMismatch>, + arg_count_correct: bool, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( @@ -595,7 +604,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // another. This is an error. However, if we already know that // the arguments don't match up with the parameters, we won't issue // an additional error, as the user already knows what's wrong. - if arg_count_correct.is_ok() { + if arg_count_correct { Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr()); } @@ -621,7 +630,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // 2. We've inferred some lifetimes, which have been provided later (i.e. // after a type or const). We want to throw an error in this case. - if arg_count_correct.is_ok() { + if arg_count_correct { let kind = arg.descr(); assert_eq!(kind, "lifetime"); let provided = @@ -686,7 +695,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_args: &'a hir::GenericArgs<'_>, infer_args: bool, self_ty: Option>, - ) -> (SubstsRef<'tcx>, Vec>, Vec) { + ) -> (SubstsRef<'tcx>, Vec>, Result<(), GenericArgCountMismatch>) + { // If the type is parameterized by this region, then replace this // region with the current anon region binding (in other words, // whatever & would get replaced with). @@ -712,7 +722,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { assert!(self_ty.is_none() && parent_substs.is_empty()); } - let (arg_count_correct, potential_assoc_types) = Self::check_generic_arg_count( + let arg_count_correct = Self::check_generic_arg_count( tcx, span, &generic_params, @@ -745,7 +755,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { parent_substs, self_ty.is_some(), self_ty, - arg_count_correct, + arg_count_correct.is_ok(), // Provide the generic args, and whether types should be inferred. |did| { if did == def_id { @@ -858,7 +868,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { generic_params, self_ty, substs ); - (substs, assoc_bindings, potential_assoc_types) + (substs, assoc_bindings, arg_count_correct) } crate fn create_substs_for_associated_item( @@ -989,7 +999,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, speculative: bool, - ) -> Vec { + ) -> Result<(), GenericArgCountMismatch> { let trait_def_id = trait_ref.trait_def_id(); debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id); @@ -1006,7 +1016,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } else { trait_ref.path.span }; - let (substs, assoc_bindings, potential_assoc_types) = self.create_substs_for_ast_trait_ref( + let (substs, assoc_bindings, arg_count_correct) = self.create_substs_for_ast_trait_ref( path_span, trait_def_id, self_ty, @@ -1036,7 +1046,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_ref, bounds, poly_trait_ref ); - potential_assoc_types + arg_count_correct } /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct @@ -1064,7 +1074,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { constness: Constness, self_ty: Ty<'tcx>, bounds: &mut Bounds<'tcx>, - ) -> Vec { + ) -> Result<(), GenericArgCountMismatch> { self.instantiate_poly_trait_ref_inner( &poly_trait_ref.trait_ref, poly_trait_ref.span, @@ -1153,7 +1163,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { trait_def_id: DefId, self_ty: Ty<'tcx>, trait_segment: &'a hir::PathSegment<'a>, - ) -> (SubstsRef<'tcx>, Vec>, Vec) { + ) -> (SubstsRef<'tcx>, Vec>, Result<(), GenericArgCountMismatch>) + { debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment); self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment); @@ -1498,13 +1509,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut potential_assoc_types = Vec::new(); let dummy_self = self.tcx().types.trait_object_dummy_self; for trait_bound in trait_bounds.iter().rev() { - let cur_potential_assoc_types = self.instantiate_poly_trait_ref( + if let Err(GenericArgCountMismatch { + invalid_args: cur_potential_assoc_types, .. + }) = self.instantiate_poly_trait_ref( trait_bound, Constness::NotConst, dummy_self, &mut bounds, - ); - potential_assoc_types.extend(cur_potential_assoc_types.into_iter()); + ) { + potential_assoc_types.extend(cur_potential_assoc_types.into_iter()); + } } // Expand trait aliases recursively and check that only one regular (non-auto) trait diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 38773abeef2..108affe5a86 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -313,7 +313,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { parent_substs, false, None, - arg_count_correct, + arg_count_correct.is_ok(), // Provide the generic args, and whether types should be inferred. |def_id| { // The last component of the returned tuple here is unimportant. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index daedeafbcc3..3738afb2c3d 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5452,7 +5452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // parameter internally, but we don't allow users to specify the // parameter's value explicitly, so we have to do some error- // checking here. - if let Err(GenericArgCountMismatch(Some(ErrorReported))) = + if let Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }) = AstConv::check_generic_arg_count_for_call( tcx, span, &generics, &seg, false, // `is_method_call` ) @@ -5521,11 +5521,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &[][..], has_self, self_ty, - if infer_args_for_err.is_empty() { - Ok(()) - } else { - Err(GenericArgCountMismatch(Some(ErrorReported))) - }, + infer_args_for_err.is_empty(), // Provide the generic args, and whether types should be inferred. |def_id| { if let Some(&PathSeg(_, index)) = From e372ad48001920a77464c94cb2f48702af7e9ad3 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 22 Feb 2020 01:56:05 +0000 Subject: [PATCH 0431/1250] Expand the documentation for E0747 --- src/librustc_error_codes/error_codes/E0747.md | 9 +++++++++ .../const-param-after-const-literal-arg.rs | 2 +- .../const-param-after-const-literal-arg.stderr | 8 -------- .../ui/const-generics/const-param-before-other-params.rs | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) delete mode 100644 src/test/ui/const-generics/const-param-after-const-literal-arg.stderr diff --git a/src/librustc_error_codes/error_codes/E0747.md b/src/librustc_error_codes/error_codes/E0747.md index 9bdfb5ef0bc..df1afbfef46 100644 --- a/src/librustc_error_codes/error_codes/E0747.md +++ b/src/librustc_error_codes/error_codes/E0747.md @@ -9,3 +9,12 @@ struct S<'a, T>(&'a T); type X = S<(), 'static>; // error: the type argument is provided before the // lifetime argument ``` + +The argument order should be changed to match the parameter declaration +order, as in the following. + +``` +struct S<'a, T>(&'a T); + +type X = S<'static, ()>; // ok +``` diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs index 683bcc867c7..19c4120eb2f 100644 --- a/src/test/ui/const-generics/const-param-after-const-literal-arg.rs +++ b/src/test/ui/const-generics/const-param-after-const-literal-arg.rs @@ -1,7 +1,7 @@ // check-pass +#![allow(incomplete_features)] #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash struct Foo; diff --git a/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr b/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr deleted file mode 100644 index a949a6ec9ff..00000000000 --- a/src/test/ui/const-generics/const-param-after-const-literal-arg.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/const-param-after-const-literal-arg.rs:3:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - diff --git a/src/test/ui/const-generics/const-param-before-other-params.rs b/src/test/ui/const-generics/const-param-before-other-params.rs index 2c81681b85e..756e961ce91 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.rs +++ b/src/test/ui/const-generics/const-param-before-other-params.rs @@ -1,5 +1,5 @@ +#![allow(incomplete_features)] #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash fn bar(_: &'a ()) { //~^ ERROR lifetime parameters must be declared prior to const parameters From bead79ebc6d0f605f42a0f8315ce9f5fe5764b99 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 22 Feb 2020 02:35:24 +0000 Subject: [PATCH 0432/1250] Add note regarding argument ordering --- src/librustc_typeck/astconv.rs | 8 +++++--- .../const-generics/const-arg-type-arg-misordered.stderr | 2 ++ .../const-generics/const-param-before-other-params.stderr | 8 -------- src/test/ui/parser/issue-14303-fncall.stderr | 2 ++ src/test/ui/parser/issue-14303-path.stderr | 2 ++ src/test/ui/suggestions/suggest-move-types.stderr | 8 ++++++++ src/test/ui/traits/trait-object-vs-lifetime.stderr | 2 ++ 7 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9a80452aef3..49f38d86d91 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -464,15 +464,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Report an error that a generic argument did not match the generic parameter that was /// expected. fn generic_arg_mismatch_err(sess: &Session, arg: &GenericArg<'_>, kind: &'static str) { - struct_span_err!( + let mut err = struct_span_err!( sess, arg.span(), E0747, "{} provided when a {} was expected", arg.descr(), kind, - ) - .emit(); + ); + // This note will be true as long as generic parameters are strictly ordered by their kind. + err.note(&format!("{} arguments must be provided before {} arguments", kind, arg.descr())); + err.emit(); } /// Creates the relevant generic argument substitutions diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr index 225e1cd547e..150a6011c2c 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -11,6 +11,8 @@ error[E0747]: constant provided when a type was expected | LL | fn foo() -> Array { | ^ + | + = note: type arguments must be provided before constant arguments error: aborting due to previous error diff --git a/src/test/ui/const-generics/const-param-before-other-params.stderr b/src/test/ui/const-generics/const-param-before-other-params.stderr index fccf732de4c..9b18b8c79ed 100644 --- a/src/test/ui/const-generics/const-param-before-other-params.stderr +++ b/src/test/ui/const-generics/const-param-before-other-params.stderr @@ -10,13 +10,5 @@ error: type parameters must be declared prior to const parameters LL | fn foo(_: &T) { | --------------^- help: reorder the parameters: lifetimes, then types, then consts: `` -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/const-param-before-other-params.rs:1:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-14303-fncall.stderr b/src/test/ui/parser/issue-14303-fncall.stderr index cdda0d001c7..10954223713 100644 --- a/src/test/ui/parser/issue-14303-fncall.stderr +++ b/src/test/ui/parser/issue-14303-fncall.stderr @@ -3,6 +3,8 @@ error[E0747]: type provided when a lifetime was expected | LL | .collect::>>(); | ^ + | + = note: lifetime arguments must be provided before type arguments error: aborting due to previous error diff --git a/src/test/ui/parser/issue-14303-path.stderr b/src/test/ui/parser/issue-14303-path.stderr index 841e63ecbe9..c1ad2332b5b 100644 --- a/src/test/ui/parser/issue-14303-path.stderr +++ b/src/test/ui/parser/issue-14303-path.stderr @@ -3,6 +3,8 @@ error[E0747]: type provided when a lifetime was expected | LL | fn bar<'a, 'b, 'c, T>(x: foo::X<'a, T, 'b, 'c>) {} | ^ + | + = note: lifetime arguments must be provided before type arguments error: aborting due to previous error diff --git a/src/test/ui/suggestions/suggest-move-types.stderr b/src/test/ui/suggestions/suggest-move-types.stderr index 07ad1a31508..ac91813f928 100644 --- a/src/test/ui/suggestions/suggest-move-types.stderr +++ b/src/test/ui/suggestions/suggest-move-types.stderr @@ -79,24 +79,32 @@ error[E0747]: type provided when a lifetime was expected | LL | struct Al<'a, T, M: OneWithLifetime> { | ^ + | + = note: lifetime arguments must be provided before type arguments error[E0747]: type provided when a lifetime was expected --> $DIR/suggest-move-types.rs:48:71 | LL | struct Bl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { | ^ + | + = note: lifetime arguments must be provided before type arguments error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:64:56 | LL | struct Cl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { | ^^ + | + = note: type arguments must be provided before lifetime arguments error[E0747]: lifetime provided when a type was expected --> $DIR/suggest-move-types.rs:80:56 | LL | struct Dl<'a, 'b, 'c, T, U, V, M: ThreeWithLifetime> { | ^^ + | + = note: type arguments must be provided before lifetime arguments error: aborting due to 12 previous errors diff --git a/src/test/ui/traits/trait-object-vs-lifetime.stderr b/src/test/ui/traits/trait-object-vs-lifetime.stderr index d1e5a65c0ad..04529fb8cfa 100644 --- a/src/test/ui/traits/trait-object-vs-lifetime.stderr +++ b/src/test/ui/traits/trait-object-vs-lifetime.stderr @@ -27,6 +27,8 @@ error[E0747]: type provided when a lifetime was expected | LL | let _: S; | ^^^^^^^^^^^^^ + | + = note: lifetime arguments must be provided before type arguments error: aborting due to 5 previous errors From d15a98b87815850ef9dd11564e896b6f19b724c3 Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Sat, 22 Feb 2020 14:03:46 +0100 Subject: [PATCH 0433/1250] Stabilize const for integer {to,from}_{be,le,ne}_bytes methods All of these functions can be implemented simply and naturally as const functions, e.g. u32::from_le_bytes can be implemented as (bytes[0] as u32) | (bytes[1] as u32) << 8 | (bytes[2] as u32) << 16 | (bytes[3] as u32) << 24 So stabilizing the constness will not expose that internally they are implemented using transmute which is not const in stable. --- src/libcore/lib.rs | 1 - src/libcore/num/mod.rs | 28 +++++++++++-------- .../ui/consts/const-int-conversion-rpass.rs | 2 -- 3 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index bca96b77812..00909094cd0 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -131,7 +131,6 @@ #![feature(rtm_target_feature)] #![feature(f16c_target_feature)] #![feature(hexagon_target_feature)] -#![feature(const_int_conversion)] #![feature(const_transmute)] #![feature(structural_match)] #![feature(abi_unadjusted)] diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 6f55e7c8be8..22897680567 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -2195,7 +2195,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -2215,7 +2215,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -2250,7 +2250,8 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[allow_internal_unstable(const_transmute)] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -2284,7 +2285,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -2317,7 +2318,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -2360,7 +2361,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[allow_internal_unstable(const_transmute)] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them @@ -4132,7 +4134,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_be_bytes(); assert_eq!(bytes, ", $be_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn to_be_bytes(self) -> [u8; mem::size_of::()] { self.to_be().to_ne_bytes() @@ -4152,7 +4154,7 @@ let bytes = ", $swap_op, stringify!($SelfT), ".to_le_bytes(); assert_eq!(bytes, ", $le_bytes, "); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn to_le_bytes(self) -> [u8; mem::size_of::()] { self.to_le().to_ne_bytes() @@ -4187,7 +4189,8 @@ assert_eq!( ); ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[allow_internal_unstable(const_transmute)] #[inline] pub const fn to_ne_bytes(self) -> [u8; mem::size_of::()] { // SAFETY: integers are plain old datatypes so we can always transmute them to @@ -4221,7 +4224,7 @@ fn read_be_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn from_be_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_be(Self::from_ne_bytes(bytes)) @@ -4254,7 +4257,7 @@ fn read_le_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] #[inline] pub const fn from_le_bytes(bytes: [u8; mem::size_of::()]) -> Self { Self::from_le(Self::from_ne_bytes(bytes)) @@ -4297,7 +4300,8 @@ fn read_ne_", stringify!($SelfT), "(input: &mut &[u8]) -> ", stringify!($SelfT), } ```"), #[stable(feature = "int_to_from_bytes", since = "1.32.0")] - #[rustc_const_unstable(feature = "const_int_conversion", issue = "53718")] + #[rustc_const_stable(feature = "const_int_conversion", since = "1.43.0")] + #[allow_internal_unstable(const_transmute)] #[inline] pub const fn from_ne_bytes(bytes: [u8; mem::size_of::()]) -> Self { // SAFETY: integers are plain old datatypes so we can always transmute to them diff --git a/src/test/ui/consts/const-int-conversion-rpass.rs b/src/test/ui/consts/const-int-conversion-rpass.rs index d52dbbae1e7..6484169dd9a 100644 --- a/src/test/ui/consts/const-int-conversion-rpass.rs +++ b/src/test/ui/consts/const-int-conversion-rpass.rs @@ -1,7 +1,5 @@ // run-pass -#![feature(const_int_conversion)] - const REVERSE: u32 = 0x12345678_u32.reverse_bits(); const FROM_BE_BYTES: i32 = i32::from_be_bytes([0x12, 0x34, 0x56, 0x78]); const FROM_LE_BYTES: i32 = i32::from_le_bytes([0x12, 0x34, 0x56, 0x78]); From 20c9a40fec886826a3e7c4ec0c33ea4692f2c6a8 Mon Sep 17 00:00:00 2001 From: Maxim Zholobak Date: Sat, 22 Feb 2020 16:07:05 +0200 Subject: [PATCH 0434/1250] Rename CodeMap to SourceMap follow up --- src/librustc/ich/hcx.rs | 2 +- src/librustc/middle/stability.rs | 4 +-- src/librustc_ast_pretty/pprust.rs | 20 ++++++------ src/librustc_driver/pretty.rs | 4 +-- src/librustc_errors/json.rs | 8 ++--- src/librustc_errors/lib.rs | 32 +++++++++---------- src/librustc_hir/print.rs | 8 ++--- .../infer/error_reporting/mod.rs | 8 ++--- src/librustc_parse/parser/expr.rs | 4 +-- src/librustc_passes/liveness.rs | 8 ++--- src/librustc_resolve/diagnostics.rs | 14 ++++---- src/librustc_resolve/late/diagnostics.rs | 22 ++++++------- src/librustc_save_analysis/dump_visitor.rs | 4 +-- src/librustc_save_analysis/lib.rs | 10 +++--- src/librustc_session/parse.rs | 10 +++--- src/librustc_span/caching_source_map_view.rs | 8 ++--- src/librustc_typeck/check/demand.rs | 24 +++++++------- src/librustc_typeck/coherence/orphan.rs | 4 +-- src/librustdoc/clean/mod.rs | 14 ++++---- src/librustdoc/core.rs | 2 +- src/librustdoc/html/highlight.rs | 4 +-- .../passes/check_code_block_syntax.rs | 4 +-- src/librustdoc/test.rs | 4 +-- src/libsyntax/util/comments.rs | 4 +-- 24 files changed, 113 insertions(+), 113 deletions(-) diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 9e2db35dc6d..1a9c5d1f13f 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -149,7 +149,7 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn source_map(&mut self) -> &mut CachingSourceMapView<'a> { match self.caching_source_map { - Some(ref mut cm) => cm, + Some(ref mut sm) => sm, ref mut none => { *none = Some(CachingSourceMapView::new(self.raw_source_map)); none.as_mut().unwrap() diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index dd30fb23c2e..7b5faa2423a 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -106,10 +106,10 @@ pub fn report_unstable( }; let msp: MultiSpan = span.into(); - let cm = &sess.parse_sess.source_map(); + let sm = &sess.parse_sess.source_map(); let span_key = msp.primary_span().and_then(|sp: Span| { if !sp.is_dummy() { - let file = cm.lookup_char_pos(sp.lo()).file; + let file = sm.lookup_char_pos(sp.lo()).file; if file.name.is_macros() { None } else { Some(span) } } else { None diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 6e1567ce34e..2f7d33b97ce 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -47,15 +47,15 @@ pub struct NoAnn; impl PpAnn for NoAnn {} pub struct Comments<'a> { - cm: &'a SourceMap, + sm: &'a SourceMap, comments: Vec, current: usize, } impl<'a> Comments<'a> { - pub fn new(cm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> { - let comments = comments::gather_comments(cm, filename, input); - Comments { cm, comments, current: 0 } + pub fn new(sm: &'a SourceMap, filename: FileName, input: String) -> Comments<'a> { + let comments = comments::gather_comments(sm, filename, input); + Comments { sm, comments, current: 0 } } pub fn next(&self) -> Option { @@ -71,8 +71,8 @@ impl<'a> Comments<'a> { if cmnt.style != comments::Trailing { return None; } - let span_line = self.cm.lookup_char_pos(span.hi()); - let comment_line = self.cm.lookup_char_pos(cmnt.pos); + let span_line = self.sm.lookup_char_pos(span.hi()); + let comment_line = self.sm.lookup_char_pos(cmnt.pos); let next = next_pos.unwrap_or_else(|| cmnt.pos + BytePos(1)); if span.hi() < cmnt.pos && cmnt.pos < next && span_line.line == comment_line.line { return Some(cmnt); @@ -95,7 +95,7 @@ crate const INDENT_UNIT: usize = 4; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments to copy forward. pub fn print_crate<'a>( - cm: &'a SourceMap, + sm: &'a SourceMap, krate: &ast::Crate, filename: FileName, input: String, @@ -106,7 +106,7 @@ pub fn print_crate<'a>( ) -> String { let mut s = State { s: pp::mk_printer(), - comments: Some(Comments::new(cm, filename, input)), + comments: Some(Comments::new(sm, filename, input)), ann, is_expanded, }; @@ -522,8 +522,8 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere self.hardbreak(); } } - if let Some(cm) = self.comments() { - cm.current += 1; + if let Some(cmnts) = self.comments() { + cmnts.current += 1; } } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index d4f01490499..236a7243998 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -452,8 +452,8 @@ pub fn print_after_hir_lowering<'tcx>( call_with_pp_support_hir(&s, tcx, move |annotation, krate| { debug!("pretty printing source code {:?}", s); let sess = annotation.sess(); - let cm = sess.source_map(); - *out = pprust_hir::print_crate(cm, krate, src_name, src, annotation.pp_ann()) + let sm = sess.source_map(); + *out = pprust_hir::print_crate(sm, krate, src_name, src, annotation.pp_ann()) }) } diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs index ffdff6acec5..1f6e268b506 100644 --- a/src/librustc_errors/json.rs +++ b/src/librustc_errors/json.rs @@ -373,13 +373,13 @@ impl DiagnosticSpan { impl DiagnosticSpanLine { fn line_from_source_file( - fm: &rustc_span::SourceFile, + sf: &rustc_span::SourceFile, index: usize, h_start: usize, h_end: usize, ) -> DiagnosticSpanLine { DiagnosticSpanLine { - text: fm.get_line(index).map_or(String::new(), |l| l.into_owned()), + text: sf.get_line(index).map_or(String::new(), |l| l.into_owned()), highlight_start: h_start, highlight_end: h_end, } @@ -392,13 +392,13 @@ impl DiagnosticSpanLine { je.sm .span_to_lines(span) .map(|lines| { - let fm = &*lines.file; + let sf = &*lines.file; lines .lines .iter() .map(|line| { DiagnosticSpanLine::line_from_source_file( - fm, + sf, line.line_index, line.start_col.0 + 1, line.end_col.0 + 1, diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 594e813def8..1a0fe343521 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -144,7 +144,7 @@ pub struct SubstitutionPart { impl CodeSuggestion { /// Returns the assembled code suggestions, whether they should be shown with an underline /// and whether the substitution only differs in capitalization. - pub fn splice_lines(&self, cm: &SourceMap) -> Vec<(String, Vec, bool)> { + pub fn splice_lines(&self, sm: &SourceMap) -> Vec<(String, Vec, bool)> { use rustc_span::{CharPos, Pos}; fn push_trailing( @@ -176,7 +176,7 @@ impl CodeSuggestion { .filter(|subst| { // Suggestions coming from macros can have malformed spans. This is a heavy // handed approach to avoid ICEs by ignoring the suggestion outright. - let invalid = subst.parts.iter().any(|item| cm.is_valid_span(item.span).is_err()); + let invalid = subst.parts.iter().any(|item| sm.is_valid_span(item.span).is_err()); if invalid { debug!("splice_lines: suggestion contains an invalid span: {:?}", subst); } @@ -193,7 +193,7 @@ impl CodeSuggestion { let hi = substitution.parts.iter().map(|part| part.span.hi()).max()?; let bounding_span = Span::with_root_ctxt(lo, hi); // The different spans might belong to different contexts, if so ignore suggestion. - let lines = cm.span_to_lines(bounding_span).ok()?; + let lines = sm.span_to_lines(bounding_span).ok()?; assert!(!lines.lines.is_empty()); // To build up the result, we do this for each span: @@ -205,36 +205,36 @@ impl CodeSuggestion { // - splice in the span substitution // // Finally push the trailing line segment of the last span - let fm = &lines.file; - let mut prev_hi = cm.lookup_char_pos(bounding_span.lo()); + let sf = &lines.file; + let mut prev_hi = sm.lookup_char_pos(bounding_span.lo()); prev_hi.col = CharPos::from_usize(0); - let mut prev_line = fm.get_line(lines.lines[0].line_index); + let mut prev_line = sf.get_line(lines.lines[0].line_index); let mut buf = String::new(); for part in &substitution.parts { - let cur_lo = cm.lookup_char_pos(part.span.lo()); + let cur_lo = sm.lookup_char_pos(part.span.lo()); if prev_hi.line == cur_lo.line { push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, Some(&cur_lo)); } else { push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None); // push lines between the previous and current span (if any) for idx in prev_hi.line..(cur_lo.line - 1) { - if let Some(line) = fm.get_line(idx) { + if let Some(line) = sf.get_line(idx) { buf.push_str(line.as_ref()); buf.push('\n'); } } - if let Some(cur_line) = fm.get_line(cur_lo.line - 1) { + if let Some(cur_line) = sf.get_line(cur_lo.line - 1) { let end = std::cmp::min(cur_line.len(), cur_lo.col.to_usize()); buf.push_str(&cur_line[..end]); } } buf.push_str(&part.snippet); - prev_hi = cm.lookup_char_pos(part.span.hi()); - prev_line = fm.get_line(prev_hi.line - 1); + prev_hi = sm.lookup_char_pos(part.span.hi()); + prev_line = sf.get_line(prev_hi.line - 1); } - let only_capitalization = is_case_difference(cm, &buf, bounding_span); + let only_capitalization = is_case_difference(sm, &buf, bounding_span); // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None); @@ -363,23 +363,23 @@ impl Handler { color_config: ColorConfig, can_emit_warnings: bool, treat_err_as_bug: Option, - cm: Option>, + sm: Option>, ) -> Self { Self::with_tty_emitter_and_flags( color_config, - cm, + sm, HandlerFlags { can_emit_warnings, treat_err_as_bug, ..Default::default() }, ) } pub fn with_tty_emitter_and_flags( color_config: ColorConfig, - cm: Option>, + sm: Option>, flags: HandlerFlags, ) -> Self { let emitter = Box::new(EmitterWriter::stderr( color_config, - cm, + sm, false, false, None, diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index e49f99fb717..c9faa299d37 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -140,13 +140,13 @@ pub const INDENT_UNIT: usize = 4; /// Requires you to pass an input filename and reader so that /// it can scan the input text for comments to copy forward. pub fn print_crate<'a>( - cm: &'a SourceMap, + sm: &'a SourceMap, krate: &hir::Crate<'_>, filename: FileName, input: String, ann: &'a dyn PpAnn, ) -> String { - let mut s = State::new_from_input(cm, filename, input, ann); + let mut s = State::new_from_input(sm, filename, input, ann); // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. @@ -158,12 +158,12 @@ pub fn print_crate<'a>( impl<'a> State<'a> { pub fn new_from_input( - cm: &'a SourceMap, + sm: &'a SourceMap, filename: FileName, input: String, ann: &'a dyn PpAnn, ) -> State<'a> { - State { s: pp::mk_printer(), comments: Some(Comments::new(cm, filename, input)), ann } + State { s: pp::mk_printer(), comments: Some(Comments::new(sm, filename, input)), ann } } } diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 359b417b3bf..008658dff42 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -194,7 +194,7 @@ fn msg_span_from_early_bound_and_free_regions( tcx: TyCtxt<'tcx>, region: ty::Region<'tcx>, ) -> (String, Option) { - let cm = tcx.sess.source_map(); + let sm = tcx.sess.source_map(); let scope = region.free_region_binding_scope(tcx); let node = tcx.hir().as_local_hir_id(scope).unwrap_or(hir::DUMMY_HIR_ID); @@ -207,7 +207,7 @@ fn msg_span_from_early_bound_and_free_regions( }; let (prefix, span) = match *region { ty::ReEarlyBound(ref br) => { - let mut sp = cm.def_span(tcx.hir().span(node)); + let mut sp = sm.def_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) { @@ -216,7 +216,7 @@ fn msg_span_from_early_bound_and_free_regions( (format!("the lifetime `{}` as defined on", br.name), sp) } ty::ReFree(ty::FreeRegion { bound_region: ty::BoundRegion::BrNamed(_, name), .. }) => { - let mut sp = cm.def_span(tcx.hir().span(node)); + let mut sp = sm.def_span(tcx.hir().span(node)); if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(name)) { @@ -230,7 +230,7 @@ fn msg_span_from_early_bound_and_free_regions( } _ => ( format!("the lifetime `{}` as defined on", region), - cm.def_span(tcx.hir().span(node)), + sm.def_span(tcx.hir().span(node)), ), }, _ => bug!(), diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 97daa91eed1..3ae97ed5f88 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1625,10 +1625,10 @@ impl<'a> Parser<'a> { let hi = self.token.span; if require_comma { - let cm = self.sess.source_map(); + let sm = self.sess.source_map(); self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)]).map_err( |mut err| { - match (cm.span_to_lines(expr.span), cm.span_to_lines(arm_start_span)) { + match (sm.span_to_lines(expr.span), sm.span_to_lines(arm_start_span)) { (Ok(ref expr_lines), Ok(ref arm_start_lines)) if arm_start_lines.lines[0].end_col == expr_lines.lines[0].end_col && expr_lines.lines.len() == 2 diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 709068d2189..f0bb3cd08ad 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -144,11 +144,11 @@ enum LiveNodeKind { } fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { - let cm = tcx.sess.source_map(); + let sm = tcx.sess.source_map(); match lnk { - UpvarNode(s) => format!("Upvar node [{}]", cm.span_to_string(s)), - ExprNode(s) => format!("Expr node [{}]", cm.span_to_string(s)), - VarDefNode(s) => format!("Var def node [{}]", cm.span_to_string(s)), + UpvarNode(s) => format!("Upvar node [{}]", sm.span_to_string(s)), + ExprNode(s) => format!("Expr node [{}]", sm.span_to_string(s)), + VarDefNode(s) => format!("Var def node [{}]", sm.span_to_string(s)), ExitNode => "Exit node".to_owned(), } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 075dca8f01d..7c48ccfaddd 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -90,9 +90,9 @@ impl<'tcx> Into> for &'tcx hir::Generics<'tcx> { /// *Attention*: the method used is very fragile since it essentially duplicates the work of the /// parser. If you need to use this function or something similar, please consider updating the /// `source_map` functions and this function to something more robust. -fn reduce_impl_span_to_impl_keyword(cm: &SourceMap, impl_span: Span) -> Span { - let impl_span = cm.span_until_char(impl_span, '<'); - let impl_span = cm.span_until_whitespace(impl_span); +fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span { + let impl_span = sm.span_until_char(impl_span, '<'); + let impl_span = sm.span_until_whitespace(impl_span); impl_span } @@ -136,14 +136,14 @@ impl<'a> Resolver<'a> { ); err.span_label(span, format!("use of generic parameter from outer function")); - let cm = self.session.source_map(); + let sm = self.session.source_map(); match outer_res { Res::SelfTy(maybe_trait_defid, maybe_impl_defid) => { if let Some(impl_span) = maybe_impl_defid.and_then(|def_id| self.definitions.opt_span(def_id)) { err.span_label( - reduce_impl_span_to_impl_keyword(cm, impl_span), + reduce_impl_span_to_impl_keyword(sm, impl_span), "`Self` type implicitly declared here, by this `impl`", ); } @@ -180,7 +180,7 @@ impl<'a> Resolver<'a> { // Try to retrieve the span of the function signature and generate a new // message with a local type or const parameter. let sugg_msg = &format!("try using a local generic parameter instead"); - if let Some((sugg_span, snippet)) = cm.generate_local_type_param_snippet(span) { + if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) { // Suggest the modification to the user err.span_suggestion( sugg_span, @@ -188,7 +188,7 @@ impl<'a> Resolver<'a> { snippet, Applicability::MachineApplicable, ); - } else if let Some(sp) = cm.generate_fn_name_span(span) { + } else if let Some(sp) = sm.generate_fn_name_span(span) { err.span_label( sp, format!("try adding a local generic parameter in this method instead"), diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 6ec4a13500e..6a6fba8270b 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -725,21 +725,21 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { /// Only used in a specific case of type ascription suggestions fn get_colon_suggestion_span(&self, start: Span) -> Span { - let cm = self.r.session.source_map(); - start.to(cm.next_point(start)) + let sm = self.r.session.source_map(); + start.to(sm.next_point(start)) } fn type_ascription_suggestion(&self, err: &mut DiagnosticBuilder<'_>, base_span: Span) { - let cm = self.r.session.source_map(); - let base_snippet = cm.span_to_snippet(base_span); + let sm = self.r.session.source_map(); + let base_snippet = sm.span_to_snippet(base_span); if let Some(sp) = self.diagnostic_metadata.current_type_ascription.last() { let mut sp = *sp; loop { // Try to find the `:`; bail on first non-':' / non-whitespace. - sp = cm.next_point(sp); - if let Ok(snippet) = cm.span_to_snippet(sp.to(cm.next_point(sp))) { - let line_sp = cm.lookup_char_pos(sp.hi()).line; - let line_base_sp = cm.lookup_char_pos(base_span.lo()).line; + sp = sm.next_point(sp); + if let Ok(snippet) = sm.span_to_snippet(sp.to(sm.next_point(sp))) { + let line_sp = sm.lookup_char_pos(sp.hi()).line; + let line_base_sp = sm.lookup_char_pos(base_span.lo()).line; if snippet == ":" { let mut show_label = true; if line_sp != line_base_sp { @@ -753,7 +753,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let colon_sp = self.get_colon_suggestion_span(sp); let after_colon_sp = self.get_colon_suggestion_span(colon_sp.shrink_to_hi()); - if !cm + if !sm .span_to_snippet(after_colon_sp) .map(|s| s == " ") .unwrap_or(false) @@ -770,8 +770,8 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let mut sp = after_colon_sp; for _ in 0..100 { // Try to find an assignment - sp = cm.next_point(sp); - let snippet = cm.span_to_snippet(sp.to(cm.next_point(sp))); + sp = sm.next_point(sp); + let snippet = sm.span_to_snippet(sp.to(sm.next_point(sp))); match snippet { Ok(ref x) if x.as_str() == "=" => { err.span_suggestion( diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index db7733e7241..41325c1307f 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1233,8 +1233,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { let qualname = format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id))); - let cm = self.tcx.sess.source_map(); - let filename = cm.span_to_filename(span); + let sm = self.tcx.sess.source_map(); + let filename = sm.span_to_filename(span); let data_id = id_from_node_id(id, &self.save_ctxt); let children = m.items.iter().map(|i| id_from_node_id(i.id, &self.save_ctxt)).collect(); let span = self.span_from_span(span); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 6e7ecf92441..43a0cfecd3e 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -66,9 +66,9 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { fn span_from_span(&self, span: Span) -> SpanData { use rls_span::{Column, Row}; - let cm = self.tcx.sess.source_map(); - let start = cm.lookup_char_pos(span.lo()); - let end = cm.lookup_char_pos(span.hi()); + let sm = self.tcx.sess.source_map(); + let start = sm.lookup_char_pos(span.lo()); + let end = sm.lookup_char_pos(span.hi()); SpanData { file_name: start.file.name.to_string().into(), @@ -258,8 +258,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) ); - let cm = self.tcx.sess.source_map(); - let filename = cm.span_to_filename(m.inner); + let sm = self.tcx.sess.source_map(); + let filename = sm.span_to_filename(m.inner); filter!(self.span_utils, item.ident.span); diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs index 6a4871b6da0..72b34cff551 100644 --- a/src/librustc_session/parse.rs +++ b/src/librustc_session/parse.rs @@ -124,9 +124,9 @@ pub struct ParseSess { impl ParseSess { pub fn new(file_path_mapping: FilePathMapping) -> Self { - let cm = Lrc::new(SourceMap::new(file_path_mapping)); - let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(cm.clone())); - ParseSess::with_span_handler(handler, cm) + let sm = Lrc::new(SourceMap::new(file_path_mapping)); + let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, None, Some(sm.clone())); + ParseSess::with_span_handler(handler, sm) } pub fn with_span_handler(handler: Handler, source_map: Lrc) -> Self { @@ -148,9 +148,9 @@ impl ParseSess { } pub fn with_silent_emitter() -> Self { - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let handler = Handler::with_emitter(false, None, Box::new(SilentEmitter)); - ParseSess::with_span_handler(handler, cm) + ParseSess::with_span_handler(handler, sm) } #[inline] diff --git a/src/librustc_span/caching_source_map_view.rs b/src/librustc_span/caching_source_map_view.rs index c329f2225b0..d6725160a5d 100644 --- a/src/librustc_span/caching_source_map_view.rs +++ b/src/librustc_span/caching_source_map_view.rs @@ -13,14 +13,14 @@ struct CacheEntry { } #[derive(Clone)] -pub struct CachingSourceMapView<'cm> { - source_map: &'cm SourceMap, +pub struct CachingSourceMapView<'sm> { + source_map: &'sm SourceMap, line_cache: [CacheEntry; 3], time_stamp: usize, } -impl<'cm> CachingSourceMapView<'cm> { - pub fn new(source_map: &'cm SourceMap) -> CachingSourceMapView<'cm> { +impl<'sm> CachingSourceMapView<'sm> { + pub fn new(source_map: &'sm SourceMap) -> CachingSourceMapView<'sm> { let files = source_map.files(); let first_file = files[0].clone(); let entry = CacheEntry { diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 63ebf612964..c289176c303 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -324,13 +324,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir_id: hir::HirId, sp: Span, ) -> bool { - let cm = self.sess().source_map(); + let sm = self.sess().source_map(); let parent_id = self.tcx.hir().get_parent_node(hir_id); if let Some(parent) = self.tcx.hir().find(parent_id) { // Account for fields if let Node::Expr(hir::Expr { kind: hir::ExprKind::Struct(_, fields, ..), .. }) = parent { - if let Ok(src) = cm.span_to_snippet(sp) { + if let Ok(src) = sm.span_to_snippet(sp) { for field in *fields { if field.ident.as_str() == src && field.is_shorthand { return true; @@ -364,9 +364,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { checked_ty: Ty<'tcx>, expected: Ty<'tcx>, ) -> Option<(Span, &'static str, String)> { - let cm = self.sess().source_map(); + let sm = self.sess().source_map(); let sp = expr.span; - if !cm.span_to_filename(sp).is_real() { + if !sm.span_to_filename(sp).is_real() { // Ignore if span is from within a macro #41858, #58298. We previously used the macro // call span, but that breaks down when the type error comes from multiple calls down. return None; @@ -388,7 +388,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = cm.span_to_snippet(sp) { + if let Ok(src) = sm.span_to_snippet(sp) { if src.starts_with("b\"") { return Some(( sp, @@ -403,7 +403,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if arr == self.tcx.types.u8 => { if let hir::ExprKind::Lit(_) = expr.kind { - if let Ok(src) = cm.span_to_snippet(sp) { + if let Ok(src) = sm.span_to_snippet(sp) { if src.starts_with("\"") { return Some(( sp, @@ -450,7 +450,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { sugg_sp = arg.span; } } - if let Ok(src) = cm.span_to_snippet(sugg_sp) { + if let Ok(src) = sm.span_to_snippet(sugg_sp) { let needs_parens = match expr.kind { // parenthesize if needed (Issue #46756) hir::ExprKind::Cast(_, _) | hir::ExprKind::Binary(_, _, _) => true, @@ -480,7 +480,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // | | // consider dereferencing here: `*opt` | // expected mutable reference, found enum `Option` - if let Ok(src) = cm.span_to_snippet(left_expr.span) { + if let Ok(src) = sm.span_to_snippet(left_expr.span) { return Some(( left_expr.span, "consider dereferencing here to assign to the mutable \ @@ -516,8 +516,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest removing a `&`. - if !cm.span_to_filename(expr.span).is_real() { - if let Ok(code) = cm.span_to_snippet(sp) { + if !sm.span_to_filename(expr.span).is_real() { + if let Ok(code) = sm.span_to_snippet(sp) { if code.chars().next() == Some('&') { return Some(( sp, @@ -528,7 +528,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } return None; } - if let Ok(code) = cm.span_to_snippet(expr.span) { + if let Ok(code) = sm.span_to_snippet(expr.span) { return Some((sp, "consider removing the borrow", code)); } } @@ -562,7 +562,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let is_copy = self.infcx.type_is_copy_modulo_regions(self.param_env, expected, sp); if is_copy && impls_deref { - if let Ok(code) = cm.span_to_snippet(sp) { + if let Ok(code) = sm.span_to_snippet(sp) { let message = if checked_ty.is_region_ptr() { "consider dereferencing the borrow" } else { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 6ce0da666a7..a8e5a0ddf26 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -33,8 +33,8 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { ); let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap(); let trait_def_id = trait_ref.def_id; - let cm = self.tcx.sess.source_map(); - let sp = cm.def_span(item.span); + let sm = self.tcx.sess.source_map(); + let sp = sm.def_span(item.span); match traits::orphan_check(self.tcx, def_id) { Ok(()) => {} Err(traits::OrphanCheckErr::NonLocalInputType(tys)) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index af81087b53e..50c780e9ecb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -263,9 +263,9 @@ impl Clean for doctree::Module<'_> { // determine if we should display the inner contents or // the outer `mod` item for the source code. let whence = { - let cm = cx.sess().source_map(); - let outer = cm.lookup_char_pos(self.where_outer.lo()); - let inner = cm.lookup_char_pos(self.where_inner.lo()); + let sm = cx.sess().source_map(); + let outer = sm.lookup_char_pos(self.where_outer.lo()); + let inner = sm.lookup_char_pos(self.where_inner.lo()); if outer.file.start_pos == inner.file.start_pos { // mod foo { ... } self.where_outer @@ -1917,10 +1917,10 @@ impl Clean for rustc_span::Span { return Span::empty(); } - let cm = cx.sess().source_map(); - let filename = cm.span_to_filename(*self); - let lo = cm.lookup_char_pos(self.lo()); - let hi = cm.lookup_char_pos(self.hi()); + let sm = cx.sess().source_map(); + let filename = sm.span_to_filename(*self); + let lo = sm.lookup_char_pos(self.lo()); + let hi = sm.lookup_char_pos(self.hi()); Span { filename, loline: lo.line, diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index c3c07e2e02c..8c4e65765d3 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -177,7 +177,7 @@ pub fn new_handler( Box::new( EmitterWriter::stderr( color_config, - source_map.map(|cm| cm as _), + source_map.map(|sm| sm as _), short, debugging_opts.teach, debugging_opts.terminal_width, diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 1ea053605ec..849c5c3e072 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -38,11 +38,11 @@ pub fn render_with_highlighting( } let sess = ParseSess::with_silent_emitter(); - let fm = sess + let sf = sess .source_map() .new_source_file(FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned()); let highlight_result = rustc_driver::catch_fatal_errors(|| { - let lexer = lexer::StringReader::new(&sess, fm, None); + let lexer = lexer::StringReader::new(&sess, sf, None); let mut classifier = Classifier::new(lexer, sess.source_map()); let mut highlighted_source = vec![]; diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 3b7c0db05a5..a6dad3c3920 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -32,9 +32,9 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { let emitter = BufferEmitter { messages: Lrc::clone(&buffered_messages) }; - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let handler = Handler::with_emitter(false, None, Box::new(emitter)); - let sess = ParseSess::with_span_handler(handler, cm); + let sess = ParseSess::with_span_handler(handler, sm); let source_file = sess.source_map().new_source_file( FileName::Custom(String::from("doctest")), dox[code_block.code].to_owned(), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 0c7dfa1417a..5dd7bd82755 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -402,12 +402,12 @@ pub fn make_test( // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. - let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); + let sm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); - let sess = ParseSess::with_span_handler(handler, cm); + let sess = ParseSess::with_span_handler(handler, sm); let mut found_main = false; let mut found_extern_crate = cratename.is_none(); diff --git a/src/libsyntax/util/comments.rs b/src/libsyntax/util/comments.rs index 5a67531624d..0e42ae11fa2 100644 --- a/src/libsyntax/util/comments.rs +++ b/src/libsyntax/util/comments.rs @@ -189,8 +189,8 @@ fn split_block_comment_into_lines(text: &str, col: CharPos) -> Vec { // it appears this function is called only from pprust... that's // probably not a good thing. pub fn gather_comments(sm: &SourceMap, path: FileName, src: String) -> Vec { - let cm = SourceMap::new(sm.path_mapping().clone()); - let source_file = cm.new_source_file(path, src); + let sm = SourceMap::new(sm.path_mapping().clone()); + let source_file = sm.new_source_file(path, src); let text = (*source_file.src.as_ref().unwrap()).clone(); let text: &str = text.as_str(); From 4356d18e4ab262a6703fa3a901c7cf00e9d27cc7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 22 Feb 2020 16:22:38 +0300 Subject: [PATCH 0435/1250] parser: Cleanup `Parser::bump_with` and its uses --- src/librustc_parse/parser/mod.rs | 178 +++++++++---------------------- src/libsyntax/token.rs | 33 ++++++ 2 files changed, 84 insertions(+), 127 deletions(-) diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 937e5e3cd69..75d4b3750f1 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -601,141 +601,76 @@ impl<'a> Parser<'a> { ) } - /// Expects and consumes a `+`. if `+=` is seen, replaces it with a `=` - /// and continues. If a `+` is not seen, returns `false`. - /// - /// This is used when token-splitting `+=` into `+`. - /// See issue #47856 for an example of when this may occur. - fn eat_plus(&mut self) -> bool { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Plus))); - match self.token.kind { - token::BinOp(token::Plus) => { - self.bump(); + /// Eats the expected token if it's present possibly breaking + /// compound tokens like multi-character operators in process. + /// Returns `true` if the token was eaten. + fn break_and_eat(&mut self, expected: TokenKind) -> bool { + if self.token.kind == expected { + self.bump(); + return true; + } + match self.token.kind.break_two_token_op() { + Some((first, second)) if first == expected => { + let first_span = self.sess.source_map().start_point(self.token.span); + let second_span = self.token.span.with_lo(first_span.hi()); + self.set_token(Token::new(first, first_span)); + self.bump_with(Token::new(second, second_span)); true } - token::BinOpEq(token::Plus) => { - let start_point = self.sess.source_map().start_point(self.token.span); - self.bump_with(token::Eq, self.token.span.with_lo(start_point.hi())); - true + _ => { + self.expected_tokens.push(TokenType::Token(expected)); + false } - _ => false, } } - /// Expects and consumes an `&`. If `&&` is seen, replaces it with a single - /// `&` and continues. If an `&` is not seen, signals an error. + /// Eats `+` possibly breaking tokens like `+=` in process. + fn eat_plus(&mut self) -> bool { + self.break_and_eat(token::BinOp(token::Plus)) + } + + /// Eats `&` possibly breaking tokens like `&&` in process. + /// Signals an error if `&` is not eaten. fn expect_and(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::And))); - match self.token.kind { - token::BinOp(token::And) => { - self.bump(); - Ok(()) - } - token::AndAnd => { - let start_point = self.sess.source_map().start_point(self.token.span); - Ok(self - .bump_with(token::BinOp(token::And), self.token.span.with_lo(start_point.hi()))) - } - _ => self.unexpected(), - } + if self.break_and_eat(token::BinOp(token::And)) { Ok(()) } else { self.unexpected() } } - /// Expects and consumes an `|`. If `||` is seen, replaces it with a single - /// `|` and continues. If an `|` is not seen, signals an error. + /// Eats `|` possibly breaking tokens like `||` in process. + /// Signals an error if `|` was not eaten. fn expect_or(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::BinOp(token::Or))); - match self.token.kind { - token::BinOp(token::Or) => { - self.bump(); - Ok(()) - } - token::OrOr => { - let start_point = self.sess.source_map().start_point(self.token.span); - Ok(self - .bump_with(token::BinOp(token::Or), self.token.span.with_lo(start_point.hi()))) - } - _ => self.unexpected(), - } + if self.break_and_eat(token::BinOp(token::Or)) { Ok(()) } else { self.unexpected() } } - /// Attempts to consume a `<`. If `<<` is seen, replaces it with a single - /// `<` and continue. If `<-` is seen, replaces it with a single `<` - /// and continue. If a `<` is not seen, returns false. - /// - /// This is meant to be used when parsing generics on a path to get the - /// starting token. + /// Eats `<` possibly breaking tokens like `<<` in process. fn eat_lt(&mut self) -> bool { - self.expected_tokens.push(TokenType::Token(token::Lt)); - let ate = match self.token.kind { - token::Lt => { - self.bump(); - true - } - token::BinOp(token::Shl) => { - let start_point = self.sess.source_map().start_point(self.token.span); - self.bump_with(token::Lt, self.token.span.with_lo(start_point.hi())); - true - } - token::LArrow => { - let start_point = self.sess.source_map().start_point(self.token.span); - self.bump_with( - token::BinOp(token::Minus), - self.token.span.with_lo(start_point.hi()), - ); - true - } - _ => false, - }; - + let ate = self.break_and_eat(token::Lt); if ate { // See doc comment for `unmatched_angle_bracket_count`. self.unmatched_angle_bracket_count += 1; self.max_angle_bracket_count += 1; debug!("eat_lt: (increment) count={:?}", self.unmatched_angle_bracket_count); } - ate } + /// Eats `<` possibly breaking tokens like `<<` in process. + /// Signals an error if `<` was not eaten. fn expect_lt(&mut self) -> PResult<'a, ()> { - if !self.eat_lt() { self.unexpected() } else { Ok(()) } + if self.eat_lt() { Ok(()) } else { self.unexpected() } } - /// Expects and consumes a single `>` token. if a `>>` is seen, replaces it - /// with a single `>` and continues. If a `>` is not seen, signals an error. + /// Eats `>` possibly breaking tokens like `>>` in process. + /// Signals an error if `>` was not eaten. fn expect_gt(&mut self) -> PResult<'a, ()> { - self.expected_tokens.push(TokenType::Token(token::Gt)); - let ate = match self.token.kind { - token::Gt => { - self.bump(); - Some(()) - } - token::BinOp(token::Shr) => { - let start_point = self.sess.source_map().start_point(self.token.span); - Some(self.bump_with(token::Gt, self.token.span.with_lo(start_point.hi()))) - } - token::BinOpEq(token::Shr) => { - let start_point = self.sess.source_map().start_point(self.token.span); - Some(self.bump_with(token::Ge, self.token.span.with_lo(start_point.hi()))) - } - token::Ge => { - let start_point = self.sess.source_map().start_point(self.token.span); - Some(self.bump_with(token::Eq, self.token.span.with_lo(start_point.hi()))) - } - _ => None, - }; - - match ate { - Some(_) => { - // See doc comment for `unmatched_angle_bracket_count`. - if self.unmatched_angle_bracket_count > 0 { - self.unmatched_angle_bracket_count -= 1; - debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count); - } - - Ok(()) + if self.break_and_eat(token::Gt) { + // See doc comment for `unmatched_angle_bracket_count`. + if self.unmatched_angle_bracket_count > 0 { + self.unmatched_angle_bracket_count -= 1; + debug!("expect_gt: (decrement) count={:?}", self.unmatched_angle_bracket_count); } - None => self.unexpected(), + Ok(()) + } else { + self.unexpected() } } @@ -903,10 +838,10 @@ impl<'a> Parser<'a> { } } - /// Advance the parser by one token. - pub fn bump(&mut self) { + /// Advance the parser by one token using provided token as the next one. + fn bump_with(&mut self, next_token: Token) { + // Bumping after EOF is a bad sign, usually an infinite loop. if self.prev_token.kind == TokenKind::Eof { - // Bumping after EOF is a bad sign, usually an infinite loop. let msg = "attempted to bump the parser past EOF (may be stuck in a loop)"; self.span_bug(self.token.span, msg); } @@ -914,30 +849,19 @@ impl<'a> Parser<'a> { // Update the current and previous tokens. self.prev_token = self.token.take(); self.unnormalized_prev_token = self.unnormalized_token.take(); - let next_token = self.next_tok(self.unnormalized_prev_token.span); self.set_token(next_token); // Update fields derived from the previous token. self.prev_span = self.unnormalized_prev_token.span; + // Diagnostics. self.expected_tokens.clear(); } - /// Advances the parser using provided token as a next one. Use this when - /// consuming a part of a token. For example a single `<` from `<<`. - /// FIXME: this function sets the previous token data to some semi-nonsensical values - /// which kind of work because they are currently used in very limited ways in practice. - /// Correct token kinds and spans need to be calculated instead. - fn bump_with(&mut self, next: TokenKind, span: Span) { - // Update the current and previous tokens. - self.prev_token = self.token.take(); - self.unnormalized_prev_token = self.unnormalized_token.take(); - self.set_token(Token::new(next, span)); - - // Update fields derived from the previous token. - self.prev_span = self.unnormalized_prev_token.span.with_hi(span.lo()); - - self.expected_tokens.clear(); + /// Advance the parser by one token. + pub fn bump(&mut self) { + let next_token = self.next_tok(self.unnormalized_token.span); + self.bump_with(next_token); } /// Look-ahead `dist` tokens of `self.token` and get access to that token there. diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 862934300e0..6eeee498815 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -270,6 +270,39 @@ impl TokenKind { Literal(Lit::new(kind, symbol, suffix)) } + // An approximation to proc-macro-style single-character operators used by rustc parser. + // If the operator token can be broken into two tokens, the first of which is single-character, + // then this function performs that operation, otherwise it returns `None`. + pub fn break_two_token_op(&self) -> Option<(TokenKind, TokenKind)> { + Some(match *self { + Le => (Lt, Eq), + EqEq => (Eq, Eq), + Ne => (Not, Eq), + Ge => (Gt, Eq), + AndAnd => (BinOp(And), BinOp(And)), + OrOr => (BinOp(Or), BinOp(Or)), + BinOp(Shl) => (Lt, Lt), + BinOp(Shr) => (Gt, Gt), + BinOpEq(Plus) => (BinOp(Plus), Eq), + BinOpEq(Minus) => (BinOp(Minus), Eq), + BinOpEq(Star) => (BinOp(Star), Eq), + BinOpEq(Slash) => (BinOp(Slash), Eq), + BinOpEq(Percent) => (BinOp(Percent), Eq), + BinOpEq(Caret) => (BinOp(Caret), Eq), + BinOpEq(And) => (BinOp(And), Eq), + BinOpEq(Or) => (BinOp(Or), Eq), + BinOpEq(Shl) => (Lt, Le), + BinOpEq(Shr) => (Gt, Ge), + DotDot => (Dot, Dot), + DotDotDot => (Dot, DotDot), + ModSep => (Colon, Colon), + RArrow => (BinOp(Minus), Gt), + LArrow => (Lt, BinOp(Minus)), + FatArrow => (Eq, Gt), + _ => return None, + }) + } + /// Returns tokens that are likely to be typed accidentally instead of the current token. /// Enables better error recovery when the wrong token is found. pub fn similar_tokens(&self) -> Option> { From a796af7a7685a21e8c43f93aa5fb3007cd847253 Mon Sep 17 00:00:00 2001 From: jumbatm Date: Sun, 23 Feb 2020 01:43:47 +1000 Subject: [PATCH 0436/1250] Fail on multiple declarations of `main`. Previously, when inserting the entry function, we only checked for duplicate _definitions_ of `main`. However, it's possible to cause problems even only having a duplicate _declaration_. For example, shadowing `main` using an extern block isn't caught by the current check, and causes an assertion failure down the line in in LLVM code. --- src/librustc_codegen_ssa/base.rs | 4 ++-- src/test/ui/duplicate/dupe-symbols-7.rs | 2 +- src/test/ui/duplicate/dupe-symbols-7.stderr | 2 +- src/test/ui/duplicate/dupe-symbols-8.rs | 12 ++++++++++++ src/test/ui/duplicate/dupe-symbols-8.stderr | 15 +++++++++++++++ 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/duplicate/dupe-symbols-8.rs create mode 100644 src/test/ui/duplicate/dupe-symbols-8.stderr diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index e9431d94863..d6e1ab8909c 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -437,10 +437,10 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // listing. let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap()); - if cx.get_defined_value("main").is_some() { + if cx.get_declared_value("main").is_some() { // FIXME: We should be smart and show a better diagnostic here. cx.sess() - .struct_span_err(sp, "entry symbol `main` defined multiple times") + .struct_span_err(sp, "entry symbol `main` declared multiple times") .help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead") .emit(); cx.sess().abort_if_errors(); diff --git a/src/test/ui/duplicate/dupe-symbols-7.rs b/src/test/ui/duplicate/dupe-symbols-7.rs index 89a32c61620..633ca4c3189 100644 --- a/src/test/ui/duplicate/dupe-symbols-7.rs +++ b/src/test/ui/duplicate/dupe-symbols-7.rs @@ -1,7 +1,7 @@ // build-fail // -// error-pattern: entry symbol `main` defined multiple times +// error-pattern: entry symbol `main` declared multiple times // FIXME https://github.com/rust-lang/rust/issues/59774 // normalize-stderr-test "thread.*panicked.*Metadata module not compiled.*\n" -> "" diff --git a/src/test/ui/duplicate/dupe-symbols-7.stderr b/src/test/ui/duplicate/dupe-symbols-7.stderr index 608ae27110a..2ea5521e095 100644 --- a/src/test/ui/duplicate/dupe-symbols-7.stderr +++ b/src/test/ui/duplicate/dupe-symbols-7.stderr @@ -1,4 +1,4 @@ -error: entry symbol `main` defined multiple times +error: entry symbol `main` declared multiple times --> $DIR/dupe-symbols-7.rs:12:1 | LL | fn main(){} diff --git a/src/test/ui/duplicate/dupe-symbols-8.rs b/src/test/ui/duplicate/dupe-symbols-8.rs new file mode 100644 index 00000000000..ce7fa24a9fe --- /dev/null +++ b/src/test/ui/duplicate/dupe-symbols-8.rs @@ -0,0 +1,12 @@ +// build-fail +// error-pattern: entry symbol `main` declared multiple times +// +// See #67946. + +#![allow(warnings)] +fn main() { + extern "Rust" { + fn main(); + } + unsafe { main(); } +} diff --git a/src/test/ui/duplicate/dupe-symbols-8.stderr b/src/test/ui/duplicate/dupe-symbols-8.stderr new file mode 100644 index 00000000000..f001201b8d0 --- /dev/null +++ b/src/test/ui/duplicate/dupe-symbols-8.stderr @@ -0,0 +1,15 @@ +error: entry symbol `main` declared multiple times + --> $DIR/dupe-symbols-8.rs:7:1 + | +LL | / fn main() { +LL | | extern "Rust" { +LL | | fn main(); +LL | | } +LL | | unsafe { main(); } +LL | | } + | |_^ + | + = help: did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead + +error: aborting due to previous error + From 494dd0b71936813e3a5565d5ea88c6fdf07240e3 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Sat, 22 Feb 2020 08:28:56 -0800 Subject: [PATCH 0437/1250] Remove trait --- src/librustc_lint/builtin.rs | 69 +++++++++++++----------------------- 1 file changed, 25 insertions(+), 44 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 705097d4644..54b5b922ac7 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -738,52 +738,33 @@ impl EarlyLintPass for DeprecatedAttr { } } -trait UnusedDocCommentExt { - fn warn_if_doc( - &self, - cx: &EarlyContext<'_>, - node_span: Span, - node_kind: &str, - attrs: &[ast::Attribute], - ); -} +fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) { + let mut attrs = attrs.into_iter().peekable(); -impl UnusedDocCommentExt for UnusedDocComment { - fn warn_if_doc( - &self, - cx: &EarlyContext<'_>, - node_span: Span, - node_kind: &str, - attrs: &[ast::Attribute], - ) { - let mut attrs = attrs.into_iter().peekable(); - - // Accumulate a single span for sugared doc comments. - let mut sugared_span: Option = None; + // Accumulate a single span for sugared doc comments. + let mut sugared_span: Option = None; - while let Some(attr) = attrs.next() { - if attr.is_doc_comment() { - sugared_span = Some( - sugared_span.map_or_else(|| attr.span, |span| span.with_hi(attr.span.hi())), - ); - } + while let Some(attr) = attrs.next() { + if attr.is_doc_comment() { + sugared_span = + Some(sugared_span.map_or_else(|| attr.span, |span| span.with_hi(attr.span.hi()))); + } - if attrs.peek().map(|next_attr| next_attr.is_doc_comment()).unwrap_or_default() { - continue; - } + if attrs.peek().map(|next_attr| next_attr.is_doc_comment()).unwrap_or_default() { + continue; + } - let span = sugared_span.take().unwrap_or_else(|| attr.span); + let span = sugared_span.take().unwrap_or_else(|| attr.span); - if attr.is_doc_comment() || attr.check_name(sym::doc) { - cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { - let mut err = lint.build("unused doc comment"); - err.span_label( - node_span, - format!("rustdoc does not generate documentation for {}", node_kind), - ); - err.emit(); - }); - } + if attr.is_doc_comment() || attr.check_name(sym::doc) { + cx.struct_span_lint(UNUSED_DOC_COMMENTS, span, |lint| { + let mut err = lint.build("unused doc comment"); + err.span_label( + node_span, + format!("rustdoc does not generate documentation for {}", node_kind), + ); + err.emit(); + }); } } } @@ -797,16 +778,16 @@ impl EarlyLintPass for UnusedDocComment { ast::StmtKind::Semi(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Mac(..) => return, }; - self.warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs()); + warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs()); } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { let arm_span = arm.pat.span.with_hi(arm.body.span.hi()); - self.warn_if_doc(cx, arm_span, "match arms", &arm.attrs); + warn_if_doc(cx, arm_span, "match arms", &arm.attrs); } fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) { - self.warn_if_doc(cx, expr.span, "expressions", &expr.attrs); + warn_if_doc(cx, expr.span, "expressions", &expr.attrs); } } From 7f7709e3d4c10e1b71461496bf6747c3cea63b75 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 30 Dec 2019 19:46:30 -0600 Subject: [PATCH 0438/1250] Generalized article_and_description --- src/librustc/ty/context.rs | 16 ++++++++- src/librustc/ty/sty.rs | 35 +++++++++++++++++++ .../diagnostics/conflict_errors.rs | 7 ++-- .../borrow_check/diagnostics/region_errors.rs | 16 ++++----- .../borrow_check/universal_regions.rs | 23 ++++++++++++ 5 files changed, 83 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e59738d8886..fd2f58d24f8 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -209,7 +209,7 @@ fn validate_hir_id_for_typeck_tables( ty::tls::with(|tcx| { bug!( "node {} with HirId::owner {:?} cannot be placed in \ - TypeckTables with local_id_root {:?}", + TypeckTables with local_id_root {:?}", tcx.hir().node_to_string(hir_id), DefId::local(hir_id.owner), local_id_root @@ -1512,6 +1512,20 @@ impl<'tcx> TyCtxt<'tcx> { .subst(*self, self.mk_substs([self.lifetimes.re_static.into()].iter())), ) } + + /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "closure")`). + pub fn article_and_description( + &self, + def_id: crate::hir::def_id::DefId, + ) -> (&'static str, &'static str) { + self.def_kind(def_id).map_or_else( + || { + // TODO: is it a problem to try to use the ty here? + self.type_of(def_id).kind.article_and_description() + }, + |def_kind| (def_kind.article(), def_kind.descr(def_id)), + ) + } } impl<'tcx> GlobalCtxt<'tcx> { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index c3698f402a9..a54bf4d7eff 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -254,6 +254,41 @@ pub enum TyKind<'tcx> { Error, } +impl<'tcx> TyKind<'tcx> { + pub fn article_and_description(&self) -> (&'static str, &'static str) { + match *self { + Bool => ("a", "boolean value"), + Char => ("a", "character"), + Int(..) => ("a", "signed interger"), + Uint(..) => ("an", "unsigned integer"), + Float(..) => ("a", "floating point number"), + Adt(..) => ("an", "abstract data type"), + Foreign(..) => ("a", "foreign type"), + Str => ("a", "string slice"), + Array(..) => ("an", "array"), + Slice(..) => ("a", "slice"), + RawPtr(..) => ("a", "raw pointer"), + Ref(..) => ("a", "reference"), + FnDef(..) => ("a", "function"), + FnPtr(..) => ("a", "function pointer"), + Dynamic(..) => ("a", "trait object"), + Closure(..) => ("a", "closure"), + Generator(..) => ("a", "generator"), + GeneratorWitness(..) => ("a", "generator witness"), + Never => ("a", "never"), + Tuple(..) => ("a", "tuple"), + Projection(..) => ("a", "projection"), + UnnormalizedProjection(..) => ("an", "unnormalized projection"), + Opaque(..) => ("an", "opaque type"), + Param(..) => ("a", "type parameter"), + Bound(..) => ("a", "bound type variable"), + Placeholder(..) => ("a", "universally quantified higher-ranked type"), + Infer(..) => ("an", "inference variable"), + Error => ("a", "type error"), + } + } +} + // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] static_assert_size!(TyKind<'_>, 24); diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 0ed7dd03f3a..41a99d1125b 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1257,7 +1257,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } _ => bug!( "report_escaping_closure_capture called with unexpected constraint \ - category: `{:?}`", + category: `{:?}`", category ), }; @@ -1279,8 +1279,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tables = tcx.typeck_tables_of(self.mir_def_id); let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); match tables.node_type(mir_hir_id).kind { - ty::Closure(..) => "closure", - ty::Generator(..) => "generator", + ref kind @ ty::Closure(..) | ref kind @ ty::Generator(..) => { + kind.article_and_description().1 + } _ => bug!("Closure body doesn't have a closure or generator type"), } } else { diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index a3e0e51c5b6..0f0fd64844a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -427,18 +427,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { errci.outlived_fr, ); - let escapes_from = match self.regioncx.universal_regions().defining_ty { - DefiningTy::Closure(..) => "closure", - DefiningTy::Generator(..) => "generator", - DefiningTy::FnDef(..) => "function", - DefiningTy::Const(..) => "const", - }; + let (_, escapes_from) = + self.infcx.tcx.article_and_description(self.universal_regions.defining_ty.def_id()); // Revert to the normal error in these cases. // Assignments aren't "escapes" in function items. if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) - || (*category == ConstraintCategory::Assignment && escapes_from == "function") - || escapes_from == "const" + || (*category == ConstraintCategory::Assignment + && self.universal_regions.defining_ty.is_fn_def()) + || self.universal_regions.defining_ty.is_closure() { return self.report_general_error(&ErrorConstraintInfo { fr_is_local: true, @@ -504,8 +501,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut diag = self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough"); - let mir_def_name = - if self.infcx.tcx.is_closure(self.mir_def_id) { "closure" } else { "function" }; + let (_, mir_def_name) = self.infcx.tcx.article_and_description(self.mir_def_id); let fr_name = self.give_region_a_name(*fr).unwrap(); fr_name.highlight_region_name(&mut diag); diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 0913de63e8e..777eea22eb6 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -131,6 +131,29 @@ impl<'tcx> DefiningTy<'tcx> { DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0, } } + + pub fn is_closure(&self) -> bool { + match *self { + DefiningTy::Closure(..) => true, + _ => false, + } + } + + pub fn is_fn_def(&self) -> bool { + match *self { + DefiningTy::FnDef(..) => true, + _ => false, + } + } + + pub fn def_id(&self) -> DefId { + match *self { + DefiningTy::Closure(def_id, ..) => def_id, + DefiningTy::Generator(def_id, ..) => def_id, + DefiningTy::FnDef(def_id, ..) => def_id, + DefiningTy::Const(def_id, ..) => def_id, + } + } } #[derive(Debug)] From 4d22e757cd97d1a69ed8ddda7d346355ce466255 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 24 Jan 2020 12:02:33 -0600 Subject: [PATCH 0439/1250] minor cleanup --- src/librustc_mir/borrow_check/universal_regions.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 777eea22eb6..6d79b7228f2 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -148,10 +148,10 @@ impl<'tcx> DefiningTy<'tcx> { pub fn def_id(&self) -> DefId { match *self { - DefiningTy::Closure(def_id, ..) => def_id, - DefiningTy::Generator(def_id, ..) => def_id, - DefiningTy::FnDef(def_id, ..) => def_id, - DefiningTy::Const(def_id, ..) => def_id, + DefiningTy::Closure(def_id, ..) + | DefiningTy::Generator(def_id, ..) + | DefiningTy::FnDef(def_id, ..) + | DefiningTy::Const(def_id, ..) => def_id, } } } From 245062cdcd9907bd7f71822f958219dc8ce994d2 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 24 Jan 2020 12:13:45 -0600 Subject: [PATCH 0440/1250] some fixes --- src/librustc/ty/context.rs | 11 ++++------- .../borrow_check/diagnostics/conflict_errors.rs | 13 +------------ .../borrow_check/diagnostics/region_errors.rs | 2 +- 3 files changed, 6 insertions(+), 20 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fd2f58d24f8..07c7ccfd16d 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1518,13 +1518,10 @@ impl<'tcx> TyCtxt<'tcx> { &self, def_id: crate::hir::def_id::DefId, ) -> (&'static str, &'static str) { - self.def_kind(def_id).map_or_else( - || { - // TODO: is it a problem to try to use the ty here? - self.type_of(def_id).kind.article_and_description() - }, - |def_kind| (def_kind.article(), def_kind.descr(def_id)), - ) + match self.def_kind(def_id) { + Some(def_kind) => (def_kind.article(), def_kind.descr(def_id)), + None => self.type_of(def_id).kind.article_and_description(), + } } } diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 41a99d1125b..83669a53eb4 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1275,18 +1275,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) -> DiagnosticBuilder<'cx> { let tcx = self.infcx.tcx; - let escapes_from = if tcx.is_closure(self.mir_def_id) { - let tables = tcx.typeck_tables_of(self.mir_def_id); - let mir_hir_id = tcx.hir().def_index_to_hir_id(self.mir_def_id.index); - match tables.node_type(mir_hir_id).kind { - ref kind @ ty::Closure(..) | ref kind @ ty::Generator(..) => { - kind.article_and_description().1 - } - _ => bug!("Closure body doesn't have a closure or generator type"), - } - } else { - "function" - }; + let (_, escapes_from) = tcx.article_and_description(self.mir_def_id); let mut err = borrowck_errors::borrowed_data_escapes_closure(tcx, escape_span, escapes_from); diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 0f0fd64844a..f4089b26860 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -435,7 +435,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) || (*category == ConstraintCategory::Assignment && self.universal_regions.defining_ty.is_fn_def()) - || self.universal_regions.defining_ty.is_closure() + || self.universal_regions.defining_ty.is_const() { return self.report_general_error(&ErrorConstraintInfo { fr_is_local: true, From 66500effea474498052ecd0cd26274be5602a63a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 25 Jan 2020 19:09:23 -0600 Subject: [PATCH 0441/1250] add generator_kind query --- src/librustc/query/mod.rs | 3 +++ src/librustc/ty/context.rs | 22 +++++++++++-------- src/librustc_metadata/rmeta/decoder.rs | 19 +++++++++++----- .../rmeta/decoder/cstore_impl.rs | 1 + src/librustc_metadata/rmeta/encoder.rs | 16 ++++---------- src/librustc_metadata/rmeta/mod.rs | 6 ++--- .../borrow_check/diagnostics/region_errors.rs | 10 +++++---- .../borrow_check/universal_regions.rs | 8 +++---- src/librustc_typeck/collect.rs | 15 +++++++++++-- 9 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 02c51a2ebb0..3a6961660fd 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -308,6 +308,9 @@ rustc_queries! { /// Returns `Some(mutability)` if the node pointed to by `def_id` is a static item. query static_mutability(_: DefId) -> Option {} + /// Returns `Some(generator_kind)` if the node pointed to by `def_id` is a generator. + query generator_kind(_: DefId) -> Option {} + /// Gets a map with the variance of every item; use `item_variance` instead. query crate_variances(_: CrateNum) -> &'tcx ty::CrateVariancesMap<'tcx> { desc { "computing the variances for items in this crate" } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 07c7ccfd16d..2d8601f9556 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -5,7 +5,7 @@ use crate::dep_graph::DepGraph; use crate::dep_graph::{self, DepConstructor}; use crate::hir::exports::Export; use crate::hir::map as hir_map; -use crate::hir::map::DefPathHash; +use crate::hir::map::{DefPathData, DefPathHash}; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; use crate::lint::{struct_lint_level, LintSource}; @@ -1513,14 +1513,18 @@ impl<'tcx> TyCtxt<'tcx> { ) } - /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "closure")`). - pub fn article_and_description( - &self, - def_id: crate::hir::def_id::DefId, - ) -> (&'static str, &'static str) { - match self.def_kind(def_id) { - Some(def_kind) => (def_kind.article(), def_kind.descr(def_id)), - None => self.type_of(def_id).kind.article_and_description(), + /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`). + pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) { + match self.def_key(def_id).disambiguated_data.data { + DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { + let kind = self.def_kind(def_id).unwrap(); + (kind.article(), kind.descr(def_id)) + } + DefPathData::ClosureExpr => { + // TODO + todo!(); + } + _ => bug!("article_and_description called on def_id {:?}", def_id), } } } diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 01fd637b20e..d09e68e34a6 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -500,7 +500,7 @@ impl MetadataBlob { } } -impl<'tcx> EntryKind<'tcx> { +impl EntryKind { fn def_kind(&self) -> Option { Some(match *self { EntryKind::Const(..) => DefKind::Const, @@ -614,11 +614,11 @@ impl<'a, 'tcx> CrateMetadata { self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some() } - fn maybe_kind(&self, item_id: DefIndex) -> Option> { + fn maybe_kind(&self, item_id: DefIndex) -> Option { self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self)) } - fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> { + fn kind(&self, item_id: DefIndex) -> EntryKind { assert!(!self.is_proc_macro(item_id)); self.maybe_kind(item_id).unwrap_or_else(|| { bug!( @@ -723,7 +723,7 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant( &self, tcx: TyCtxt<'tcx>, - kind: &EntryKind<'_>, + kind: &EntryKind, index: DefIndex, parent_did: DefId, ) -> ty::VariantDef { @@ -1390,6 +1390,13 @@ impl<'a, 'tcx> CrateMetadata { } } + fn generator_kind(&self, id: DefIndex) -> Option { + match self.kind(id) { + EntryKind::Generator(data) => Some(data.decode(self)), + _ => None, + } + } + fn fn_sig(&self, id: DefIndex, tcx: TyCtxt<'tcx>) -> ty::PolyFnSig<'tcx> { self.root.per_def.fn_sig.get(self, id).unwrap().decode((self, tcx)) } @@ -1499,8 +1506,8 @@ impl<'a, 'tcx> CrateMetadata { ); debug!( "CrateMetaData::imported_source_files alloc \ - source_file {:?} original (start_pos {:?} end_pos {:?}) \ - translated (start_pos {:?} end_pos {:?})", + source_file {:?} original (start_pos {:?} end_pos {:?}) \ + translated (start_pos {:?} end_pos {:?})", local_version.name, start_pos, end_pos, diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index fb7e5541e26..e6270e90329 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -134,6 +134,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, asyncness => { cdata.asyncness(def_id.index) } is_foreign_item => { cdata.is_foreign_item(def_id.index) } static_mutability => { cdata.static_mutability(def_id.index) } + generator_kind => { cdata.generator_kind(def_id.index) } def_kind => { cdata.def_kind(def_id.index) } def_span => { cdata.get_span(def_id.index, &tcx.sess) } lookup_stability => { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 41fc5ed843f..e985ec5fcdf 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -306,7 +306,7 @@ impl<'tcx> EncodeContext<'tcx> { assert!( last_min_end <= lazy.position, "make sure that the calls to `lazy*` \ - are in the same order as the metadata fields", + are in the same order as the metadata fields", ); lazy.position.get() - last_min_end.get() } @@ -1248,12 +1248,7 @@ impl EncodeContext<'tcx> { self.encode_deprecation(def_id); } - fn encode_info_for_generic_param( - &mut self, - def_id: DefId, - kind: EntryKind<'tcx>, - encode_type: bool, - ) { + fn encode_info_for_generic_param(&mut self, def_id: DefId, kind: EntryKind, encode_type: bool) { record!(self.per_def.kind[def_id] <- kind); record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); record!(self.per_def.span[def_id] <- self.tcx.def_span(def_id)); @@ -1271,11 +1266,8 @@ impl EncodeContext<'tcx> { let ty = self.tcx.typeck_tables_of(def_id).node_type(hir_id); record!(self.per_def.kind[def_id] <- match ty.kind { - ty::Generator(def_id, ..) => { - let layout = self.tcx.generator_layout(def_id); - let data = GeneratorData { - layout: layout.clone(), - }; + ty::Generator(..) => { + let data = self.tcx.generator_kind(def_id).unwrap(); EntryKind::Generator(self.lazy(data)) } diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 77ec3eb4555..a3e3165f31e 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -252,7 +252,7 @@ macro_rules! define_per_def_tables { } define_per_def_tables! { - kind: Table)>, + kind: Table>, visibility: Table>, span: Table>, attributes: Table>, @@ -279,7 +279,7 @@ define_per_def_tables! { } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] -enum EntryKind<'tcx> { +enum EntryKind { Const(mir::ConstQualifs, Lazy), ImmStatic, MutStatic, @@ -302,7 +302,7 @@ enum EntryKind<'tcx> { Mod(Lazy), MacroDef(Lazy), Closure, - Generator(Lazy!(GeneratorData<'tcx>)), + Generator(Lazy), Trait(Lazy), Impl(Lazy), Method(Lazy), diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index f4089b26860..8d991927d54 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -427,15 +427,17 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { errci.outlived_fr, ); - let (_, escapes_from) = - self.infcx.tcx.article_and_description(self.universal_regions.defining_ty.def_id()); + let (_, escapes_from) = self + .infcx + .tcx + .article_and_description(self.regioncx.universal_regions().defining_ty.def_id()); // Revert to the normal error in these cases. // Assignments aren't "escapes" in function items. if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) || (*category == ConstraintCategory::Assignment - && self.universal_regions.defining_ty.is_fn_def()) - || self.universal_regions.defining_ty.is_const() + && self.regioncx.universal_regions().defining_ty.is_fn_def()) + || self.regioncx.universal_regions().defining_ty.is_const() { return self.report_general_error(&ErrorConstraintInfo { fr_is_local: true, diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 6d79b7228f2..af4ea759f4f 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -132,16 +132,16 @@ impl<'tcx> DefiningTy<'tcx> { } } - pub fn is_closure(&self) -> bool { + pub fn is_fn_def(&self) -> bool { match *self { - DefiningTy::Closure(..) => true, + DefiningTy::FnDef(..) => true, _ => false, } } - pub fn is_fn_def(&self) -> bool { + pub fn is_const(&self) -> bool { match *self { - DefiningTy::FnDef(..) => true, + DefiningTy::Const(..) => true, _ => false, } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 70586be0d04..2b85cba9003 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -76,6 +76,7 @@ pub fn provide(providers: &mut Providers<'_>) { impl_polarity, is_foreign_item, static_mutability, + generator_kind, codegen_fn_attrs, collect_mod_item_types, ..*providers @@ -1006,7 +1007,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { .struct_span_err( item.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ - which traits can use parenthetical notation", + which traits can use parenthetical notation", ) .help("add `#![feature(unboxed_closures)]` to the crate attributes to use it") .emit(); @@ -2106,7 +2107,7 @@ fn compute_sig_of_foreign_fn_decl<'tcx>( ast_ty.span, &format!( "use of SIMD type `{}` in FFI is highly experimental and \ - may result in invalid code", + may result in invalid code", tcx.hir().hir_to_pretty_string(ast_ty.hir_id) ), ) @@ -2145,6 +2146,16 @@ fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option } } +fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option { + match tcx.hir().get_if_local(def_id) { + Some(Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { + tcx.hir().body(body_id).generator_kind() + } + Some(_) => None, + _ => bug!("generator_kind applied to non-local def-id {:?}", def_id), + } +} + fn from_target_feature( tcx: TyCtxt<'_>, id: DefId, From c6781037eb5864b532094ade1fdbeea336af1836 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 25 Jan 2020 19:31:38 -0600 Subject: [PATCH 0442/1250] article and descr for closures --- src/librustc/ty/context.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 2d8601f9556..4db20817e64 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1520,10 +1520,11 @@ impl<'tcx> TyCtxt<'tcx> { let kind = self.def_kind(def_id).unwrap(); (kind.article(), kind.descr(def_id)) } - DefPathData::ClosureExpr => { - // TODO - todo!(); - } + DefPathData::ClosureExpr => match self.generator_kind(def_id) { + None => ("a", "closure"), + Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), + Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), + }, _ => bug!("article_and_description called on def_id {:?}", def_id), } } From 74360571e9850840c093bdba2310fa7b8f898a0f Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 8 Feb 2020 16:33:50 -0600 Subject: [PATCH 0443/1250] address some review comments/bugs --- src/librustc/ty/context.rs | 2 ++ src/librustc_typeck/collect.rs | 7 ++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 4db20817e64..7237b50d8f3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1525,6 +1525,8 @@ impl<'tcx> TyCtxt<'tcx> { Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), }, + DefPathData::LifetimeNs(..) => ("a", "lifetime"), + DefPathData::Impl => ("an", "implementation"), _ => bug!("article_and_description called on def_id {:?}", def_id), } } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2b85cba9003..869a1dcbcc7 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2148,9 +2148,10 @@ fn static_mutability(tcx: TyCtxt<'_>, def_id: DefId) -> Option fn generator_kind(tcx: TyCtxt<'_>, def_id: DefId) -> Option { match tcx.hir().get_if_local(def_id) { - Some(Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. })) => { - tcx.hir().body(body_id).generator_kind() - } + Some(Node::Expr(&rustc_hir::Expr { + kind: rustc_hir::ExprKind::Closure(_, _, body_id, _, _), + .. + })) => tcx.hir().body(body_id).generator_kind(), Some(_) => None, _ => bug!("generator_kind applied to non-local def-id {:?}", def_id), } From 9207a13bfc48ebc8582555abd922748a69d2488c Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 22 Feb 2020 13:05:32 -0600 Subject: [PATCH 0444/1250] get rid of lazy --- src/librustc_metadata/rmeta/decoder.rs | 2 +- src/librustc_metadata/rmeta/encoder.rs | 2 +- src/librustc_metadata/rmeta/mod.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index d09e68e34a6..2576514735b 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1392,7 +1392,7 @@ impl<'a, 'tcx> CrateMetadata { fn generator_kind(&self, id: DefIndex) -> Option { match self.kind(id) { - EntryKind::Generator(data) => Some(data.decode(self)), + EntryKind::Generator(data) => Some(data), _ => None, } } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index e985ec5fcdf..ee54f40ece5 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1268,7 +1268,7 @@ impl EncodeContext<'tcx> { record!(self.per_def.kind[def_id] <- match ty.kind { ty::Generator(..) => { let data = self.tcx.generator_kind(def_id).unwrap(); - EntryKind::Generator(self.lazy(data)) + EntryKind::Generator(data) } ty::Closure(..) => EntryKind::Closure, diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index a3e3165f31e..01a3f6c560f 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -302,7 +302,7 @@ enum EntryKind { Mod(Lazy), MacroDef(Lazy), Closure, - Generator(Lazy), + Generator(hir::GeneratorKind), Trait(Lazy), Impl(Lazy), Method(Lazy), From 7a6361f4655fe26f6f25efc551242115953ae335 Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 22 Feb 2020 13:09:54 -0600 Subject: [PATCH 0445/1250] remove unneeded fn --- src/librustc/ty/sty.rs | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index a54bf4d7eff..c3698f402a9 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -254,41 +254,6 @@ pub enum TyKind<'tcx> { Error, } -impl<'tcx> TyKind<'tcx> { - pub fn article_and_description(&self) -> (&'static str, &'static str) { - match *self { - Bool => ("a", "boolean value"), - Char => ("a", "character"), - Int(..) => ("a", "signed interger"), - Uint(..) => ("an", "unsigned integer"), - Float(..) => ("a", "floating point number"), - Adt(..) => ("an", "abstract data type"), - Foreign(..) => ("a", "foreign type"), - Str => ("a", "string slice"), - Array(..) => ("an", "array"), - Slice(..) => ("a", "slice"), - RawPtr(..) => ("a", "raw pointer"), - Ref(..) => ("a", "reference"), - FnDef(..) => ("a", "function"), - FnPtr(..) => ("a", "function pointer"), - Dynamic(..) => ("a", "trait object"), - Closure(..) => ("a", "closure"), - Generator(..) => ("a", "generator"), - GeneratorWitness(..) => ("a", "generator witness"), - Never => ("a", "never"), - Tuple(..) => ("a", "tuple"), - Projection(..) => ("a", "projection"), - UnnormalizedProjection(..) => ("an", "unnormalized projection"), - Opaque(..) => ("an", "opaque type"), - Param(..) => ("a", "type parameter"), - Bound(..) => ("a", "bound type variable"), - Placeholder(..) => ("a", "universally quantified higher-ranked type"), - Infer(..) => ("an", "inference variable"), - Error => ("a", "type error"), - } - } -} - // `TyKind` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] static_assert_size!(TyKind<'_>, 24); From fa1f547f82d66f986af2c33220199b042fcb5f99 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 22 Feb 2020 11:36:09 -0800 Subject: [PATCH 0446/1250] Add more double cast + method call tests --- .../parser/issue-35813-postfix-after-cast.rs | 23 ++++ .../issue-35813-postfix-after-cast.stderr | 104 ++++++++++++++---- 2 files changed, 105 insertions(+), 22 deletions(-) diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index d04a092e93b..5c6e0ce5024 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -35,6 +35,29 @@ pub fn cast_after_cast() { let _ = 0i32: i32: i32 as u32 as i32; } +pub fn cast_cast_method_call() { + let _ = 0i32: i32: i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32: i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32.count_ones(): u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32.count_ones(): u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32.count_ones() as u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0 as i32.count_ones() as u32; + //~^ ERROR: casts cannot be followed by a method call + let _ = 0i32: i32: i32.count_ones() as u32 as i32; + //~^ ERROR: casts cannot be followed by a method call +} + // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index f96000ea0aa..42b614edf76 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -22,68 +22,128 @@ error: casts cannot be followed by indexing LL | (&[0i32]): &[i32; 1][0]; | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:39:13 + | +LL | let _ = 0i32: i32: i32.count_ones(); + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:41:13 + | +LL | let _ = 0 as i32: i32.count_ones(); + | ^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:43:13 + | +LL | let _ = 0i32: i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:45:13 + | +LL | let _ = 0 as i32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:47:13 + | +LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32 as u32 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:49:13 + | +LL | let _ = 0i32: i32.count_ones(): u32; + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:51:13 + | +LL | let _ = 0 as i32.count_ones(): u32; + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:53:13 + | +LL | let _ = 0i32: i32.count_ones() as u32; + | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:55:13 + | +LL | let _ = 0 as i32.count_ones() as u32; + | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:57:13 + | +LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; + | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:40:18 + --> $DIR/issue-35813-postfix-after-cast.rs:63:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:45:5 + --> $DIR/issue-35813-postfix-after-cast.rs:68:5 | LL | 0 as i32.max(0); | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:47:5 + --> $DIR/issue-35813-postfix-after-cast.rs:70:5 | LL | 0: i32.max(0); | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:62:8 + --> $DIR/issue-35813-postfix-after-cast.rs:85:8 | LL | if 5u64 as i32.max(0) == 0 { | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:65:8 + --> $DIR/issue-35813-postfix-after-cast.rs:88:8 | LL | if 5u64: u64.max(0) == 0 { | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:72:9 + --> $DIR/issue-35813-postfix-after-cast.rs:95:9 | LL | 5u64 as u32.max(0) == 0 | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:76:9 + --> $DIR/issue-35813-postfix-after-cast.rs:99:9 | LL | 5u64: u64.max(0) == 0 | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:81:24 + --> $DIR/issue-35813-postfix-after-cast.rs:104:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:84:25 + --> $DIR/issue-35813-postfix-after-cast.rs:107:25 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:89:5 + --> $DIR/issue-35813-postfix-after-cast.rs:112:5 | LL | Err(0u64) as Result?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:91:5 + --> $DIR/issue-35813-postfix-after-cast.rs:114:5 | LL | Err(0u64): Result?; | ^^^^^^^^^-^^^^^^^^^^^^^^^^ @@ -94,25 +154,25 @@ LL | Err(0u64): Result?; = note: see issue #23416 for more information error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:115:5 + --> $DIR/issue-35813-postfix-after-cast.rs:138:5 | LL | drop as fn(u8)(0); | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:117:5 + --> $DIR/issue-35813-postfix-after-cast.rs:140:5 | LL | drop_ptr: fn(u8)(0); | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:122:5 + --> $DIR/issue-35813-postfix-after-cast.rs:145:5 | LL | Box::pin(noop()) as Pin>>.await; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:125:5 + --> $DIR/issue-35813-postfix-after-cast.rs:148:5 | LL | Box::pin(noop()): Pin>.await; | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ @@ -123,41 +183,41 @@ LL | Box::pin(noop()): Pin>.await; = note: see issue #23416 for more information error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:137:5 + --> $DIR/issue-35813-postfix-after-cast.rs:160:5 | LL | Foo::default() as Foo.bar; | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:139:5 + --> $DIR/issue-35813-postfix-after-cast.rs:162:5 | LL | Foo::default(): Foo.bar; | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:54:9 + --> $DIR/issue-35813-postfix-after-cast.rs:77:9 | LL | if true { 33 } else { 44 } as i32.max(0), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:56:9 + --> $DIR/issue-35813-postfix-after-cast.rs:79:9 | LL | if true { 33 } else { 44 }: i32.max(0) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:101:13 + --> $DIR/issue-35813-postfix-after-cast.rs:124:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:103:15 + --> $DIR/issue-35813-postfix-after-cast.rs:126:15 | LL | drop_ptr: F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 25 previous errors +error: aborting due to 35 previous errors For more information about this error, try `rustc --explain E0214`. From 03ca0e270613592f35ce654e2ef1e68cdfb154e3 Mon Sep 17 00:00:00 2001 From: John Ericson Date: Sat, 22 Feb 2020 14:38:38 -0500 Subject: [PATCH 0447/1250] Allow getting `no_std` from the config file Currently, it is only set correctly in the sanity checking implicit default fallback code. Having a config file at all will for force `no_std = false`. --- src/bootstrap/config.rs | 3 +++ src/bootstrap/sanity.rs | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 214d572329e..b474d896bd2 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -353,6 +353,7 @@ struct TomlTarget { musl_root: Option, wasi_root: Option, qemu_rootfs: Option, + no_std: Option, } impl Config { @@ -615,6 +616,8 @@ impl Config { target.musl_root = cfg.musl_root.clone().map(PathBuf::from); target.wasi_root = cfg.wasi_root.clone().map(PathBuf::from); target.qemu_rootfs = cfg.qemu_rootfs.clone().map(PathBuf::from); + target.no_std = + cfg.no_std.unwrap_or(triple.contains("-none-") || triple.contains("nvptx")); config.target_config.insert(INTERNER.intern_string(triple.clone()), target); } diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 8ff7056e628..76e721ed8e3 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -194,9 +194,7 @@ pub fn check(build: &mut Build) { if target.contains("-none-") || target.contains("nvptx") { if build.no_std(*target).is_none() { - let target = build.config.target_config.entry(target.clone()).or_default(); - - target.no_std = true; + build.config.target_config.entry(target.clone()).or_default(); } if build.no_std(*target) == Some(false) { From f434c6e636eda6c6c4fe167eee5b2549f8524ec7 Mon Sep 17 00:00:00 2001 From: David Ross Date: Sat, 22 Feb 2020 12:33:06 -0800 Subject: [PATCH 0448/1250] Use multipart suggestion This is a modified version of estebank's suggestion, with a bit of extra cleanup now that we don't need the different cases for if we can turn a span into a string or not. --- src/librustc_parse/parser/expr.rs | 22 +- .../parser/issue-35813-postfix-after-cast.rs | 7 + .../issue-35813-postfix-after-cast.stderr | 275 ++++++++++++++---- 3 files changed, 238 insertions(+), 66 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3d0f746d395..12729019e9b 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -648,8 +648,6 @@ impl<'a> Parser<'a> { if !matches!(with_postfix.kind, ExprKind::Cast(_, _) | ExprKind::Type(_, _)) || after_hash != before_hash { - let expr_str = self.span_to_snippet(span); - let msg = format!( "casts cannot be followed by {}", match with_postfix.kind { @@ -663,22 +661,20 @@ impl<'a> Parser<'a> { } ); let mut err = self.struct_span_err(span, &msg); - let suggestion = "try surrounding the expression in parentheses"; // if type ascription is "likely an error", the user will already be getting a useful // help message, and doesn't need a second. if self.last_type_ascription.map_or(false, |last_ascription| last_ascription.1) { self.maybe_annotate_with_ascription(&mut err, false); } else { - if let Ok(expr_str) = expr_str { - err.span_suggestion( - span, - suggestion, - format!("({})", expr_str), - Applicability::MachineApplicable, - ); - } else { - err.span_help(span, suggestion); - } + let suggestions = vec![ + (span.shrink_to_lo(), "(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ]; + err.multipart_suggestion( + "try surrounding the expression in parentheses", + suggestions, + Applicability::MachineApplicable, + ); } err.emit(); }; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.rs b/src/test/ui/parser/issue-35813-postfix-after-cast.rs index 5c6e0ce5024..e725aa5d73d 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.rs +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.rs @@ -58,6 +58,13 @@ pub fn cast_cast_method_call() { //~^ ERROR: casts cannot be followed by a method call } +pub fn multiline_error() { + let _ = 0 + as i32 + .count_ones(); + //~^^^ ERROR: casts cannot be followed by a method call +} + // this tests that the precedence for `!x as Y.Z` is still what we expect pub fn precedence() { let x: i32 = &vec![1, 2, 3] as &Vec[0]; diff --git a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr index 42b614edf76..255e9f40921 100644 --- a/src/test/ui/parser/issue-35813-postfix-after-cast.stderr +++ b/src/test/ui/parser/issue-35813-postfix-after-cast.stderr @@ -2,148 +2,282 @@ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:10:5 | LL | vec![1, 2, 3] as Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3] as Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3] as Vec)[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:12:5 | LL | vec![1, 2, 3]: Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(vec![1, 2, 3]: Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (vec![1, 2, 3]: Vec)[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:17:5 | LL | (&[0]) as &[i32][0]; - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0]) as &[i32])` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0]) as &[i32])[0]; + | ^ ^ error: casts cannot be followed by indexing --> $DIR/issue-35813-postfix-after-cast.rs:19:5 | LL | (&[0i32]): &[i32; 1][0]; - | ^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `((&[0i32]): &[i32; 1])` + | ^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | ((&[0i32]): &[i32; 1])[0]; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:39:13 | LL | let _ = 0i32: i32: i32.count_ones(); - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:41:13 | LL | let _ = 0 as i32: i32.count_ones(); - | ^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32: i32)` + | ^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32: i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:43:13 | LL | let _ = 0i32: i32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32 as i32)` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:45:13 | LL | let _ = 0 as i32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32 as i32)` + | ^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:47:13 | LL | let _ = 0i32: i32: i32 as u32 as i32.count_ones(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32 as u32 as i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32 as u32 as i32).count_ones(); + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:49:13 | LL | let _ = 0i32: i32.count_ones(): u32; - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones(): u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:51:13 | LL | let _ = 0 as i32.count_ones(): u32; - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones(): u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:53:13 | LL | let _ = 0i32: i32.count_ones() as u32; - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32).count_ones() as u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:55:13 | LL | let _ = 0 as i32.count_ones() as u32; - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 as i32).count_ones() as u32; + | ^ ^ error: casts cannot be followed by a method call --> $DIR/issue-35813-postfix-after-cast.rs:57:13 | LL | let _ = 0i32: i32: i32.count_ones() as u32 as i32; - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(0i32: i32: i32)` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0i32: i32: i32).count_ones() as u32 as i32; + | ^ ^ + +error: casts cannot be followed by a method call + --> $DIR/issue-35813-postfix-after-cast.rs:62:13 + | +LL | let _ = 0 + | _____________^ +LL | | as i32 + | |______________^ + | +help: try surrounding the expression in parentheses + | +LL | let _ = (0 +LL | as i32) + | error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:63:18 + --> $DIR/issue-35813-postfix-after-cast.rs:70:18 | LL | let x: i32 = &vec![1, 2, 3] as &Vec[0]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&vec![1, 2, 3] as &Vec)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | let x: i32 = (&vec![1, 2, 3] as &Vec)[0]; + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:68:5 + --> $DIR/issue-35813-postfix-after-cast.rs:75:5 | LL | 0 as i32.max(0); - | ^^^^^^^^ help: try surrounding the expression in parentheses: `(0 as i32)` + | ^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0 as i32).max(0); + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:70:5 + --> $DIR/issue-35813-postfix-after-cast.rs:77:5 | LL | 0: i32.max(0); - | ^^^^^^ help: try surrounding the expression in parentheses: `(0: i32)` + | ^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (0: i32).max(0); + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:85:8 + --> $DIR/issue-35813-postfix-after-cast.rs:92:8 | LL | if 5u64 as i32.max(0) == 0 { - | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as i32)` + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64 as i32).max(0) == 0 { + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:88:8 + --> $DIR/issue-35813-postfix-after-cast.rs:95:8 | LL | if 5u64: u64.max(0) == 0 { - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | if (5u64: u64).max(0) == 0 { + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:95:9 + --> $DIR/issue-35813-postfix-after-cast.rs:102:9 | LL | 5u64 as u32.max(0) == 0 - | ^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64 as u32)` + | ^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64 as u32).max(0) == 0 + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:99:9 + --> $DIR/issue-35813-postfix-after-cast.rs:106:9 | LL | 5u64: u64.max(0) == 0 - | ^^^^^^^^^ help: try surrounding the expression in parentheses: `(5u64: u64)` + | ^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (5u64: u64).max(0) == 0 + | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:104:24 + --> $DIR/issue-35813-postfix-after-cast.rs:111:24 | LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]); - | ^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1,2,3] as &[i32])` + | ^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar: &[i32] = &((&[1,2,3] as &[i32])[0..1]); + | ^ ^ error: casts cannot be followed by indexing - --> $DIR/issue-35813-postfix-after-cast.rs:107:25 + --> $DIR/issue-35813-postfix-after-cast.rs:114:25 | LL | static bar2: &[i32] = &(&[1i32,2,3]: &[i32; 3][0..1]); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(&[1i32,2,3]: &[i32; 3])` + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | static bar2: &[i32] = &((&[1i32,2,3]: &[i32; 3])[0..1]); + | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:112:5 + --> $DIR/issue-35813-postfix-after-cast.rs:119:5 | LL | Err(0u64) as Result?; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Err(0u64) as Result)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Err(0u64) as Result)?; + | ^ ^ error: casts cannot be followed by ? - --> $DIR/issue-35813-postfix-after-cast.rs:114:5 + --> $DIR/issue-35813-postfix-after-cast.rs:121:5 | LL | Err(0u64): Result?; | ^^^^^^^^^-^^^^^^^^^^^^^^^^ @@ -154,25 +288,40 @@ LL | Err(0u64): Result?; = note: see issue #23416 for more information error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:138:5 + --> $DIR/issue-35813-postfix-after-cast.rs:145:5 | LL | drop as fn(u8)(0); - | ^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop as fn(u8))` + | ^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop as fn(u8))(0); + | ^ ^ error: casts cannot be followed by a function call - --> $DIR/issue-35813-postfix-after-cast.rs:140:5 + --> $DIR/issue-35813-postfix-after-cast.rs:147:5 | LL | drop_ptr: fn(u8)(0); - | ^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(drop_ptr: fn(u8))` + | ^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (drop_ptr: fn(u8))(0); + | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:145:5 + --> $DIR/issue-35813-postfix-after-cast.rs:152:5 | LL | Box::pin(noop()) as Pin>>.await; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Box::pin(noop()) as Pin>>)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Box::pin(noop()) as Pin>>).await; + | ^ ^ error: casts cannot be followed by `.await` - --> $DIR/issue-35813-postfix-after-cast.rs:148:5 + --> $DIR/issue-35813-postfix-after-cast.rs:155:5 | LL | Box::pin(noop()): Pin>.await; | ^^^^^^^^^^^^^^^^-^^^^^^^^^^^^ @@ -183,41 +332,61 @@ LL | Box::pin(noop()): Pin>.await; = note: see issue #23416 for more information error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:160:5 + --> $DIR/issue-35813-postfix-after-cast.rs:167:5 | LL | Foo::default() as Foo.bar; - | ^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default() as Foo)` + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default() as Foo).bar; + | ^ ^ error: casts cannot be followed by a field access - --> $DIR/issue-35813-postfix-after-cast.rs:162:5 + --> $DIR/issue-35813-postfix-after-cast.rs:169:5 | LL | Foo::default(): Foo.bar; - | ^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(Foo::default(): Foo)` + | ^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (Foo::default(): Foo).bar; + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:77:9 + --> $DIR/issue-35813-postfix-after-cast.rs:84:9 | LL | if true { 33 } else { 44 } as i32.max(0), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 } as i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 } as i32).max(0), + | ^ ^ error: casts cannot be followed by a method call - --> $DIR/issue-35813-postfix-after-cast.rs:79:9 + --> $DIR/issue-35813-postfix-after-cast.rs:86:9 | LL | if true { 33 } else { 44 }: i32.max(0) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try surrounding the expression in parentheses: `(if true { 33 } else { 44 }: i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try surrounding the expression in parentheses + | +LL | (if true { 33 } else { 44 }: i32).max(0) + | ^ ^ error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:124:13 + --> $DIR/issue-35813-postfix-after-cast.rs:131:13 | LL | drop as F(); | ^^^ only `Fn` traits may use parentheses error[E0214]: parenthesized type parameters may only be used with a `Fn` trait - --> $DIR/issue-35813-postfix-after-cast.rs:126:15 + --> $DIR/issue-35813-postfix-after-cast.rs:133:15 | LL | drop_ptr: F(); | ^^^ only `Fn` traits may use parentheses -error: aborting due to 35 previous errors +error: aborting due to 36 previous errors For more information about this error, try `rustc --explain E0214`. From 9e41c4b682f625ae7860255c2d17790f5d9f324a Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Sat, 22 Feb 2020 13:28:53 -0800 Subject: [PATCH 0449/1250] Relax str::get_unchecked precondition to permit empty slicing Prior to this commit, `str` documented that `get_unchecked` had the precondition that "`begin` must come before `end`". This would appear to prohibit empty slices (i.e. begin == end). In practice, get_unchecked is called often with empty slices. Let's relax the precondition so as to allow them. --- src/libcore/str/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 668b3ff3a36..9c0db5d9872 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2486,7 +2486,7 @@ impl str { /// Callers of this function are responsible that these preconditions are /// satisfied: /// - /// * The starting index must come before the ending index; + /// * The starting index must not exceed the ending index; /// * Indexes must be within bounds of the original slice; /// * Indexes must lie on UTF-8 sequence boundaries. /// @@ -2518,7 +2518,7 @@ impl str { /// Callers of this function are responsible that these preconditions are /// satisfied: /// - /// * The starting index must come before the ending index; + /// * The starting index must not exceed the ending index; /// * Indexes must be within bounds of the original slice; /// * Indexes must lie on UTF-8 sequence boundaries. /// @@ -2563,7 +2563,7 @@ impl str { /// Callers of this function are responsible that three preconditions are /// satisfied: /// - /// * `begin` must come before `end`. + /// * `begin` must not exceed `end`. /// * `begin` and `end` must be byte positions within the string slice. /// * `begin` and `end` must lie on UTF-8 sequence boundaries. /// @@ -2612,7 +2612,7 @@ impl str { /// Callers of this function are responsible that three preconditions are /// satisfied: /// - /// * `begin` must come before `end`. + /// * `begin` must not exceed `end`. /// * `begin` and `end` must be byte positions within the string slice. /// * `begin` and `end` must lie on UTF-8 sequence boundaries. #[stable(feature = "str_slice_mut", since = "1.5.0")] From 9434d6b67fb0817e7db5217e6355cbf4c7e402f6 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sat, 22 Feb 2020 16:14:14 -0600 Subject: [PATCH 0450/1250] update some tests --- .../ui/async-await/issues/issue-62097.nll.stderr | 6 +++--- .../ui/async-await/issues/issue-63388-1.nll.stderr | 2 +- src/test/ui/issues/issue-16683.nll.stderr | 6 +++--- src/test/ui/issues/issue-17758.nll.stderr | 6 +++--- ...one-existing-name-if-else-using-impl.nll.stderr | 2 +- ...ne-existing-name-return-type-is-anon.nll.stderr | 2 +- ...eturn-one-existing-name-self-is-anon.nll.stderr | 2 +- ...oth-anon-regions-return-type-is-anon.nll.stderr | 2 +- .../ex3-both-anon-regions-self-is-anon.nll.stderr | 2 +- src/test/ui/nll/outlives-suggestion-simple.rs | 2 +- src/test/ui/nll/outlives-suggestion-simple.stderr | 8 ++++---- ...lf_types_pin_lifetime_mismatch-async.nll.stderr | 6 +++--- ...ary_self_types_pin_lifetime_mismatch.nll.stderr | 6 +++--- .../ui/self/elision/lt-ref-self-async.nll.stderr | 12 ++++++------ src/test/ui/self/elision/lt-ref-self.nll.stderr | 12 ++++++------ .../ui/self/elision/ref-mut-self-async.nll.stderr | 12 ++++++------ src/test/ui/self/elision/ref-mut-self.nll.stderr | 12 ++++++------ .../self/elision/ref-mut-struct-async.nll.stderr | 10 +++++----- src/test/ui/self/elision/ref-mut-struct.nll.stderr | 10 +++++----- src/test/ui/self/elision/ref-self.nll.stderr | 14 +++++++------- .../ui/self/elision/ref-struct-async.nll.stderr | 10 +++++----- src/test/ui/self/elision/ref-struct.nll.stderr | 10 +++++----- 22 files changed, 77 insertions(+), 77 deletions(-) diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr index 0c64f90cb9f..f72c645bf8d 100644 --- a/src/test/ui/async-await/issues/issue-62097.nll.stderr +++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr @@ -16,13 +16,13 @@ help: to force the closure to take ownership of `self` (and any other referenced LL | foo(move || self.bar()).await; | ^^^^^^^ -error[E0521]: borrowed data escapes outside of function +error[E0521]: borrowed data escapes outside of method --> $DIR/issue-62097.rs:13:9 | LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the function body + | ----- `self` is a reference that is only valid in the method body LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the function body here + | ^^^^^^^^^^^^^^^^^^ `self` escapes the method body here error: aborting due to 2 previous errors 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 index 8e0e1ce3dc3..696f79ec40f 100644 --- a/src/test/ui/async-await/issues/issue-63388-1.nll.stderr +++ b/src/test/ui/async-await/issues/issue-63388-1.nll.stderr @@ -9,7 +9,7 @@ LL | ) -> &dyn Foo LL | / { LL | | foo LL | | } - | |_____^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | |_____^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr index ea6b69d1a76..f76e7a4e44f 100644 --- a/src/test/ui/issues/issue-16683.nll.stderr +++ b/src/test/ui/issues/issue-16683.nll.stderr @@ -1,10 +1,10 @@ -error[E0521]: borrowed data escapes outside of function +error[E0521]: borrowed data escapes outside of method --> $DIR/issue-16683.rs:4:9 | LL | fn b(&self) { - | ----- `self` is a reference that is only valid in the function body + | ----- `self` is a reference that is only valid in the method body LL | self.a(); - | ^^^^^^^^ `self` escapes the function body here + | ^^^^^^^^ `self` escapes the method body here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr index b9dc9da3683..92e21f4dc17 100644 --- a/src/test/ui/issues/issue-17758.nll.stderr +++ b/src/test/ui/issues/issue-17758.nll.stderr @@ -1,10 +1,10 @@ -error[E0521]: borrowed data escapes outside of function +error[E0521]: borrowed data escapes outside of method --> $DIR/issue-17758.rs:7:9 | LL | fn bar(&self) { - | ----- `self` is a reference that is only valid in the function body + | ----- `self` is a reference that is only valid in the method body LL | self.foo(); - | ^^^^^^^^^^ `self` escapes the function body here + | ^^^^^^^^^^ `self` escapes the method body here error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr index fc9093bb2e4..291edc505cd 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32 { | lifetime `'a` defined here LL | LL | if x > y { x } else { y } - | ^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr index 3384c24da8f..15ee58574ec 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-return-type-is-anon.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a i32) -> &i32 { | lifetime `'a` defined here LL | LL | x - | ^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | ^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr index 5ef29076e07..a27a91e38f1 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-self-is-anon.nll.stderr @@ -7,7 +7,7 @@ LL | fn foo<'a>(&self, x: &'a Foo) -> &'a Foo { | lifetime `'a` defined here LL | LL | if true { x } else { self } - | ^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` + | ^^^^ method was supposed to return data with lifetime `'a` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr index 1c258ad98ba..5f922d8560b 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-return-type-is-anon.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &i32) -> &i32 { | | | let's call the lifetime of this reference `'2` LL | x - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr index ffe39fdd8c9..91d7597c87f 100644 --- a/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-self-is-anon.nll.stderr @@ -6,7 +6,7 @@ LL | fn foo<'a>(&self, x: &Foo) -> &Foo { | | | let's call the lifetime of this reference `'2` LL | if true { x } else { self } - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to previous error diff --git a/src/test/ui/nll/outlives-suggestion-simple.rs b/src/test/ui/nll/outlives-suggestion-simple.rs index 91a7a1d71e8..ee5a80ae648 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.rs +++ b/src/test/ui/nll/outlives-suggestion-simple.rs @@ -70,7 +70,7 @@ pub struct Foo2<'a> { impl<'a> Foo2<'a> { // should not produce outlives suggestions to name 'self fn get_bar(&self) -> Bar2 { - Bar2::new(&self) //~ERROR borrowed data escapes outside of function + Bar2::new(&self) //~ERROR borrowed data escapes outside of method } } diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr index db7f57ceccf..cf55603cd71 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.stderr +++ b/src/test/ui/nll/outlives-suggestion-simple.stderr @@ -93,16 +93,16 @@ LL | self.x | = help: consider adding the following bound: `'b: 'a` -error[E0521]: borrowed data escapes outside of function +error[E0521]: borrowed data escapes outside of method --> $DIR/outlives-suggestion-simple.rs:73:9 | LL | fn get_bar(&self) -> Bar2 { | ----- | | - | `self` declared here, outside of the function body - | `self` is a reference that is only valid in the function body + | `self` declared here, outside of the method body + | `self` is a reference that is only valid in the method body LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ `self` escapes the function body here + | ^^^^^^^^^^^^^^^^ `self` escapes the method body here error: aborting due to 9 previous errors 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 index 61f6680d5a4..6afcf24cd3e 100644 --- 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 @@ -2,7 +2,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:8:52 | LL | async fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | - - ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -11,7 +11,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:11:75 | LL | async fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | - - ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -20,7 +20,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch-async.rs:17:64 | LL | async fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- - ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | -- - ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` | | | | | let's call the lifetime of this reference `'1` | lifetime `'a` defined here diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr index 1a0904fcbba..a659e448785 100644 --- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr +++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_mismatch.nll.stderr @@ -2,7 +2,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:6:46 | LL | fn a(self: Pin<&Foo>, f: &Foo) -> &Foo { f } - | - - ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -11,7 +11,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:8:69 | LL | fn c(self: Pin<&Self>, f: &Foo, g: &Foo) -> (Pin<&Foo>, &Foo) { (self, f) } - | - - ^^^^^^^^^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | - - ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` | | | | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` @@ -20,7 +20,7 @@ error: lifetime may not live long enough --> $DIR/arbitrary_self_types_pin_lifetime_mismatch.rs:13:58 | LL | fn bar<'a>(self: Alias<&Self>, arg: &'a ()) -> &() { arg } - | -- ---- has type `std::pin::Pin<&'1 Foo>` ^^^ function was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` + | -- ---- has type `std::pin::Pin<&'1 Foo>` ^^^ method was supposed to return data with lifetime `'1` but it is returning data with lifetime `'a` | | | lifetime `'a` defined here 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 index e66711076e8..57d0929c50a 100644 --- a/src/test/ui/self/elision/lt-ref-self-async.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:19:9 @@ -16,7 +16,7 @@ LL | async fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:23:9 @@ -26,7 +26,7 @@ LL | async fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:27:9 @@ -36,7 +36,7 @@ LL | async fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:31:9 @@ -46,7 +46,7 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self-async.rs:35:9 @@ -56,7 +56,7 @@ LL | async fn box_pin_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/lt-ref-self.nll.stderr b/src/test/ui/self/elision/lt-ref-self.nll.stderr index a0c56f22218..b51b5a0ba38 100644 --- a/src/test/ui/self/elision/lt-ref-self.nll.stderr +++ b/src/test/ui/self/elision/lt-ref-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:17:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:21:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:25:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:29:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/lt-ref-self.rs:33:9 @@ -56,7 +56,7 @@ LL | fn box_pin_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors 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 index 82098cd4f07..46e828390b0 100644 --- a/src/test/ui/self/elision/ref-mut-self-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_self(&mut self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:19:9 @@ -16,7 +16,7 @@ LL | async fn ref_Self(self: &mut Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:23:9 @@ -26,7 +26,7 @@ LL | async fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:27:9 @@ -36,7 +36,7 @@ LL | async fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:31:9 @@ -46,7 +46,7 @@ LL | async fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self-async.rs:35:9 @@ -56,7 +56,7 @@ LL | async fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 6 previous errors diff --git a/src/test/ui/self/elision/ref-mut-self.nll.stderr b/src/test/ui/self/elision/ref-mut-self.nll.stderr index 4e7d7f521d2..6c8c030e5ff 100644 --- a/src/test/ui/self/elision/ref-mut-self.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&mut self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:17:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &mut Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:21:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:25:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&mut Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:29:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-self.rs:33:9 @@ -56,7 +56,7 @@ LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` 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 index 736cebae4bc..99340800790 100644 --- a/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:17:9 @@ -16,7 +16,7 @@ LL | async fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:21:9 @@ -26,7 +26,7 @@ LL | async fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:25:9 @@ -36,7 +36,7 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct-async.rs:29:9 @@ -46,7 +46,7 @@ LL | async fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-mut-struct.nll.stderr b/src/test/ui/self/elision/ref-mut-struct.nll.stderr index cec7034cd9f..e3886444db2 100644 --- a/src/test/ui/self/elision/ref-mut-struct.nll.stderr +++ b/src/test/ui/self/elision/ref-mut-struct.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &mut Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:15:9 @@ -16,7 +16,7 @@ LL | fn box_ref_Struct(self: Box<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:19:9 @@ -26,7 +26,7 @@ LL | fn pin_ref_Struct(self: Pin<&mut Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:23:9 @@ -36,7 +36,7 @@ LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-mut-struct.rs:27:9 @@ -46,7 +46,7 @@ LL | fn box_pin_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-self.nll.stderr b/src/test/ui/self/elision/ref-self.nll.stderr index 20045be0527..ecac1ce3378 100644 --- a/src/test/ui/self/elision/ref-self.nll.stderr +++ b/src/test/ui/self/elision/ref-self.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_self(&self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:27:9 @@ -16,7 +16,7 @@ LL | fn ref_Self(self: &Self, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:31:9 @@ -26,7 +26,7 @@ LL | fn box_ref_Self(self: Box<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:35:9 @@ -36,7 +36,7 @@ LL | fn pin_ref_Self(self: Pin<&Self>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:39:9 @@ -46,7 +46,7 @@ LL | fn box_box_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:43:9 @@ -56,7 +56,7 @@ LL | fn box_pin_ref_Self(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-self.rs:47:9 @@ -66,7 +66,7 @@ LL | fn wrap_ref_Self_Self(self: Wrap<&Self, Self>, f: &u8) -> &u8 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` 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 index 5d7dd76827a..bcbf79bc039 100644 --- a/src/test/ui/self/elision/ref-struct-async.nll.stderr +++ b/src/test/ui/self/elision/ref-struct-async.nll.stderr @@ -6,7 +6,7 @@ LL | async fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:17:9 @@ -16,7 +16,7 @@ LL | async fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:21:9 @@ -26,7 +26,7 @@ LL | async fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:25:9 @@ -36,7 +36,7 @@ LL | async fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct-async.rs:29:9 @@ -46,7 +46,7 @@ LL | async fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors diff --git a/src/test/ui/self/elision/ref-struct.nll.stderr b/src/test/ui/self/elision/ref-struct.nll.stderr index 31bb9f49a6c..39e7631f31e 100644 --- a/src/test/ui/self/elision/ref-struct.nll.stderr +++ b/src/test/ui/self/elision/ref-struct.nll.stderr @@ -6,7 +6,7 @@ LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:15:9 @@ -16,7 +16,7 @@ LL | fn box_ref_Struct(self: Box<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:19:9 @@ -26,7 +26,7 @@ LL | fn pin_ref_Struct(self: Pin<&Struct>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:23:9 @@ -36,7 +36,7 @@ LL | fn box_box_ref_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: lifetime may not live long enough --> $DIR/ref-struct.rs:27:9 @@ -46,7 +46,7 @@ LL | fn box_pin_Struct(self: Box>, f: &u32) -> &u32 { | | | let's call the lifetime of this reference `'2` LL | f - | ^ function was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` + | ^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1` error: aborting due to 5 previous errors From 2cf339aeda77f29a8ad609f88b67591e0a668b89 Mon Sep 17 00:00:00 2001 From: Daniel Henry-Mantilla Date: Sat, 22 Feb 2020 23:19:05 +0100 Subject: [PATCH 0451/1250] Fix doc example for `MaybeUninit::get_mut()` Suggested by @ametisf in https://github.com/rust-lang/rust/pull/65948#issuecomment-589988183 Co-Authored-By: Frantisek Fladung --- src/libcore/mem/maybe_uninit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem/maybe_uninit.rs b/src/libcore/mem/maybe_uninit.rs index 5fb3c651b6b..58aaac21ad7 100644 --- a/src/libcore/mem/maybe_uninit.rs +++ b/src/libcore/mem/maybe_uninit.rs @@ -669,7 +669,7 @@ impl MaybeUninit { /// // Now we can use `buf` as a normal slice: /// buf.sort_unstable(); /// assert!( - /// buf.chunks(2).all(|chunk| chunk[0] <= chunk[1]), + /// buf.windows(2).all(|pair| pair[0] <= pair[1]), /// "buffer is sorted", /// ); /// ``` From 40c67221e272c007cfae407d4398b166754491c9 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Sat, 22 Feb 2020 15:13:22 -0800 Subject: [PATCH 0452/1250] make doc comments regular comments --- src/libstd/sys/wasi/fd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index 00327c1743c..bf7db3a799e 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -13,7 +13,7 @@ pub struct WasiFd { fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { assert_eq!(mem::size_of::>(), mem::size_of::()); assert_eq!(mem::align_of::>(), mem::align_of::()); - /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout + // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout unsafe { mem::transmute(a) } @@ -22,7 +22,7 @@ fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { assert_eq!(mem::size_of::>(), mem::size_of::()); assert_eq!(mem::align_of::>(), mem::align_of::()); - /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout + // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout unsafe { mem::transmute(a) } From 09bc5e3d969a154ffcbeb6827a901d36a6a854eb Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Sat, 22 Feb 2020 15:29:03 -0800 Subject: [PATCH 0453/1250] rustfmt darnit --- src/libstd/sys/wasi/fd.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs index bf7db3a799e..8458ded5db0 100644 --- a/src/libstd/sys/wasi/fd.rs +++ b/src/libstd/sys/wasi/fd.rs @@ -14,18 +14,14 @@ fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] { assert_eq!(mem::size_of::>(), mem::size_of::()); assert_eq!(mem::align_of::>(), mem::align_of::()); // SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout - unsafe { - mem::transmute(a) - } + unsafe { mem::transmute(a) } } fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] { assert_eq!(mem::size_of::>(), mem::size_of::()); assert_eq!(mem::align_of::>(), mem::align_of::()); // SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout - unsafe { - mem::transmute(a) - } + unsafe { mem::transmute(a) } } impl WasiFd { From d78b22f35ec367368643fe7d6f7e87d01762692b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 23 Feb 2020 00:00:00 +0000 Subject: [PATCH 0454/1250] Mark attributes consumed by `check_mod_attrs` as normal Take advantage of the fact that `check_mod_attrs` marks attributes as used and change their type to normal, so that any remaining uses will be warned about by the unused attribute lint. --- src/librustc_feature/builtin_attrs.rs | 12 +++--- src/test/ui/unused/unused-attr-crate.rs | 13 ++++++ src/test/ui/unused/unused-attr-crate.stderr | 44 +++++++++++++++++++++ 3 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/unused/unused-attr-crate.rs create mode 100644 src/test/ui/unused/unused-attr-crate.stderr diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e2e061c185c..91658db1a7a 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -234,7 +234,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(export_name, Whitelisted, template!(NameValueStr: "name")), ungated!(link_section, Whitelisted, template!(NameValueStr: "name")), ungated!(no_mangle, Whitelisted, template!(Word)), - ungated!(used, Whitelisted, template!(Word)), + ungated!(used, Normal, template!(Word)), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), @@ -250,17 +250,17 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(path, Normal, template!(NameValueStr: "file")), ungated!(no_std, CrateLevel, template!(Word)), ungated!(no_implicit_prelude, Normal, template!(Word)), - ungated!(non_exhaustive, Whitelisted, template!(Word)), + ungated!(non_exhaustive, Normal, template!(Word)), // Runtime ungated!(windows_subsystem, Whitelisted, template!(NameValueStr: "windows|console")), ungated!(panic_handler, Normal, template!(Word)), // RFC 2070 // Code generation: - ungated!(inline, Whitelisted, template!(Word, List: "always|never")), + ungated!(inline, Normal, template!(Word, List: "always|never")), ungated!(cold, Whitelisted, template!(Word)), ungated!(no_builtins, Whitelisted, template!(Word)), - ungated!(target_feature, Whitelisted, template!(List: r#"enable = "name""#)), + ungated!(target_feature, Normal, template!(List: r#"enable = "name""#)), gated!( no_sanitize, Whitelisted, template!(List: "address, memory, thread"), @@ -275,7 +275,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // ========================================================================== // Linking: - gated!(naked, Whitelisted, template!(Word), naked_functions, experimental!(naked)), + gated!(naked, Normal, template!(Word), naked_functions, experimental!(naked)), gated!( link_args, Normal, template!(NameValueStr: "args"), "the `link_args` attribute is experimental and not portable across platforms, \ @@ -332,7 +332,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), gated!(ffi_returns_twice, Whitelisted, template!(Word), experimental!(ffi_returns_twice)), - gated!(track_caller, Whitelisted, template!(Word), experimental!(track_caller)), + gated!(track_caller, Normal, template!(Word), experimental!(track_caller)), gated!( register_attr, CrateLevel, template!(List: "attr1, attr2, ..."), experimental!(register_attr), diff --git a/src/test/ui/unused/unused-attr-crate.rs b/src/test/ui/unused/unused-attr-crate.rs new file mode 100644 index 00000000000..adb939e9b40 --- /dev/null +++ b/src/test/ui/unused/unused-attr-crate.rs @@ -0,0 +1,13 @@ +#![deny(unused_attributes)] + +#![feature(naked_functions)] +#![feature(track_caller)] + +#![used] //~ ERROR unused attribute +#![non_exhaustive] //~ ERROR unused attribute +#![inline] //~ ERROR unused attribute +#![target_feature(enable = "")] //~ ERROR unused attribute +#![naked] //~ ERROR unused attribute +#![track_caller] //~ ERROR unused attribute + +fn main() {} diff --git a/src/test/ui/unused/unused-attr-crate.stderr b/src/test/ui/unused/unused-attr-crate.stderr new file mode 100644 index 00000000000..620a3ea5315 --- /dev/null +++ b/src/test/ui/unused/unused-attr-crate.stderr @@ -0,0 +1,44 @@ +error: unused attribute + --> $DIR/unused-attr-crate.rs:6:1 + | +LL | #![used] + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-attr-crate.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-crate.rs:7:1 + | +LL | #![non_exhaustive] + | ^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-crate.rs:8:1 + | +LL | #![inline] + | ^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-crate.rs:9:1 + | +LL | #![target_feature(enable = "")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-crate.rs:10:1 + | +LL | #![naked] + | ^^^^^^^^^ + +error: unused attribute + --> $DIR/unused-attr-crate.rs:11:1 + | +LL | #![track_caller] + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors + From ad47bf50f6ff9d7a73e54bed6ab518c01ae2fdc5 Mon Sep 17 00:00:00 2001 From: memoryruins Date: Sat, 22 Feb 2020 22:25:47 -0500 Subject: [PATCH 0455/1250] Add rustdoc aliases to `ptr::copy` and `ptr::copy_nonoverlapping` --- src/libcore/intrinsics.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 2cee23a5c75..43f8cfc0c47 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1515,6 +1515,7 @@ fn overlaps(src: *const T, dst: *const T, count: usize) -> bool { /// ``` /// /// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append +#[doc(alias = "memcpy")] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { @@ -1579,6 +1580,7 @@ pub unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: usize) { /// dst /// } /// ``` +#[doc(alias = "memmove")] #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub unsafe fn copy(src: *const T, dst: *mut T, count: usize) { From 78e4bd1c758b59593c02e2785e8024dbec6069f4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Feb 2020 12:02:32 +0100 Subject: [PATCH 0456/1250] Clean up E0367 explanation --- src/librustc_error_codes/error_codes/E0367.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0367.md b/src/librustc_error_codes/error_codes/E0367.md index 7d661b2f033..cfebeada272 100644 --- a/src/librustc_error_codes/error_codes/E0367.md +++ b/src/librustc_error_codes/error_codes/E0367.md @@ -1,8 +1,9 @@ An attempt was made to implement `Drop` on a specialization of a generic type. -An example is shown below: + +Erroneous code example: ```compile_fail,E0367 -trait Foo{} +trait Foo {} struct MyStruct { t: T From c103a16f3a0c56351270eca9624acc27e2804bce Mon Sep 17 00:00:00 2001 From: Michael Morehouse <640167+yawpitch@users.noreply.github.com> Date: Sat, 22 Feb 2020 11:49:52 +0000 Subject: [PATCH 0457/1250] Update links Formatting fixes Now that I can actually run `python x.py test src/tools/tidy` locally ... my god it takes a long time to compile when you're on a cellular connection. Removing unnecessary whitespaces Updates src/test/ui/json-short.stderr golden test file Fixes test failure by updating the golden file for changes in src/librustc_error_codes/error_codes/E0601.md Update src/librustc_error_codes/error_codes/E0080.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0080.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0080.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0154.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0154.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0661.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0662.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0663.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0664.md Co-Authored-By: varkor Update src/test/ui/json-short.stderr Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0260.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0154.md Co-Authored-By: varkor Update src/librustc_error_codes/error_codes/E0260.md Co-Authored-By: varkor Apply suggestions from code review Co-Authored-By: varkor Fixing 1 character over 80 cascade --- src/librustc_error_codes/error_codes/E0080.md | 9 ++++++--- src/librustc_error_codes/error_codes/E0133.md | 4 +++- src/librustc_error_codes/error_codes/E0154.md | 7 ++++--- src/librustc_error_codes/error_codes/E0260.md | 7 ++++--- src/librustc_error_codes/error_codes/E0303.md | 4 +++- src/librustc_error_codes/error_codes/E0364.md | 6 +++--- src/librustc_error_codes/error_codes/E0365.md | 6 +++--- src/librustc_error_codes/error_codes/E0382.md | 6 +++--- src/librustc_error_codes/error_codes/E0387.md | 4 ++-- src/librustc_error_codes/error_codes/E0455.md | 6 ++++-- src/librustc_error_codes/error_codes/E0499.md | 10 ++++++---- src/librustc_error_codes/error_codes/E0501.md | 7 ++++--- src/librustc_error_codes/error_codes/E0502.md | 6 ++++-- src/librustc_error_codes/error_codes/E0503.md | 6 ++++-- src/librustc_error_codes/error_codes/E0505.md | 6 ++++-- src/librustc_error_codes/error_codes/E0507.md | 6 ++++-- src/librustc_error_codes/error_codes/E0525.md | 6 ++++-- src/librustc_error_codes/error_codes/E0534.md | 6 ++++-- src/librustc_error_codes/error_codes/E0535.md | 6 ++++-- src/librustc_error_codes/error_codes/E0536.md | 6 ++++-- src/librustc_error_codes/error_codes/E0537.md | 6 ++++-- src/librustc_error_codes/error_codes/E0601.md | 6 ++++-- src/librustc_error_codes/error_codes/E0610.md | 7 ++++--- src/librustc_error_codes/error_codes/E0660.md | 7 ++++--- src/librustc_error_codes/error_codes/E0661.md | 7 ++++--- src/librustc_error_codes/error_codes/E0662.md | 7 ++++--- src/librustc_error_codes/error_codes/E0663.md | 7 ++++--- src/librustc_error_codes/error_codes/E0664.md | 7 ++++--- src/test/ui/json-short.stderr | 6 ++++-- 29 files changed, 113 insertions(+), 71 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0080.md b/src/librustc_error_codes/error_codes/E0080.md index 273238a943b..7b1bbde6140 100644 --- a/src/librustc_error_codes/error_codes/E0080.md +++ b/src/librustc_error_codes/error_codes/E0080.md @@ -14,7 +14,10 @@ constant expression that had to be evaluated. Attempting to divide by 0 or causing an integer overflow are two ways to induce this error. Ensure that the expressions given can be evaluated as the desired integer type. -See the FFI section of the Reference for more information about using a custom -integer type: -https://doc.rust-lang.org/reference.html#ffi-attributes +See the [Custom Discriminants][custom-discriminants] section of the Reference +for more information about setting custom integer types on fieldless enums +using the [`repr` attribute][repr-attribute]. + +[custom-discriminants]: https://doc.rust-lang.org/reference/items/enumerations.html#custom-discriminant-values-for-field-less-enumerations +[repr-attribute]: https://doc.rust-lang.org/reference/type-layout.html#reprc-enums diff --git a/src/librustc_error_codes/error_codes/E0133.md b/src/librustc_error_codes/error_codes/E0133.md index 0488cdd808d..1adbcc31356 100644 --- a/src/librustc_error_codes/error_codes/E0133.md +++ b/src/librustc_error_codes/error_codes/E0133.md @@ -28,4 +28,6 @@ fn main() { } ``` -See also https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html +See the [unsafe section][unsafe-section] of the Book for more details. + +[unsafe-section]: https://doc.rust-lang.org/book/ch19-01-unsafe-rust.html diff --git a/src/librustc_error_codes/error_codes/E0154.md b/src/librustc_error_codes/error_codes/E0154.md index 725a775e72c..e437a71897c 100644 --- a/src/librustc_error_codes/error_codes/E0154.md +++ b/src/librustc_error_codes/error_codes/E0154.md @@ -27,7 +27,8 @@ fn f() { } ``` -See the Declaration Statements section of the reference for more information -about what constitutes an Item declaration and what does not: +See the [Declaration Statements][declaration-statements] section of the +reference for more information about what constitutes an item declaration +and what does not. -https://doc.rust-lang.org/reference.html#statements +[declaration-statements]: https://doc.rust-lang.org/reference/statements.html#declaration-statements diff --git a/src/librustc_error_codes/error_codes/E0260.md b/src/librustc_error_codes/error_codes/E0260.md index 4a36735ae76..b8bdb81fcbf 100644 --- a/src/librustc_error_codes/error_codes/E0260.md +++ b/src/librustc_error_codes/error_codes/E0260.md @@ -28,7 +28,8 @@ extern crate core as xyz; struct abc; ``` -See the Declaration Statements section of the reference for more information -about what constitutes an Item declaration and what does not: +See the [Declaration Statements][declaration-statements] section of the +reference for more information about what constitutes an item declaration +and what does not. -https://doc.rust-lang.org/reference.html#statements +[declaration-statements]: https://doc.rust-lang.org/reference/statements.html#declaration-statements diff --git a/src/librustc_error_codes/error_codes/E0303.md b/src/librustc_error_codes/error_codes/E0303.md index 700a66438e0..459906047cc 100644 --- a/src/librustc_error_codes/error_codes/E0303.md +++ b/src/librustc_error_codes/error_codes/E0303.md @@ -33,4 +33,6 @@ match Some("hi".to_string()) { The `op_string_ref` binding has type `&Option<&String>` in both cases. -See also https://github.com/rust-lang/rust/issues/14587 +See also [Issue 14587][issue-14587]. + +[issue-14587]: https://github.com/rust-lang/rust/issues/14587 diff --git a/src/librustc_error_codes/error_codes/E0364.md b/src/librustc_error_codes/error_codes/E0364.md index 0cca8f58b17..ec1fb911f3c 100644 --- a/src/librustc_error_codes/error_codes/E0364.md +++ b/src/librustc_error_codes/error_codes/E0364.md @@ -26,7 +26,7 @@ pub use foo::X; fn main() {} ``` -See the 'Use Declarations' section of the reference for more information on -this topic: +See the [Use Declarations][use-declarations] section of the reference for +more information on this topic. -https://doc.rust-lang.org/reference.html#use-declarations +[use-declarations]: https://doc.rust-lang.org/reference/items/use-declarations.html diff --git a/src/librustc_error_codes/error_codes/E0365.md b/src/librustc_error_codes/error_codes/E0365.md index 8f90d949e30..e3d417a7d01 100644 --- a/src/librustc_error_codes/error_codes/E0365.md +++ b/src/librustc_error_codes/error_codes/E0365.md @@ -26,7 +26,7 @@ pub use foo as foo2; fn main() {} ``` -See the 'Use Declarations' section of the reference for more information -on this topic: +See the [Use Declarations][use-declarations] section of the reference for +more information on this topic. -https://doc.rust-lang.org/reference.html#use-declarations +[use-declarations]: https://doc.rust-lang.org/reference/items/use-declarations.html diff --git a/src/librustc_error_codes/error_codes/E0382.md b/src/librustc_error_codes/error_codes/E0382.md index 1592eac2ec5..f2356583cce 100644 --- a/src/librustc_error_codes/error_codes/E0382.md +++ b/src/librustc_error_codes/error_codes/E0382.md @@ -104,7 +104,7 @@ With this approach, x and y share ownership of the data via the `Rc` (reference count type). `RefCell` essentially performs runtime borrow checking: ensuring that at most one writer or multiple readers can access the data at any one time. -If you wish to learn more about ownership in Rust, start with the chapter in the -Book: +If you wish to learn more about ownership in Rust, start with the +[Understanding Ownership][understanding-ownership] chapter in the Book. -https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html +[understanding-ownership]: https://doc.rust-lang.org/book/ch04-00-understanding-ownership.html diff --git a/src/librustc_error_codes/error_codes/E0387.md b/src/librustc_error_codes/error_codes/E0387.md index 3a5facfdd25..38ad19bd6aa 100644 --- a/src/librustc_error_codes/error_codes/E0387.md +++ b/src/librustc_error_codes/error_codes/E0387.md @@ -52,6 +52,6 @@ fn mutable() { } ``` -You can read more about cell types in the API documentation: +You can read more in the API documentation for [Cell][std-cell]. -https://doc.rust-lang.org/std/cell/ +[std-cell]: https://doc.rust-lang.org/std/cell/ diff --git a/src/librustc_error_codes/error_codes/E0455.md b/src/librustc_error_codes/error_codes/E0455.md index a642528dee2..2f80c34b889 100644 --- a/src/librustc_error_codes/error_codes/E0455.md +++ b/src/librustc_error_codes/error_codes/E0455.md @@ -15,5 +15,7 @@ To solve this error you can use conditional compilation: extern {} ``` -See more: -https://doc.rust-lang.org/reference/attributes.html#conditional-compilation +Learn more in the [Conditional Compilation][conditional-compilation] section +of the Reference. + +[conditional-compilation]: https://doc.rust-lang.org/reference/attributes.html#conditional-compilation diff --git a/src/librustc_error_codes/error_codes/E0499.md b/src/librustc_error_codes/error_codes/E0499.md index 370ceef530b..a07e8eb3b38 100644 --- a/src/librustc_error_codes/error_codes/E0499.md +++ b/src/librustc_error_codes/error_codes/E0499.md @@ -10,11 +10,13 @@ x; // error: cannot borrow `i` as mutable more than once at a time ``` -Please note that in rust, you can either have many immutable references, or one -mutable reference. Take a look at -https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html for more -information. Example: +Please note that in Rust, you can either have many immutable references, or one +mutable reference. For more details you may want to read the +[References & Borrowing][references-and-borrowing] section of the Book. +[references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html + +Example: ``` let mut i = 0; diff --git a/src/librustc_error_codes/error_codes/E0501.md b/src/librustc_error_codes/error_codes/E0501.md index 95e0dfd4001..f5aa17a8094 100644 --- a/src/librustc_error_codes/error_codes/E0501.md +++ b/src/librustc_error_codes/error_codes/E0501.md @@ -3,9 +3,10 @@ captured by a closure. Because the closure has borrowed the variable, it is not available for use until the closure goes out of scope. Note that a capture will either move or borrow a variable, but in this -situation, the closure is borrowing the variable. Take a look at -http://rustbyexample.com/fn/closures/capture.html for more information about -capturing. +situation, the closure is borrowing the variable. Take a look at the chapter +on [Capturing][capturing] in Rust By Example for more information. + +[capturing]: https://doc.rust-lang.org/stable/rust-by-example/fn/closures/capture.html Erroneous code example: diff --git a/src/librustc_error_codes/error_codes/E0502.md b/src/librustc_error_codes/error_codes/E0502.md index 69220259e3d..f15c05d558d 100644 --- a/src/librustc_error_codes/error_codes/E0502.md +++ b/src/librustc_error_codes/error_codes/E0502.md @@ -25,5 +25,7 @@ fn foo(a: &mut i32) { } ``` -For more information on the rust ownership system, take a look at -https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html. +For more information on Rust's ownership system, take a look at the +[References & Borrowing][references-and-borrowing] section of the Book. + +[references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0503.md b/src/librustc_error_codes/error_codes/E0503.md index c683619e3d0..c52525fee54 100644 --- a/src/librustc_error_codes/error_codes/E0503.md +++ b/src/librustc_error_codes/error_codes/E0503.md @@ -48,5 +48,7 @@ fn main() { } ``` -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html +For more information on Rust's ownership system, take a look at the +[References & Borrowing][references-and-borrowing] section of the Book. + +[references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0505.md b/src/librustc_error_codes/error_codes/E0505.md index 14baa01cb50..b11e3c0e947 100644 --- a/src/librustc_error_codes/error_codes/E0505.md +++ b/src/librustc_error_codes/error_codes/E0505.md @@ -81,5 +81,7 @@ fn main() { } ``` -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html +For more information on Rust's ownership system, take a look at the +[References & Borrowing][references-and-borrowing] section of the Book. + +[references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0507.md b/src/librustc_error_codes/error_codes/E0507.md index 89a6fb47377..1e3457e96c5 100644 --- a/src/librustc_error_codes/error_codes/E0507.md +++ b/src/librustc_error_codes/error_codes/E0507.md @@ -127,5 +127,7 @@ let borrowed = &mut cave; mem::replace(&mut borrowed.knight, TheDarkKnight).nothing_is_true(); // ok! ``` -You can find more information about borrowing in the rust-book: -http://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html +For more information on Rust's ownership system, take a look at the +[References & Borrowing][references-and-borrowing] section of the Book. + +[references-and-borrowing]: https://doc.rust-lang.org/book/ch04-02-references-and-borrowing.html diff --git a/src/librustc_error_codes/error_codes/E0525.md b/src/librustc_error_codes/error_codes/E0525.md index 95e5f362bde..a769440ca1b 100644 --- a/src/librustc_error_codes/error_codes/E0525.md +++ b/src/librustc_error_codes/error_codes/E0525.md @@ -36,5 +36,7 @@ fn main() { } ``` -To understand better how closures work in Rust, read: -https://doc.rust-lang.org/book/ch13-01-closures.html +To better understand how these work in Rust, read the [Closures][closures] +chapter of the Book. + +[closures]: https://doc.rust-lang.org/book/ch13-01-closures.html diff --git a/src/librustc_error_codes/error_codes/E0534.md b/src/librustc_error_codes/error_codes/E0534.md index 0afa4a8c958..1ca9411b8d4 100644 --- a/src/librustc_error_codes/error_codes/E0534.md +++ b/src/librustc_error_codes/error_codes/E0534.md @@ -31,5 +31,7 @@ compiler about inlining opportunity: fn something() {} ``` -For more information about the inline attribute, read: -https://doc.rust-lang.org/reference.html#inline-attributes +For more information see the [`inline` attribute][inline-attribute] section +of the Reference. + +[inline-attribute]: https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute diff --git a/src/librustc_error_codes/error_codes/E0535.md b/src/librustc_error_codes/error_codes/E0535.md index 035d395b76f..0cf3118b02c 100644 --- a/src/librustc_error_codes/error_codes/E0535.md +++ b/src/librustc_error_codes/error_codes/E0535.md @@ -24,5 +24,7 @@ pub fn something() {} fn main() {} ``` -For more information about the inline attribute, https: -read://doc.rust-lang.org/reference.html#inline-attributes +For more information see the [`inline` Attribute][inline-attribute] section +of the Reference. + +[inline-attribute]: https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute diff --git a/src/librustc_error_codes/error_codes/E0536.md b/src/librustc_error_codes/error_codes/E0536.md index 9006906a703..c081a3d9cfa 100644 --- a/src/librustc_error_codes/error_codes/E0536.md +++ b/src/librustc_error_codes/error_codes/E0536.md @@ -18,5 +18,7 @@ pub fn something() {} pub fn main() {} ``` -For more information about the cfg attribute, read: -https://doc.rust-lang.org/reference.html#conditional-compilation +For more information about the `cfg` attribute, read the section on +[Conditional Compilation][conditional-compilation] in the Reference. + +[conditional-compilation]: https://doc.rust-lang.org/reference/conditional-compilation.html diff --git a/src/librustc_error_codes/error_codes/E0537.md b/src/librustc_error_codes/error_codes/E0537.md index 82d8c6188af..123efd4f57d 100644 --- a/src/librustc_error_codes/error_codes/E0537.md +++ b/src/librustc_error_codes/error_codes/E0537.md @@ -24,5 +24,7 @@ pub fn something() {} pub fn main() {} ``` -For more information about the cfg attribute, read: -https://doc.rust-lang.org/reference.html#conditional-compilation +For more information about the `cfg` attribute, read the section on +[Conditional Compilation][conditional-compilation] in the Reference. + +[conditional-compilation]: https://doc.rust-lang.org/reference/conditional-compilation.html diff --git a/src/librustc_error_codes/error_codes/E0601.md b/src/librustc_error_codes/error_codes/E0601.md index 12ae767c9e6..8180c5db46f 100644 --- a/src/librustc_error_codes/error_codes/E0601.md +++ b/src/librustc_error_codes/error_codes/E0601.md @@ -8,5 +8,7 @@ fn main() { } ``` -If you don't know the basics of Rust, you can go look to the Rust Book to get -started: https://doc.rust-lang.org/book/ +If you don't know the basics of Rust, you can look at the +[Rust Book][rust-book] to get started. + +[rust-book]: https://doc.rust-lang.org/book/ diff --git a/src/librustc_error_codes/error_codes/E0610.md b/src/librustc_error_codes/error_codes/E0610.md index d590ce51a33..c737bd618c3 100644 --- a/src/librustc_error_codes/error_codes/E0610.md +++ b/src/librustc_error_codes/error_codes/E0610.md @@ -24,6 +24,7 @@ let variable = Foo { x: 0, y: -12 }; println!("x: {}, y: {}", variable.x, variable.y); ``` -For more information about primitives and structs, take a look at The Book: -https://doc.rust-lang.org/book/ch03-02-data-types.html -https://doc.rust-lang.org/book/ch05-00-structs.html +For more information about [primitives] and [structs], take a look at the Book. + +[primitives]: https://doc.rust-lang.org/book/ch03-02-data-types.html +[structs]: https://doc.rust-lang.org/book/ch05-00-structs.html diff --git a/src/librustc_error_codes/error_codes/E0660.md b/src/librustc_error_codes/error_codes/E0660.md index bceab1e0055..189459175dc 100644 --- a/src/librustc_error_codes/error_codes/E0660.md +++ b/src/librustc_error_codes/error_codes/E0660.md @@ -6,6 +6,7 @@ Erroneous code example: asm!("nop" "nop"); ``` -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html +Considering that this would be a long explanation, we instead recommend you +take a look at the [`asm`] chapter of the Unstable book: + +[asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0661.md b/src/librustc_error_codes/error_codes/E0661.md index 9979a61ee95..b171ada6205 100644 --- a/src/librustc_error_codes/error_codes/E0661.md +++ b/src/librustc_error_codes/error_codes/E0661.md @@ -7,6 +7,7 @@ let a; asm!("nop" : "r"(a)); ``` -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html +Considering that this would be a long explanation, we instead recommend you +take a look at the [`asm`] chapter of the Unstable book: + +[asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0662.md b/src/librustc_error_codes/error_codes/E0662.md index 3ba00eaab54..c15e736610b 100644 --- a/src/librustc_error_codes/error_codes/E0662.md +++ b/src/librustc_error_codes/error_codes/E0662.md @@ -9,6 +9,7 @@ asm!("xor %eax, %eax" ); ``` -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html +Considering that this would be a long explanation, we instead recommend you +take a look at the [`asm`] chapter of the Unstable book: + +[asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0663.md b/src/librustc_error_codes/error_codes/E0663.md index be121aa0b72..bd450230ec3 100644 --- a/src/librustc_error_codes/error_codes/E0663.md +++ b/src/librustc_error_codes/error_codes/E0663.md @@ -9,6 +9,7 @@ asm!("xor %eax, %eax" ); ``` -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html +Considering that this would be a long explanation, we instead recommend you +take a look at the [`asm`] chapter of the Unstable book: + +[asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/asm.html diff --git a/src/librustc_error_codes/error_codes/E0664.md b/src/librustc_error_codes/error_codes/E0664.md index 2b9546453d1..768ffdf2de9 100644 --- a/src/librustc_error_codes/error_codes/E0664.md +++ b/src/librustc_error_codes/error_codes/E0664.md @@ -10,6 +10,7 @@ asm!("mov $$0x200, %eax" ); ``` -Considering that this would be a long explanation, we instead recommend you to -take a look at the unstable book: -https://doc.rust-lang.org/unstable-book/language-features/asm.html +Considering that this would be a long explanation, we instead recommend you +take a look at the [`asm`] chapter of the Unstable book: + +[asm]: https://doc.rust-lang.org/stable/unstable-book/library-features/asm.html diff --git a/src/test/ui/json-short.stderr b/src/test/ui/json-short.stderr index 226343b1b8c..60c2582b11e 100644 --- a/src/test/ui/json-short.stderr +++ b/src/test/ui/json-short.stderr @@ -8,8 +8,10 @@ fn main() { } ``` -If you don't know the basics of Rust, you can go look to the Rust Book to get -started: https://doc.rust-lang.org/book/ +If you don't know the basics of Rust, you can look at the +[Rust Book][rust-book] to get started. + +[rust-book]: https://doc.rust-lang.org/book/ "},"level":"error","spans":[{"file_name":"$DIR/json-short.rs","byte_start":62,"byte_end":62,"line_start":1,"line_end":1,"column_start":63,"column_end":63,"is_primary":true,"text":[{"text":"// compile-flags: --json=diagnostic-short --error-format=json","highlight_start":63,"highlight_end":63}],"label":"consider adding a `main` function to `$DIR/json-short.rs`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-short.rs:1:63: error[E0601]: `main` function not found in crate `json_short` "} {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error From 598b187e2738b5b551f84be30cc15503896fe4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sun, 23 Feb 2020 00:00:00 +0000 Subject: [PATCH 0458/1250] bootstrap: Remove commit hash from LLVM version suffix to avoid rebuilds The custom LLVM version suffix was introduced to avoid unintentional library names conflicts. By default it included the LLVM submodule commit hash. Changing the version suffix requires the complete LLVM rebuild, and since then every change to the submodules required it as well. Remove the commit hash from version suffix to avoid complete rebuilds, while leaving the `rust` string, the release number and release channel to disambiguate the library name. --- src/bootstrap/native.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index 21dcb1d8aa0..c22c2a336f1 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -241,12 +241,8 @@ impl Step for Llvm { cfg.define("LLVM_VERSION_SUFFIX", suffix); } } else { - let mut default_suffix = - format!("-rust-{}-{}", channel::CFG_RELEASE_NUM, builder.config.channel,); - if let Some(sha) = llvm_info.sha_short() { - default_suffix.push_str("-"); - default_suffix.push_str(sha); - } + let default_suffix = + format!("-rust-{}-{}", channel::CFG_RELEASE_NUM, builder.config.channel); cfg.define("LLVM_VERSION_SUFFIX", default_suffix); } From e355a330772a7b605649651f7e670ea636e73a6e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 23 Feb 2020 01:29:36 +0300 Subject: [PATCH 0459/1250] Deduplicate identifier printing a bit --- src/librustc_ast_pretty/pprust.rs | 42 ++----------------- src/librustc_hir/print.rs | 6 +-- src/librustc_span/symbol.rs | 67 +++++++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 49 deletions(-) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 27cef8502a1..4e69253c34b 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -3,7 +3,7 @@ use crate::pp::{self, Breaks}; use rustc_span::edition::Edition; use rustc_span::source_map::{SourceMap, Spanned}; -use rustc_span::symbol::{kw, sym}; +use rustc_span::symbol::{kw, sym, IdentPrinter}; use rustc_span::{BytePos, FileName, Span}; use syntax::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax}; use syntax::ast::{Attribute, GenericArg, MacArgs}; @@ -196,40 +196,6 @@ pub fn literal_to_string(lit: token::Lit) -> String { out } -/// Print an ident from AST, `$crate` is converted into its respective crate name. -pub fn ast_ident_to_string(ident: ast::Ident, is_raw: bool) -> String { - ident_to_string(ident.name, is_raw, Some(ident.span)) -} - -// AST pretty-printer is used as a fallback for turning AST structures into token streams for -// proc macros. Additionally, proc macros may stringify their input and expect it survive the -// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30). -// So we need to somehow pretty-print `$crate` in a way preserving at least some of its -// hygiene data, most importantly name of the crate it refers to. -// As a result we print `$crate` as `crate` if it refers to the local crate -// and as `::other_crate_name` if it refers to some other crate. -// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing, -// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents, -// so we should not perform this lossy conversion if the top level call to the pretty-printer was -// done for a token stream or a single token. -fn ident_to_string(name: ast::Name, is_raw: bool, convert_dollar_crate: Option) -> String { - if is_raw { - format!("r#{}", name) - } else { - if name == kw::DollarCrate { - if let Some(span) = convert_dollar_crate { - let converted = span.ctxt().dollar_crate_name(); - return if converted.is_path_segment_keyword() { - converted.to_string() - } else { - format!("::{}", converted) - }; - } - } - name.to_string() - } -} - /// Print the token kind precisely, without converting `$crate` into its respective crate name. pub fn token_kind_to_string(tok: &TokenKind) -> String { token_kind_to_string_ext(tok, None) @@ -280,7 +246,7 @@ fn token_kind_to_string_ext(tok: &TokenKind, convert_dollar_crate: Option) token::Literal(lit) => literal_to_string(lit), /* Name components */ - token::Ident(s, is_raw) => ident_to_string(s, is_raw, convert_dollar_crate), + token::Ident(s, is_raw) => IdentPrinter::new(s, is_raw, convert_dollar_crate).to_string(), token::Lifetime(s) => s.to_string(), /* Other */ @@ -315,7 +281,7 @@ pub fn nonterminal_to_string(nt: &Nonterminal) -> String { token::NtBlock(ref e) => block_to_string(e), token::NtStmt(ref e) => stmt_to_string(e), token::NtPat(ref e) => pat_to_string(e), - token::NtIdent(e, is_raw) => ast_ident_to_string(e, is_raw), + token::NtIdent(e, is_raw) => IdentPrinter::for_ast_ident(e, is_raw).to_string(), token::NtLifetime(e) => e.to_string(), token::NtLiteral(ref e) => expr_to_string(e), token::NtTT(ref tree) => tt_to_string(tree.clone()), @@ -819,7 +785,7 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: ast::Ident) { - self.s.word(ast_ident_to_string(ident, ident.is_raw_guess())); + self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Ident(&ident)) } diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index e49f99fb717..92bd8b1ba5f 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -1,8 +1,8 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, Breaks}; -use rustc_ast_pretty::pprust::{self, Comments, PrintState}; +use rustc_ast_pretty::pprust::{Comments, PrintState}; use rustc_span::source_map::{SourceMap, Spanned}; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, IdentPrinter}; use rustc_span::{self, BytePos, FileName}; use rustc_target::spec::abi::Abi; use syntax::ast; @@ -126,7 +126,7 @@ impl<'a> PrintState<'a> for State<'a> { } fn print_ident(&mut self, ident: ast::Ident) { - self.s.word(pprust::ast_ident_to_string(ident, ident.is_raw_guess())); + self.s.word(IdentPrinter::for_ast_ident(ident, ident.is_raw_guess()).to_string()); self.ann.post(self, AnnNode::Name(&ident.name)) } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 97708d91d7e..b8e5ea97f4e 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -893,19 +893,17 @@ impl Hash for Ident { impl fmt::Debug for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.is_raw_guess() { - write!(f, "r#")?; - } - write!(f, "{}{:?}", self.name, self.span.ctxt()) + fmt::Display::fmt(self, f)?; + fmt::Debug::fmt(&self.span.ctxt(), f) } } +/// This implementation is supposed to be used in error messages, so it's expected to be identical +/// to printing the original identifier token written in source code (`token_to_string`), +/// except that AST identifiers don't keep the rawness flag, so we have to guess it. impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.is_raw_guess() { - write!(f, "r#")?; - } - fmt::Display::fmt(&self.name, f) + fmt::Display::fmt(&IdentPrinter::new(self.name, self.is_raw_guess(), None), f) } } @@ -929,6 +927,59 @@ impl UseSpecializedDecodable for Ident { } } +/// This is the most general way to print identifiers. +/// AST pretty-printer is used as a fallback for turning AST structures into token streams for +/// proc macros. Additionally, proc macros may stringify their input and expect it survive the +/// stringification (especially true for proc macro derives written between Rust 1.15 and 1.30). +/// So we need to somehow pretty-print `$crate` in a way preserving at least some of its +/// hygiene data, most importantly name of the crate it refers to. +/// As a result we print `$crate` as `crate` if it refers to the local crate +/// and as `::other_crate_name` if it refers to some other crate. +/// Note, that this is only done if the ident token is printed from inside of AST pretty-pringing, +/// but not otherwise. Pretty-printing is the only way for proc macros to discover token contents, +/// so we should not perform this lossy conversion if the top level call to the pretty-printer was +/// done for a token stream or a single token. +pub struct IdentPrinter { + symbol: Symbol, + is_raw: bool, + /// Span used for retrieving the crate name to which `$crate` refers to, + /// if this field is `None` then the `$crate` conversion doesn't happen. + convert_dollar_crate: Option, +} + +impl IdentPrinter { + /// The most general `IdentPrinter` constructor. Do not use this. + pub fn new(symbol: Symbol, is_raw: bool, convert_dollar_crate: Option) -> IdentPrinter { + IdentPrinter { symbol, is_raw, convert_dollar_crate } + } + + /// This implementation is supposed to be used when printing identifiers + /// as a part of pretty-printing for larger AST pieces. + /// Do not use this either. + pub fn for_ast_ident(ident: Ident, is_raw: bool) -> IdentPrinter { + IdentPrinter::new(ident.name, is_raw, Some(ident.span)) + } +} + +impl fmt::Display for IdentPrinter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + if self.is_raw { + f.write_str("r#")?; + } else { + if self.symbol == kw::DollarCrate { + if let Some(span) = self.convert_dollar_crate { + let converted = span.ctxt().dollar_crate_name(); + if !converted.is_path_segment_keyword() { + f.write_str("::")?; + } + return fmt::Display::fmt(&converted, f); + } + } + } + fmt::Display::fmt(&self.symbol, f) + } +} + /// An interned string. /// /// Internally, a `Symbol` is implemented as an index, and all operations From 5da393970df87f13881fd1f8cebd9b2a42659759 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 17:04:34 +0100 Subject: [PATCH 0460/1250] miri/machine: add canonical_alloc_id hook to replace find_foreign_static --- src/librustc_mir/const_eval/machine.rs | 10 +---- src/librustc_mir/interpret/machine.rs | 44 +++++++++++-------- src/librustc_mir/interpret/memory.rs | 56 +++++++++++++----------- src/librustc_mir/transform/const_prop.rs | 12 ----- 4 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index e40436ccf0b..25727b75faf 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -1,7 +1,6 @@ use rustc::mir; use rustc::ty::layout::HasTyCtxt; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc::ty::{self, Ty}; use std::borrow::{Borrow, Cow}; use std::collections::hash_map::Entry; use std::hash::Hash; @@ -320,13 +319,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } - fn find_foreign_static( - _tcx: TyCtxt<'tcx>, - _def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { - throw_unsup!(ReadForeignStatic) - } - #[inline(always)] fn init_allocation_extra<'b>( _memory_extra: &MemoryExtra, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 5291000d10b..98a305ec2d9 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -6,8 +6,7 @@ use std::borrow::{Borrow, Cow}; use std::hash::Hash; use rustc::mir; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc::ty::{self, Ty}; use rustc_span::Span; use super::{ @@ -123,10 +122,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; - /// Called before a basic block terminator is executed. - /// You can use this to detect endlessly running programs. - fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>; - /// Entry point to all function calls. /// /// Returns either the mir to use for the call, or `None` if execution should @@ -175,18 +170,6 @@ pub trait Machine<'mir, 'tcx>: Sized { unwind: Option, ) -> InterpResult<'tcx>; - /// Called for read access to a foreign static item. - /// - /// This will only be called once per static and machine; the result is cached in - /// the machine memory. (This relies on `AllocMap::get_or` being able to add the - /// owned allocation to the map even when the map is shared.) - /// - /// This allocation will then be fed to `tag_allocation` to initialize the "extra" state. - fn find_foreign_static( - tcx: TyCtxt<'tcx>, - def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>>; - /// Called for all binary operations where the LHS has pointer type. /// /// Returns a (value, overflowed) pair if the operation succeeded @@ -204,6 +187,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ) -> InterpResult<'tcx>; /// Called to read the specified `local` from the `frame`. + #[inline] fn access_local( _ecx: &InterpCx<'mir, 'tcx, Self>, frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, @@ -212,7 +196,15 @@ pub trait Machine<'mir, 'tcx>: Sized { frame.locals[local].access() } + /// Called before a basic block terminator is executed. + /// You can use this to detect endlessly running programs. + #[inline] + fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + Ok(()) + } + /// Called before a `Static` value is accessed. + #[inline] fn before_access_static( _memory_extra: &Self::MemoryExtra, _allocation: &Allocation, @@ -220,6 +212,20 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } + /// Called for *every* memory access to determine the real ID of the given allocation. + /// This provides a way for the machine to "redirect" certain allocations as it sees fit. + /// + /// This is used by Miri to redirect extern statics to real allocations. + /// + /// This function must be idempotent. + #[inline] + fn canonical_alloc_id( + _mem: &Memory<'mir, 'tcx, Self>, + id: AllocId, + ) -> AllocId { + id + } + /// Called to initialize the "extra" state of an allocation and make the pointers /// it contains (in relocations) tagged. The way we construct allocations is /// to always first construct it without extra and then add the extra. @@ -259,7 +265,7 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } - /// Called immediately before a new stack frame got pushed + /// Called immediately before a new stack frame got pushed. fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>; /// Called immediately after a stack frame gets popped diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 1df389d9c8b..048c5d7b159 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -421,6 +421,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static /// contains a reference to memory that was created during its evaluation (i.e., not to /// another static), those inner references only exist in "resolved" form. + /// + /// Assumes `id` is already canonical. fn get_static_alloc( memory_extra: &M::MemoryExtra, tcx: TyCtxtAt<'tcx>, @@ -434,31 +436,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Static(def_id)) => { // We got a "lazy" static that has not been computed yet. if tcx.is_foreign_item(def_id) { - trace!("static_alloc: foreign item {:?}", def_id); - M::find_foreign_static(tcx.tcx, def_id)? - } else { - trace!("static_alloc: Need to compute {:?}", def_id); - let instance = Instance::mono(tcx.tcx, def_id); - let gid = GlobalId { instance, promoted: None }; - // use the raw query here to break validation cycles. Later uses of the static - // will call the full query anyway - let raw_const = - tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { - // no need to report anything, the const_eval call takes care of that - // for statics - assert!(tcx.is_static(def_id)); - match err { - ErrorHandled::Reported => err_inval!(ReferencedConstant), - ErrorHandled::TooGeneric => err_inval!(TooGeneric), - } - })?; - // Make sure we use the ID of the resolved memory, not the lazy one! - let id = raw_const.alloc_id; - let allocation = tcx.alloc_map.lock().unwrap_memory(id); - - M::before_access_static(memory_extra, allocation)?; - Cow::Borrowed(allocation) + trace!("get_static_alloc: foreign item {:?}", def_id); + throw_unsup!(ReadForeignStatic) } + trace!("get_static_alloc: Need to compute {:?}", def_id); + let instance = Instance::mono(tcx.tcx, def_id); + let gid = GlobalId { instance, promoted: None }; + // use the raw query here to break validation cycles. Later uses of the static + // will call the full query anyway + let raw_const = + tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { + // no need to report anything, the const_eval call takes care of that + // for statics + assert!(tcx.is_static(def_id)); + match err { + ErrorHandled::Reported => err_inval!(ReferencedConstant), + ErrorHandled::TooGeneric => err_inval!(TooGeneric), + } + })?; + // Make sure we use the ID of the resolved memory, not the lazy one! + let id = raw_const.alloc_id; + let allocation = tcx.alloc_map.lock().unwrap_memory(id); + + M::before_access_static(memory_extra, allocation)?; + Cow::Borrowed(allocation) } }; // We got tcx memory. Let the machine initialize its "extra" stuff. @@ -478,6 +479,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation> { + let id = M::canonical_alloc_id(self, id); // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from // `get_static_alloc` that we can actually use directly without inserting anything anywhere. @@ -513,6 +515,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &mut self, id: AllocId, ) -> InterpResult<'tcx, &mut Allocation> { + let id = M::canonical_alloc_id(self, id); let tcx = self.tcx; let memory_extra = &self.extra; let a = self.alloc_map.get_mut_or(id, || { @@ -550,6 +553,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { id: AllocId, liveness: AllocCheck, ) -> InterpResult<'static, (Size, Align)> { + let id = M::canonical_alloc_id(self, id); // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static @@ -602,6 +606,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } + /// Assumes `id` is already canonical. fn get_fn_alloc(&self, id: AllocId) -> Option> { trace!("reading fn ptr: {}", id); if let Some(extra) = self.extra_fn_ptr_map.get(&id) { @@ -622,7 +627,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if ptr.offset.bytes() != 0 { throw_unsup!(InvalidFunctionPointer) } - self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) + let id = M::canonical_alloc_id(self, ptr.alloc_id); + self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9e05133132e..ccfe765f2bb 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -22,7 +22,6 @@ use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_infer::traits; @@ -222,13 +221,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { )); } - fn find_foreign_static( - _tcx: TyCtxt<'tcx>, - _def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { - throw_unsup!(ReadForeignStatic) - } - #[inline(always)] fn init_allocation_extra<'b>( _memory_extra: &(), @@ -279,10 +271,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { Ok(()) } - fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { - Ok(()) - } - #[inline(always)] fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { Ok(()) From e7a344fb745a0a663e21be947b2619df05df6d31 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Sun, 23 Feb 2020 18:04:48 +0100 Subject: [PATCH 0461/1250] Update RELEASES.md Co-Authored-By: Jonas Schievink Co-Authored-By: Mazdak Farrokhzad --- RELEASES.md | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 5d10e658f90..2a2bcfb0ea2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3,9 +3,6 @@ Version 1.42.0 (2020-03-12) Language -------- -- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning - that you can create an enum that has the exact layout and ABI of the type - it contains. - [You can now use the slice pattern syntax with subslices.][67712] e.g. ```rust fn foo(words: &[&str]) { @@ -16,18 +13,34 @@ Language } } ``` - -- [Merge `TraitItem` & `ImplItem into `AssocItem`][67131] +- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning + that you can create an enum that has the exact layout and ABI of the type + it contains. +- [There are some *syntax-only* changes:][67131] + - `default` is syntactically allowed before items in `trait` definitions. + - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically + leave out their bodies in favor of `;`. + - Bounds on associated types in `impl`s are now syntactically allowed + (e.g. `type Foo: Ord;`). + - `...` (the C-variadic type) may occur syntactically directly as the type of + any function parameter. + + These are still rejected *semantically*, so you will likely receive an error + but these changes can be seen and parsed by procedural macros and + conditional compilation. Compiler -------- -- [Added tier 3\* support for `armv7a-none-eabi`.][68253] -- [Added tier 3 support for `riscv64gc-unknown-linux-gnu`.][68037] +- [Added tier 2\* support for `armv7a-none-eabi`.][68253] +- [Added tier 2 support for `riscv64gc-unknown-linux-gnu`.][68339] - [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages pointing to the location where they were called, rather than `core`'s internals. ][67887] +\* Refer to Rust's [platform support page][forge-platform-support] for more +information on Rust's tiered platform support. + Libraries --------- - [`iter::Empty` now implements `Send` and `Sync` for any `T`.][68348] @@ -40,14 +53,14 @@ Libraries Stabilized APIs --------------- +- [`CondVar::wait_while`] +- [`CondVar::wait_timeout_while`] - [`DebugMap::key`] - [`DebugMap::value`] - [`ManuallyDrop::take`] - [`matches!`] - [`ptr::slice_from_raw_parts_mut`] - [`ptr::slice_from_raw_parts`] -- [`wait_timeout_while`] -- [`wait_while`] Cargo ----- @@ -62,7 +75,7 @@ Compatibility Notes [68253]: https://github.com/rust-lang/rust/pull/68253/ [68348]: https://github.com/rust-lang/rust/pull/68348/ [67935]: https://github.com/rust-lang/rust/pull/67935/ -[68037]: https://github.com/rust-lang/rust/pull/68037/ +[68339]: https://github.com/rust-lang/rust/pull/68339/ [68122]: https://github.com/rust-lang/rust/pull/68122/ [67712]: https://github.com/rust-lang/rust/pull/67712/ [67887]: https://github.com/rust-lang/rust/pull/67887/ @@ -78,7 +91,8 @@ Compatibility Notes [`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html [`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html [`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html -[`wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while +[`CondVar::wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while +[`CondVar::wait_timeout_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_timeout_while Version 1.41.0 (2020-01-30) From 79b8ad84c84481a43704213cd0948d2ba0ea63b4 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 23 Feb 2020 18:18:45 +0100 Subject: [PATCH 0462/1250] Implement `Copy` for `IoSlice` --- src/libstd/io/mod.rs | 1 + src/libstd/sys/cloudabi/io.rs | 1 + src/libstd/sys/hermit/io.rs | 1 + src/libstd/sys/sgx/io.rs | 1 + src/libstd/sys/unix/io.rs | 1 + src/libstd/sys/vxworks/io.rs | 1 + src/libstd/sys/wasi/io.rs | 1 + src/libstd/sys/wasm/io.rs | 1 + src/libstd/sys/windows/c.rs | 1 + src/libstd/sys/windows/io.rs | 1 + 10 files changed, 10 insertions(+) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 67b382c7a84..5dd3ec99676 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -1051,6 +1051,7 @@ impl<'a> DerefMut for IoSliceMut<'a> { /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on /// Windows. #[stable(feature = "iovec", since = "1.36.0")] +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a>(sys::io::IoSlice<'a>); diff --git a/src/libstd/sys/cloudabi/io.rs b/src/libstd/sys/cloudabi/io.rs index 976e122463d..d5f475b4310 100644 --- a/src/libstd/sys/cloudabi/io.rs +++ b/src/libstd/sys/cloudabi/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/hermit/io.rs b/src/libstd/sys/hermit/io.rs index 976e122463d..d5f475b4310 100644 --- a/src/libstd/sys/hermit/io.rs +++ b/src/libstd/sys/hermit/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/sgx/io.rs b/src/libstd/sys/sgx/io.rs index 976e122463d..d5f475b4310 100644 --- a/src/libstd/sys/sgx/io.rs +++ b/src/libstd/sys/sgx/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/unix/io.rs b/src/libstd/sys/unix/io.rs index b4a64e93c84..deb5ee76bd0 100644 --- a/src/libstd/sys/unix/io.rs +++ b/src/libstd/sys/unix/io.rs @@ -3,6 +3,7 @@ use crate::slice; use libc::{c_void, iovec}; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: iovec, diff --git a/src/libstd/sys/vxworks/io.rs b/src/libstd/sys/vxworks/io.rs index f1a2c8446ff..0f68ebf8da9 100644 --- a/src/libstd/sys/vxworks/io.rs +++ b/src/libstd/sys/vxworks/io.rs @@ -3,6 +3,7 @@ use crate::slice; use libc::{c_void, iovec}; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: iovec, diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs index ee20ea6dab8..0ad2e152855 100644 --- a/src/libstd/sys/wasi/io.rs +++ b/src/libstd/sys/wasi/io.rs @@ -1,6 +1,7 @@ use crate::marker::PhantomData; use crate::slice; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: wasi::Ciovec, diff --git a/src/libstd/sys/wasm/io.rs b/src/libstd/sys/wasm/io.rs index 976e122463d..d5f475b4310 100644 --- a/src/libstd/sys/wasm/io.rs +++ b/src/libstd/sys/wasm/io.rs @@ -1,5 +1,6 @@ use crate::mem; +#[derive(Copy, Clone)] pub struct IoSlice<'a>(&'a [u8]); impl<'a> IoSlice<'a> { diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 4d377341be3..d7e1a801030 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -295,6 +295,7 @@ pub struct WSADATA { pub szSystemStatus: [u8; WSASYS_STATUS_LEN + 1], } +#[derive(Copy, Clone)] #[repr(C)] pub struct WSABUF { pub len: ULONG, diff --git a/src/libstd/sys/windows/io.rs b/src/libstd/sys/windows/io.rs index 9d8018fd5e8..5525d283252 100644 --- a/src/libstd/sys/windows/io.rs +++ b/src/libstd/sys/windows/io.rs @@ -2,6 +2,7 @@ use crate::marker::PhantomData; use crate::slice; use crate::sys::c; +#[derive(Copy, Clone)] #[repr(transparent)] pub struct IoSlice<'a> { vec: c::WSABUF, From 01d932934748ef5c412c11a2ace18a504a7cb949 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 19:50:34 +0100 Subject: [PATCH 0463/1250] canonicalize alloc ID before calling tag_static_base_pointer --- src/librustc_mir/interpret/machine.rs | 2 ++ src/librustc_mir/interpret/memory.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 98a305ec2d9..11d28ec582a 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -253,6 +253,8 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Return the "base" tag for the given *static* allocation: the one that is used for direct /// accesses to this static/const/fn allocation. If `id` is not a static allocation, /// this will return an unusable tag (i.e., accesses will be UB)! + /// + /// Expects `id` to be already canonical, if needed. fn tag_static_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag; /// Executes a retagging operation diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 048c5d7b159..f60307e468b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -150,7 +150,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// through a pointer that was created by the program. #[inline] pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { - ptr.with_tag(M::tag_static_base_pointer(&self.extra, ptr.alloc_id)) + let id = M::canonical_alloc_id(self, ptr.alloc_id); + ptr.with_tag(M::tag_static_base_pointer(&self.extra, id)) } pub fn create_fn_alloc( From b3e0d272af149c4126f90a0262d796d7401ba7a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20K=C4=85dzio=C5=82ka?= Date: Sun, 23 Feb 2020 21:19:25 +0100 Subject: [PATCH 0464/1250] docs: Stdin::read_line: mention the appending --- src/libstd/io/stdio.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 6add644dcc2..d410faca30d 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -302,7 +302,7 @@ impl Stdin { StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) } } - /// Locks this handle and reads a line of input into the specified buffer. + /// Locks this handle and reads a line of input, appending it to the specified buffer. /// /// For detailed semantics of this method, see the documentation on /// [`BufRead::read_line`]. From 9b62d60db18415caf3460b894e4f43f51da4f645 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 22:39:57 +0100 Subject: [PATCH 0465/1250] fmt --- src/librustc_mir/interpret/machine.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 11d28ec582a..69c9664b351 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -219,10 +219,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// /// This function must be idempotent. #[inline] - fn canonical_alloc_id( - _mem: &Memory<'mir, 'tcx, Self>, - id: AllocId, - ) -> AllocId { + fn canonical_alloc_id(_mem: &Memory<'mir, 'tcx, Self>, id: AllocId) -> AllocId { id } From fa2a792491ed28530146ee55a46128c05a8026ad Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 02:01:53 +0100 Subject: [PATCH 0466/1250] add `Span` to `ast::Defaultness::Default`. --- src/librustc_ast_lowering/item.rs | 12 ++++------ src/librustc_ast_passes/ast_validation.rs | 12 ++++++---- src/librustc_ast_passes/feature_gate.rs | 4 ++-- src/librustc_ast_pretty/pprust.rs | 2 +- src/librustc_parse/parser/item.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/libsyntax/ast.rs | 2 +- .../parser/assoc-static-semantic-fail.stderr | 8 +++++-- ...item-with-defaultness-fail-semantic.stderr | 24 ++++++++++++++----- .../specialization/defaultimpl/validation.rs | 2 +- .../defaultimpl/validation.stderr | 8 ++++--- 11 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 1a19fab0265..3d6926df58d 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -810,13 +810,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } AssocItemKind::Macro(..) => unimplemented!(), }; - hir::TraitItemRef { - id: hir::TraitItemId { hir_id: self.lower_node_id(i.id) }, - ident: i.ident, - span: i.span, - defaultness: self.lower_defaultness(Defaultness::Default, has_default), - kind, - } + let id = hir::TraitItemId { hir_id: self.lower_node_id(i.id) }; + let defaultness = hir::Defaultness::Default { has_value: has_default }; + hir::TraitItemRef { id, ident: i.ident, span: i.span, defaultness, kind } } /// Construct `ExprKind::Err` for the given `span`. @@ -948,7 +944,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_defaultness(&self, d: Defaultness, has_value: bool) -> hir::Defaultness { match d { - Defaultness::Default => hir::Defaultness::Default { has_value: has_value }, + Defaultness::Default(_) => hir::Defaultness::Default { has_value }, Defaultness::Final => { assert!(has_value); hir::Defaultness::Final diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index a9844a7059e..d385ea1a4a6 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -400,9 +400,11 @@ impl<'a> AstValidator<'a> { } fn check_defaultness(&self, span: Span, defaultness: Defaultness) { - if let Defaultness::Default = defaultness { + if let Defaultness::Default(def_span) = defaultness { + let span = self.session.source_map().def_span(span); self.err_handler() .struct_span_err(span, "`default` is only allowed on items in `impl` definitions") + .span_label(def_span, "`default` because of this") .emit(); } } @@ -863,10 +865,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if polarity == ImplPolarity::Negative { self.err_handler().span_err(item.span, "inherent impls cannot be negative"); } - if defaultness == Defaultness::Default { + if let Defaultness::Default(def_span) = defaultness { + let span = self.session.source_map().def_span(item.span); self.err_handler() - .struct_span_err(item.span, "inherent impls cannot be default") - .note("only trait implementations may be annotated with default") + .struct_span_err(span, "inherent impls cannot be `default`") + .span_label(def_span, "`default` because of this") + .note("only trait implementations may be annotated with `default`") .emit(); } if let Const::Yes(span) = constness { diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 5bddae0d49e..586539d9b5e 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -349,7 +349,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ); } - if let ast::Defaultness::Default = defaultness { + if let ast::Defaultness::Default(_) = defaultness { gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); } } @@ -543,7 +543,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { - if i.defaultness == ast::Defaultness::Default { + if let ast::Defaultness::Default(_) = i.defaultness { gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 548ae6e7e63..abe3165df4b 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1389,7 +1389,7 @@ impl<'a> State<'a> { } crate fn print_defaultness(&mut self, defaultness: ast::Defaultness) { - if let ast::Defaultness::Default = defaultness { + if let ast::Defaultness::Default(_) = defaultness { self.word_nbsp("default"); } } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 328cf11c532..a6e4900bc62 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -547,7 +547,7 @@ impl<'a> Parser<'a> { ) { self.bump(); // `default` - Defaultness::Default + Defaultness::Default(self.prev_span) } else { Defaultness::Final } diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 2c07ed0571b..a7a10c0be0d 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -502,7 +502,7 @@ impl Sig for ast::Item { items: _, } => { let mut text = String::new(); - if let ast::Defaultness::Default = defaultness { + if let ast::Defaultness::Default(_) = defaultness { text.push_str("default "); } if let ast::Unsafe::Yes(_) = unsafety { diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 849950e939a..bcf94d19613 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2106,7 +2106,7 @@ pub enum Const { /// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532). #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub enum Defaultness { - Default, + Default(Span), Final, } diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr index d02e2855c7e..dfd0053fda2 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.stderr +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -74,13 +74,17 @@ error: `default` is only allowed on items in `impl` definitions --> $DIR/assoc-static-semantic-fail.rs:24:5 | LL | default static TC: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | -------^^^^^^^^^^^^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/assoc-static-semantic-fail.rs:27:5 | LL | pub(crate) default static TD: u8; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^-------^^^^^^^^^^^^^^^ + | | + | `default` because of this error[E0449]: unnecessary visibility qualifier --> $DIR/assoc-static-semantic-fail.rs:27:5 diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr index 54111df3423..6bb946d5b64 100644 --- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr +++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr @@ -2,37 +2,49 @@ error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:6:5 | LL | default const A: u8; - | ^^^^^^^^^^^^^^^^^^^^ + | -------^^^^^^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:7:5 | LL | default const B: u8 = 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | -------^^^^^^^^^^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:8:5 | LL | default type D; - | ^^^^^^^^^^^^^^^ + | -------^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:9:5 | LL | default type C: Ord; - | ^^^^^^^^^^^^^^^^^^^^ + | -------^^^^^^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:10:5 | LL | default fn f1(); - | ^^^^^^^^^^^^^^^^ + | -------^^^^^^^^^ + | | + | `default` because of this error: `default` is only allowed on items in `impl` definitions --> $DIR/trait-item-with-defaultness-fail-semantic.rs:11:5 | LL | default fn f2() {} - | ^^^^^^^^^^^^^^^^^^ + | -------^^^^^^^^ + | | + | `default` because of this error: aborting due to 6 previous errors diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs index cf5d6628054..26b3f1ec414 100644 --- a/src/test/ui/specialization/defaultimpl/validation.rs +++ b/src/test/ui/specialization/defaultimpl/validation.rs @@ -4,7 +4,7 @@ struct S; struct Z; -default impl S {} //~ ERROR inherent impls cannot be default +default impl S {} //~ ERROR inherent impls cannot be `default` default unsafe impl Send for S {} //~ ERROR impls of auto traits cannot be default default impl !Send for Z {} //~ ERROR impls of auto traits cannot be default diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 14a06c39088..03b1ef69ca0 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -1,10 +1,12 @@ -error: inherent impls cannot be default +error: inherent impls cannot be `default` --> $DIR/validation.rs:7:1 | LL | default impl S {} - | ^^^^^^^^^^^^^^^^^ + | -------^^^^^^^ + | | + | `default` because of this | - = note: only trait implementations may be annotated with default + = note: only trait implementations may be annotated with `default` error: impls of auto traits cannot be default --> $DIR/validation.rs:9:1 From d41fc138bf57db0d5491d0886a676c3ade4b746f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 02:32:02 +0100 Subject: [PATCH 0467/1250] `parse_defaultness`: avoid hardcoded list of keywords. --- src/librustc_parse/parser/item.rs | 39 +++++++++++-------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index a6e4900bc62..e770b4212e5 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -147,10 +147,7 @@ impl<'a> Parser<'a> { || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { // IMPL ITEM - let defaultness = self.parse_defaultness(); - let unsafety = self.parse_unsafety(); - self.expect_keyword(kw::Impl)?; - self.parse_item_impl(attrs, unsafety, defaultness)? + self.parse_item_impl(attrs)? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM self.parse_item_mod(attrs)? @@ -349,7 +346,7 @@ impl<'a> Parser<'a> { err } - /// Parses an implementation item, `impl` keyword is already parsed. + /// Parses an implementation item. /// /// ``` /// impl<'a, T> TYPE { /* impl items */ } @@ -363,12 +360,11 @@ impl<'a> Parser<'a> { /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}" /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}" /// ``` - fn parse_item_impl( - &mut self, - attrs: &mut Vec, - unsafety: Unsafe, - defaultness: Defaultness, - ) -> PResult<'a, ItemInfo> { + fn parse_item_impl(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let defaultness = self.parse_defaultness(); + let unsafety = self.parse_unsafety(); + self.expect_keyword(kw::Impl)?; + // First, parse generic parameters if necessary. let mut generics = if self.choose_generics_over_qpath() { self.parse_generics()? @@ -529,22 +525,13 @@ impl<'a> Parser<'a> { /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { - // `pub` is included for better error messages + // We are interested in `default` followed by another keyword. + // However, we must avoid keywords that occur as binary operators. + // Currently, the only applicable keyword is `as` (`default as Ty`). if self.check_keyword(kw::Default) - && self.is_keyword_ahead( - 1, - &[ - kw::Impl, - kw::Static, - kw::Const, - kw::Async, - kw::Fn, - kw::Unsafe, - kw::Extern, - kw::Type, - kw::Pub, - ], - ) + && self.look_ahead(1, |t| { + t.is_non_raw_ident_where(|i| i.is_reserved() && i.name != kw::As) + }) { self.bump(); // `default` Defaultness::Default(self.prev_span) From 7017058e6b289ea6253e62b9ffdae5dea036855f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 03:29:17 +0100 Subject: [PATCH 0468/1250] ast: add `Defaultness` to `Item`, making `AssocItem` an alias. --- src/librustc_ast_pretty/pprust.rs | 4 ++-- src/librustc_builtin_macros/global_asm.rs | 1 + src/librustc_builtin_macros/test_harness.rs | 24 +++++++------------ src/librustc_expand/build.rs | 1 + src/librustc_expand/expand.rs | 1 + src/librustc_expand/placeholders.rs | 3 +++ .../rmeta/decoder/cstore_impl.rs | 1 + src/librustc_parse/parser/item.rs | 7 +++--- src/libsyntax/ast.rs | 23 ++++++------------ src/libsyntax/attr/mod.rs | 2 +- src/libsyntax/mut_visit.rs | 8 +++---- src/libsyntax/visit.rs | 2 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- 13 files changed, 35 insertions(+), 44 deletions(-) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index abe3165df4b..503310c6db5 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1016,8 +1016,8 @@ impl<'a> State<'a> { } crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) { - let ast::ForeignItem { id, span, ident, attrs, kind, vis, tokens: _ } = item; - self.print_nested_item_kind(*id, *span, *ident, attrs, ast::Defaultness::Final, kind, vis); + let ast::Item { id, span, ident, attrs, kind, vis, defaultness, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis); } fn print_nested_item_kind( diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs index 052e62ee9ff..70b9fccbafc 100644 --- a/src/librustc_builtin_macros/global_asm.rs +++ b/src/librustc_builtin_macros/global_asm.rs @@ -30,6 +30,7 @@ pub fn expand_global_asm<'cx>( id: ast::DUMMY_NODE_ID, kind: ast::ItemKind::GlobalAsm(P(global_asm)), vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), + defaultness: ast::Defaultness::Final, span: cx.with_def_site_ctxt(sp), tokens: None, })]), diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index f0ea256cf2b..1d8ade1b2ba 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -162,7 +162,7 @@ impl MutVisitor for EntryPointCleaner { // #[allow(dead_code)] to avoid printing warnings. let item = match entry::entry_point_type(&item, self.depth) { EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item - .map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { + .map(|ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }| { let allow_ident = Ident::new(sym::allow, self.def_site); let dc_nested = attr::mk_nested_word_item(Ident::from_str_and_span( "dead_code", @@ -170,22 +170,13 @@ impl MutVisitor for EntryPointCleaner { )); 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); + let attrs = attrs + .into_iter() + .filter(|attr| !attr.check_name(sym::main) && !attr.check_name(sym::start)) + .chain(iter::once(allow_dead_code)) + .collect(); - ast::Item { - id, - ident, - attrs: attrs - .into_iter() - .filter(|attr| { - !attr.check_name(sym::main) && !attr.check_name(sym::start) - }) - .chain(iter::once(allow_dead_code)) - .collect(), - kind, - vis, - span, - tokens, - } + ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens } }), EntryPointType::None | EntryPointType::OtherMain => item, }; @@ -321,6 +312,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { id: ast::DUMMY_NODE_ID, kind: main, vis: respan(sp, ast::VisibilityKind::Public), + defaultness: ast::Defaultness::Final, span: sp, tokens: None, }); diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index 8a53e1d1861..246b3bff71d 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -588,6 +588,7 @@ impl<'a> ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, kind, vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), + defaultness: ast::Defaultness::Final, span, tokens: None, }) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 5d0c474140f..ba26780dea2 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -358,6 +358,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ident: Ident::invalid(), id: ast::DUMMY_NODE_ID, vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public), + defaultness: ast::Defaultness::Final, tokens: None, })]); diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs index c96b394c7b5..e7e4f482a5e 100644 --- a/src/librustc_expand/placeholders.rs +++ b/src/librustc_expand/placeholders.rs @@ -26,6 +26,7 @@ pub fn placeholder( let ident = ast::Ident::invalid(); let attrs = Vec::new(); let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited)); + let defaultness = ast::Defaultness::Final; let span = DUMMY_SP; let expr_placeholder = || { P(ast::Expr { @@ -46,6 +47,7 @@ pub fn placeholder( span, ident, vis, + defaultness, attrs, kind: ast::ItemKind::Mac(mac_placeholder()), tokens: None, @@ -76,6 +78,7 @@ pub fn placeholder( span, ident, vis, + defaultness, attrs, kind: ast::ForeignItemKind::Macro(mac_placeholder()), tokens: None, diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index fb7e5541e26..602be372573 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -464,6 +464,7 @@ impl CStore { legacy: def.legacy, }), vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), + defaultness: ast::Defaultness::Final, tokens: None, }, data.root.edition, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index e770b4212e5..190baa9b2d9 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -85,7 +85,7 @@ impl<'a> Parser<'a> { let vis = self.parse_visibility(FollowedByType::No)?; if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(P(self.mk_item(lo, ident, kind, vis, attrs)))); + return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs)))); } // FAILURE TO PARSE ITEM @@ -866,7 +866,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?; - let item = self.mk_item(lo, ident, kind, vis, attrs); + let item = self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs); self.error_on_foreign_const(&item); Ok(P(item)) } @@ -1420,10 +1420,11 @@ impl<'a> Parser<'a> { ident: Ident, kind: K, vis: Visibility, + defaultness: Defaultness, attrs: Vec, ) -> Item { let span = lo.to(self.prev_span); - Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, span, tokens: None } + Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, defaultness, span, tokens: None } } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bcf94d19613..dd3319fcba1 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2411,16 +2411,19 @@ impl VariantData { } } -/// An item. -/// -/// The name might be a dummy name in case of anonymous items. +/// An item definition. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Item { pub attrs: Vec, pub id: NodeId, pub span: Span, pub vis: Visibility, + /// The name of the item. + /// It might be a dummy name in case of anonymous items. pub ident: Ident, + /// The `default`ness of this item. + /// This should only occur in syntactically well-formed code in associated contexts. + pub defaultness: Defaultness, pub kind: K, @@ -2613,19 +2616,7 @@ pub type ForeignItemKind = AssocItemKind; /// Represents associated items. /// These include items in `impl` and `trait` definitions. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] -pub struct AssocItem { - pub attrs: Vec, - pub id: NodeId, - pub span: Span, - pub vis: Visibility, - pub ident: Ident, - - pub defaultness: Defaultness, - pub kind: AssocItemKind, - /// See `Item::tokens` for what this is. - pub tokens: Option, -} +pub type AssocItem = Item; /// Represents non-free item kinds. /// diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index 313f5269235..cd485e71378 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -722,6 +722,6 @@ macro_rules! derive_has_attrs { } derive_has_attrs! { - Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::AssocItem, ast::Arm, + Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::Arm, ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam } diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 02f790dfbb4..048026cbb24 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -948,8 +948,7 @@ pub fn noop_flat_map_assoc_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let AssocItem { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = - item.deref_mut(); + let Item { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut(); walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } @@ -1004,6 +1003,7 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { attrs, id: DUMMY_NODE_ID, vis: respan(span.shrink_to_lo(), VisibilityKind::Public), + defaultness: Defaultness::Final, span, kind: ItemKind::Mod(module), tokens: None, @@ -1031,7 +1031,7 @@ pub fn noop_flat_map_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); + let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut(); visitor.visit_ident(ident); visit_attrs(attrs, visitor); visitor.visit_id(id); @@ -1049,7 +1049,7 @@ pub fn noop_flat_map_foreign_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let ForeignItem { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); + let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut(); walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index bd35918dba7..244cb80064e 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -526,7 +526,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - let ForeignItem { id, span, ident, vis, attrs, kind, tokens: _ } = item; + let ForeignItem { id, span, ident, vis, defaultness: _, attrs, kind, tokens: _ } = item; walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign); } diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index 35e418696f1..bbda63955e0 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"defaultness":"Final","kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]} From 9ed4c0998381901ac68c19c30c375f5760016759 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 03:44:24 +0100 Subject: [PATCH 0469/1250] parse: extract `error_on_unmatched_vis`. --- src/librustc_parse/parser/item.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 190baa9b2d9..732bbdf1c54 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -88,16 +88,9 @@ impl<'a> Parser<'a> { return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs)))); } - // FAILURE TO PARSE ITEM - if let VisibilityKind::Inherited = vis.node { - } else { - let vs = pprust::vis_to_string(&vis); - let vs = vs.trim_end(); - self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) - .span_label(vis.span, "the unmatched visibility") - .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) - .emit(); - } + // At this point, we have failed to parse an item. + + self.error_on_unmatched_vis(&vis); if !attributes_allowed { self.recover_attrs_no_item(&attrs)?; @@ -105,6 +98,19 @@ impl<'a> Parser<'a> { Ok(None) } + /// Error in-case a non-inherited visibility was parsed but no item followed. + fn error_on_unmatched_vis(&self, vis: &Visibility) { + if let VisibilityKind::Inherited = vis.node { + return; + } + let vs = pprust::vis_to_string(&vis); + let vs = vs.trim_end(); + self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) + .span_label(vis.span, "the unmatched visibility") + .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) + .emit(); + } + /// Parses one of the items allowed by the flags. fn parse_item_kind( &mut self, From a920a056035d3aa8f5e90ff174764a886366d379 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 04:53:02 +0100 Subject: [PATCH 0470/1250] parse: recover `default` on free items. --- src/librustc_parse/parser/item.rs | 59 +++++++-- .../ui/parser/default-on-wrong-item-kind.rs | 26 ++++ .../parser/default-on-wrong-item-kind.stderr | 122 ++++++++++++++++++ src/test/ui/parser/default-unmatched.rs | 6 + src/test/ui/parser/default-unmatched.stderr | 14 ++ src/test/ui/parser/impl-parsing.rs | 3 +- src/test/ui/parser/impl-parsing.stderr | 14 +- 7 files changed, 226 insertions(+), 18 deletions(-) create mode 100644 src/test/ui/parser/default-on-wrong-item-kind.rs create mode 100644 src/test/ui/parser/default-on-wrong-item-kind.stderr create mode 100644 src/test/ui/parser/default-unmatched.rs create mode 100644 src/test/ui/parser/default-unmatched.stderr diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 732bbdf1c54..184956e1065 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -81,17 +81,30 @@ impl<'a> Parser<'a> { Some(item) }); + let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed)?; + if let Some(ref item) = item { + self.error_on_illegal_default(item.defaultness); + } + Ok(item.map(P)) + } + + fn parse_item_common( + &mut self, + mut attrs: Vec, + macros_allowed: bool, + attributes_allowed: bool, + ) -> PResult<'a, Option> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; - - if let Some((ident, kind)) = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis)? { - return Ok(Some(P(self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs)))); + let mut def = self.parse_defaultness(); + let kind = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis, &mut def)?; + if let Some((ident, kind)) = kind { + return Ok(Some(self.mk_item(lo, ident, kind, vis, def, attrs))); } // At this point, we have failed to parse an item. - self.error_on_unmatched_vis(&vis); - + self.error_on_unmatched_defaultness(def); if !attributes_allowed { self.recover_attrs_no_item(&attrs)?; } @@ -111,6 +124,25 @@ impl<'a> Parser<'a> { .emit(); } + /// Error in-case a `default` was parsed but no item followed. + fn error_on_unmatched_defaultness(&self, def: Defaultness) { + if let Defaultness::Default(span) = def { + self.struct_span_err(span, "unmatched `default`") + .span_label(span, "the unmatched `default`") + .emit(); + } + } + + /// Error in-case `default` was parsed in an in-appropriate context. + fn error_on_illegal_default(&self, def: Defaultness) { + if let Defaultness::Default(span) = def { + self.struct_span_err(span, "item cannot be `default`") + .span_label(span, "`default` because of this") + .note("only associated `fn`, `const`, and `type` items can be `default`") + .emit(); + } + } + /// Parses one of the items allowed by the flags. fn parse_item_kind( &mut self, @@ -118,6 +150,7 @@ impl<'a> Parser<'a> { macros_allowed: bool, lo: Span, vis: &Visibility, + def: &mut Defaultness, ) -> PResult<'a, Option> { let info = if self.eat_keyword(kw::Use) { // USE ITEM @@ -150,10 +183,9 @@ impl<'a> Parser<'a> { self.parse_item_trait(attrs, lo)? } else if self.check_keyword(kw::Impl) || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) - || self.check_keyword(kw::Default) && self.is_keyword_ahead(1, &[kw::Impl, kw::Unsafe]) { // IMPL ITEM - self.parse_item_impl(attrs)? + self.parse_item_impl(attrs, mem::replace(def, Defaultness::Final))? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM self.parse_item_mod(attrs)? @@ -366,8 +398,11 @@ impl<'a> Parser<'a> { /// "impl" GENERICS "const"? "!"? TYPE "for"? (TYPE | "..") ("where" PREDICATES)? "{" BODY "}" /// "impl" GENERICS "const"? "!"? TYPE ("where" PREDICATES)? "{" BODY "}" /// ``` - fn parse_item_impl(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let defaultness = self.parse_defaultness(); + fn parse_item_impl( + &mut self, + attrs: &mut Vec, + defaultness: Defaultness, + ) -> PResult<'a, ItemInfo> { let unsafety = self.parse_unsafety(); self.expect_keyword(kw::Impl)?; @@ -531,13 +566,11 @@ impl<'a> Parser<'a> { /// Parses defaultness (i.e., `default` or nothing). fn parse_defaultness(&mut self) -> Defaultness { - // We are interested in `default` followed by another keyword. + // We are interested in `default` followed by another identifier. // However, we must avoid keywords that occur as binary operators. // Currently, the only applicable keyword is `as` (`default as Ty`). if self.check_keyword(kw::Default) - && self.look_ahead(1, |t| { - t.is_non_raw_ident_where(|i| i.is_reserved() && i.name != kw::As) - }) + && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As)) { self.bump(); // `default` Defaultness::Default(self.prev_span) diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs new file mode 100644 index 00000000000..f7d390eb8a2 --- /dev/null +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -0,0 +1,26 @@ +// Test parsing for `default` where it doesn't belong. +// Specifically, we are interested in kinds of items or items in certain contexts. + +fn main() {} + +#[cfg(FALSE)] +mod free_items { + default extern crate foo; //~ ERROR item cannot be `default` + default use foo; //~ ERROR item cannot be `default` + default static foo: u8; //~ ERROR item cannot be `default` + default const foo: u8; //~ ERROR item cannot be `default` + default fn foo(); //~ ERROR item cannot be `default` + default mod foo {} //~ ERROR item cannot be `default` + default extern "C" {} //~ ERROR item cannot be `default` + default type foo = u8; //~ ERROR item cannot be `default` + default enum foo {} //~ ERROR item cannot be `default` + default struct foo {} //~ ERROR item cannot be `default` + default union foo {} //~ ERROR item cannot be `default` + default trait foo {} //~ ERROR item cannot be `default` + default trait foo = Ord; //~ ERROR item cannot be `default` + default impl foo {} + default!(); + default::foo::bar!(); + default macro foo {} //~ ERROR item cannot be `default` + default macro_rules! foo {} //~ ERROR item cannot be `default` +} diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr new file mode 100644 index 00000000000..d279fd962bb --- /dev/null +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -0,0 +1,122 @@ +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:8:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:9:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:10:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:11:5 + | +LL | default const foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:12:5 + | +LL | default fn foo(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:13:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:14:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:15:5 + | +LL | default type foo = u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:16:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:17:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:18:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:19:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:20:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:24:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:25:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: aborting due to 15 previous errors + diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs new file mode 100644 index 00000000000..31696de0a5c --- /dev/null +++ b/src/test/ui/parser/default-unmatched.rs @@ -0,0 +1,6 @@ +mod foo { + default!(); // OK. + default do + //~^ ERROR unmatched `default` + //~| ERROR expected item, found reserved keyword `do` +} diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr new file mode 100644 index 00000000000..6e4ef7b79fc --- /dev/null +++ b/src/test/ui/parser/default-unmatched.stderr @@ -0,0 +1,14 @@ +error: unmatched `default` + --> $DIR/default-unmatched.rs:3:5 + | +LL | default do + | ^^^^^^^ the unmatched `default` + +error: expected item, found reserved keyword `do` + --> $DIR/default-unmatched.rs:3:13 + | +LL | default do + | ^^ expected item + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs index 270c8b43dfd..662ed28f2f7 100644 --- a/src/test/ui/parser/impl-parsing.rs +++ b/src/test/ui/parser/impl-parsing.rs @@ -6,4 +6,5 @@ impl Trait .. {} //~ ERROR missing `for` in a trait impl impl ?Sized for Type {} //~ ERROR expected a trait, found type impl ?Sized for .. {} //~ ERROR expected a trait, found type -default unsafe FAIL //~ ERROR expected `impl`, found `FAIL` +default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` +//~^ ERROR unmatched `default` diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr index 7c2a7937c5d..a5fc3e46896 100644 --- a/src/test/ui/parser/impl-parsing.stderr +++ b/src/test/ui/parser/impl-parsing.stderr @@ -22,11 +22,17 @@ error: expected a trait, found type LL | impl ?Sized for .. {} | ^^^^^^ -error: expected `impl`, found `FAIL` - --> $DIR/impl-parsing.rs:9:16 +error: unmatched `default` + --> $DIR/impl-parsing.rs:9:1 | LL | default unsafe FAIL - | ^^^^ expected `impl` + | ^^^^^^^ the unmatched `default` -error: aborting due to 5 previous errors +error: expected item, found keyword `unsafe` + --> $DIR/impl-parsing.rs:9:9 + | +LL | default unsafe FAIL + | ^^^^^^ expected item + +error: aborting due to 6 previous errors From a63f35daeefc4ae89ba5b6bd0323d97bb0d050e6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 06:57:31 +0100 Subject: [PATCH 0471/1250] parse: use `parse_item_common` in `parse_foreign_item`. --- src/librustc_expand/expand.rs | 4 +- src/librustc_parse/parser/item.rs | 81 +++--- src/test/ui/macros/issue-54441.rs | 3 +- src/test/ui/macros/issue-54441.stderr | 16 +- .../ui/parser/default-on-wrong-item-kind.rs | 36 +++ .../parser/default-on-wrong-item-kind.stderr | 234 ++++++++++++++++-- .../ui/parser/default-unmatched-extern.rs | 8 + .../ui/parser/default-unmatched-extern.stderr | 26 ++ src/test/ui/parser/duplicate-visibility.rs | 3 +- .../ui/parser/duplicate-visibility.stderr | 21 +- src/test/ui/parser/extern-no-fn.rs | 3 +- src/test/ui/parser/extern-no-fn.stderr | 11 +- .../ui/parser/foreign-const-semantic-fail.rs | 1 + .../parser/foreign-const-semantic-fail.stderr | 15 +- 14 files changed, 392 insertions(+), 70 deletions(-) create mode 100644 src/test/ui/parser/default-unmatched-extern.rs create mode 100644 src/test/ui/parser/default-unmatched-extern.stderr diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index ba26780dea2..df2753813f9 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -879,8 +879,8 @@ pub fn parse_ast_fragment<'a>( } AstFragmentKind::ForeignItems => { let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_foreign_item(&mut false)?); + while let Some(item) = this.parse_foreign_item()? { + items.extend(item); } AstFragment::ForeignItems(items) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 184956e1065..ecd2049963b 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -457,7 +457,8 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let impl_items = self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end))?; + let impl_items = + self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?; let item_kind = match ty_second { Some(ty_second) => { @@ -516,8 +517,9 @@ impl<'a> Parser<'a> { fn parse_item_list( &mut self, attrs: &mut Vec, - mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, T>, + mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option>>, ) -> PResult<'a, Vec> { + let open_brace_span = self.token.span; self.expect(&token::OpenDelim(token::Brace))?; attrs.append(&mut self.parse_inner_attributes()?); @@ -528,7 +530,18 @@ impl<'a> Parser<'a> { } let mut at_end = false; match parse_item(self, &mut at_end) { - Ok(item) => items.push(item), + Ok(None) => { + // We have to bail or we'll potentially never make progress. + let non_item_span = self.token.span; + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + self.struct_span_err(non_item_span, "non-item in item list") + .span_label(open_brace_span, "item list starts here") + .span_label(non_item_span, "non-item starts here") + .span_label(self.prev_span, "item list ends here") + .emit(); + break; + } + Ok(Some(item)) => items.extend(item), Err(mut err) => { err.emit(); if !at_end { @@ -631,7 +644,9 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let items = self.parse_item_list(attrs, |p, at_end| p.parse_trait_item(at_end))?; + let items = self.parse_item_list(attrs, |p, at_end| { + p.parse_trait_item(at_end).map(Some).map(Some) + })?; Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } @@ -892,38 +907,48 @@ impl<'a> Parser<'a> { /// ``` fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p, at_end| p.parse_foreign_item(at_end))?; + let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?; let module = ast::ForeignMod { abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } /// Parses a foreign item (one in an `extern { ... }` block). - pub fn parse_foreign_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { - maybe_whole!(self, NtForeignItem, |ni| ni); + pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { + maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); - let mut attrs = self.parse_outer_attributes()?; - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, |_| true, &vis)?; - let item = self.mk_item(lo, ident, kind, vis, Defaultness::Final, attrs); - self.error_on_foreign_const(&item); - Ok(P(item)) + let attrs = self.parse_outer_attributes()?; + let it = self.parse_item_common(attrs, true, false)?; + Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { + self.error_on_illegal_default(defaultness); + let kind = match kind { + ItemKind::Mac(a) => AssocItemKind::Macro(a), + ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), + ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), + ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c), + ItemKind::Const(a, b) => { + self.error_on_foreign_const(span, ident); + AssocItemKind::Static(a, Mutability::Not, b) + } + _ => { + let span = self.sess.source_map().def_span(span); + self.struct_span_err(span, "item kind not supported in `extern` block").emit(); + return None; + } + }; + Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) + })) } - fn error_on_foreign_const(&self, item: &ForeignItem) { - if let AssocItemKind::Const(..) = item.kind { - self.struct_span_err(item.ident.span, "extern items cannot be `const`") - .span_suggestion( - item.span.with_hi(item.ident.span.lo()), - "try using a static value", - "static ".to_string(), - Applicability::MachineApplicable, - ) - .note( - "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html", - ) - .emit(); - } + fn error_on_foreign_const(&self, span: Span, ident: Ident) { + self.struct_span_err(ident.span, "extern items cannot be `const`") + .span_suggestion( + span.with_hi(ident.span.lo()), + "try using a static value", + "static ".to_string(), + Applicability::MachineApplicable, + ) + .note("for more information, visit https://doc.rust-lang.org/std/keyword.extern.html") + .emit(); } fn is_static_global(&mut self) -> bool { diff --git a/src/test/ui/macros/issue-54441.rs b/src/test/ui/macros/issue-54441.rs index 5570f081b15..b24d7e1f6be 100644 --- a/src/test/ui/macros/issue-54441.rs +++ b/src/test/ui/macros/issue-54441.rs @@ -1,7 +1,6 @@ macro_rules! m { - //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration () => { - let + let //~ ERROR macro expansion ignores token `let` and any following }; } diff --git a/src/test/ui/macros/issue-54441.stderr b/src/test/ui/macros/issue-54441.stderr index 5857aacb431..752916e6655 100644 --- a/src/test/ui/macros/issue-54441.stderr +++ b/src/test/ui/macros/issue-54441.stderr @@ -1,11 +1,13 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-54441.rs:1:1 +error: macro expansion ignores token `let` and any following + --> $DIR/issue-54441.rs:3:9 | -LL | / macro_rules! m { -LL | | -LL | | () => { -LL | | let - | |________^ missing `fn`, `type`, `const`, or `static` +LL | let + | ^^^ +... +LL | m!(); + | ----- caused by the macro expansion here + | + = note: the usage of `m!` is likely invalid in foreign item context error: aborting due to previous error diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index f7d390eb8a2..0fe20473587 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -1,5 +1,6 @@ // Test parsing for `default` where it doesn't belong. // Specifically, we are interested in kinds of items or items in certain contexts. +// Also test item kinds in `extern` blocks and associated contexts which are not allowed there. fn main() {} @@ -24,3 +25,38 @@ mod free_items { default macro foo {} //~ ERROR item cannot be `default` default macro_rules! foo {} //~ ERROR item cannot be `default` } + +#[cfg(FALSE)] +extern "C" { + default extern crate foo; //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default use foo; //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default static foo: u8; //~ ERROR item cannot be `default` + default const foo: u8; //~ ERROR item cannot be `default` + //~^ ERROR extern items cannot be `const` + default fn foo(); //~ ERROR item cannot be `default` + default mod foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default extern "C" {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default type foo = u8; //~ ERROR item cannot be `default` + default enum foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default struct foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default union foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default trait foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default trait foo = Ord; //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default impl foo {} + //~^ ERROR item kind not supported in `extern` block + default!(); + default::foo::bar!(); + default macro foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block + default macro_rules! foo {} //~ ERROR item cannot be `default` + //~^ ERROR item kind not supported in `extern` block +} diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index d279fd962bb..e089bbbddde 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -1,5 +1,5 @@ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:8:5 + --> $DIR/default-on-wrong-item-kind.rs:9:5 | LL | default extern crate foo; | ^^^^^^^ `default` because of this @@ -7,7 +7,7 @@ LL | default extern crate foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:9:5 + --> $DIR/default-on-wrong-item-kind.rs:10:5 | LL | default use foo; | ^^^^^^^ `default` because of this @@ -15,7 +15,7 @@ LL | default use foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:10:5 + --> $DIR/default-on-wrong-item-kind.rs:11:5 | LL | default static foo: u8; | ^^^^^^^ `default` because of this @@ -23,7 +23,7 @@ LL | default static foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:11:5 + --> $DIR/default-on-wrong-item-kind.rs:12:5 | LL | default const foo: u8; | ^^^^^^^ `default` because of this @@ -31,7 +31,7 @@ LL | default const foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:12:5 + --> $DIR/default-on-wrong-item-kind.rs:13:5 | LL | default fn foo(); | ^^^^^^^ `default` because of this @@ -39,7 +39,7 @@ LL | default fn foo(); = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:13:5 + --> $DIR/default-on-wrong-item-kind.rs:14:5 | LL | default mod foo {} | ^^^^^^^ `default` because of this @@ -47,7 +47,7 @@ LL | default mod foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:14:5 + --> $DIR/default-on-wrong-item-kind.rs:15:5 | LL | default extern "C" {} | ^^^^^^^ `default` because of this @@ -55,7 +55,7 @@ LL | default extern "C" {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:15:5 + --> $DIR/default-on-wrong-item-kind.rs:16:5 | LL | default type foo = u8; | ^^^^^^^ `default` because of this @@ -63,7 +63,7 @@ LL | default type foo = u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:16:5 + --> $DIR/default-on-wrong-item-kind.rs:17:5 | LL | default enum foo {} | ^^^^^^^ `default` because of this @@ -71,7 +71,7 @@ LL | default enum foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:17:5 + --> $DIR/default-on-wrong-item-kind.rs:18:5 | LL | default struct foo {} | ^^^^^^^ `default` because of this @@ -79,7 +79,7 @@ LL | default struct foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:18:5 + --> $DIR/default-on-wrong-item-kind.rs:19:5 | LL | default union foo {} | ^^^^^^^ `default` because of this @@ -87,7 +87,7 @@ LL | default union foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:19:5 + --> $DIR/default-on-wrong-item-kind.rs:20:5 | LL | default trait foo {} | ^^^^^^^ `default` because of this @@ -95,7 +95,7 @@ LL | default trait foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:20:5 + --> $DIR/default-on-wrong-item-kind.rs:21:5 | LL | default trait foo = Ord; | ^^^^^^^ `default` because of this @@ -103,7 +103,7 @@ LL | default trait foo = Ord; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:24:5 + --> $DIR/default-on-wrong-item-kind.rs:25:5 | LL | default macro foo {} | ^^^^^^^ `default` because of this @@ -111,12 +111,214 @@ LL | default macro foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:25:5 + --> $DIR/default-on-wrong-item-kind.rs:26:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:31:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:31:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:33:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:33:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:35:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:36:5 + | +LL | default const foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: extern items cannot be `const` + --> $DIR/default-on-wrong-item-kind.rs:36:19 + | +LL | default const foo: u8; + | --------------^^^ + | | + | help: try using a static value: `static` + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:38:5 + | +LL | default fn foo(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:39:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:39:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:41:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:41:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:43:5 + | +LL | default type foo = u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:44:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:44:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:46:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:46:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:48:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:48:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:50:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:50:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:52:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:52:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:54:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:58:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:58:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:60:5 | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this | = note: only associated `fn`, `const`, and `type` items can be `default` -error: aborting due to 15 previous errors +error: item kind not supported in `extern` block + --> $DIR/default-on-wrong-item-kind.rs:60:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 43 previous errors diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs new file mode 100644 index 00000000000..fbf87a892f0 --- /dev/null +++ b/src/test/ui/parser/default-unmatched-extern.rs @@ -0,0 +1,8 @@ +fn main() {} + +extern "C" { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR unmatched `default` + //~| ERROR non-item in item list +} diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr new file mode 100644 index 00000000000..00c8898e2ce --- /dev/null +++ b/src/test/ui/parser/default-unmatched-extern.stderr @@ -0,0 +1,26 @@ +error: unmatched `default` + --> $DIR/default-unmatched-extern.rs:5:5 + | +LL | default do + | ^^^^^^^ the unmatched `default` + +error: non-item in item list + --> $DIR/default-unmatched-extern.rs:5:13 + | +LL | extern "C" { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-extern.rs:4:5 + | +LL | default!(); + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index f6e7f7e6abe..949b6e1dc24 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -2,5 +2,6 @@ fn main() {} extern { pub pub fn foo(); - //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration + //~^ ERROR unmatched visibility `pub` + //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 398ba65c9e1..2c79a343d05 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,21 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/duplicate-visibility.rs:4:8 +error: unmatched visibility `pub` + --> $DIR/duplicate-visibility.rs:4:5 | LL | pub pub fn foo(); - | ^ missing `fn`, `type`, `const`, or `static` + | ^^^ the unmatched visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: non-item in item list + --> $DIR/duplicate-visibility.rs:4:9 + | +LL | extern { + | - item list starts here +LL | pub pub fn foo(); + | ^^^ non-item starts here +... +LL | } + | - item list ends here -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/extern-no-fn.rs b/src/test/ui/parser/extern-no-fn.rs index dc47f741073..d9f35e0eb5c 100644 --- a/src/test/ui/parser/extern-no-fn.rs +++ b/src/test/ui/parser/extern-no-fn.rs @@ -1,6 +1,5 @@ extern { -//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration - f(); + f(); //~ ERROR expected one of `!` or `::`, found `(` } fn main() { diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr index 8d55eefc8d0..02320125014 100644 --- a/src/test/ui/parser/extern-no-fn.stderr +++ b/src/test/ui/parser/extern-no-fn.stderr @@ -1,11 +1,8 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/extern-no-fn.rs:1:9 +error: expected one of `!` or `::`, found `(` + --> $DIR/extern-no-fn.rs:2:6 | -LL | extern { - | _________^ -LL | | -LL | | f(); - | |____^ missing `fn`, `type`, `const`, or `static` +LL | f(); + | ^ expected one of `!` or `::` error: aborting due to previous error diff --git a/src/test/ui/parser/foreign-const-semantic-fail.rs b/src/test/ui/parser/foreign-const-semantic-fail.rs index d28b6414282..82978e655ba 100644 --- a/src/test/ui/parser/foreign-const-semantic-fail.rs +++ b/src/test/ui/parser/foreign-const-semantic-fail.rs @@ -5,4 +5,5 @@ extern { //~^ ERROR extern items cannot be `const` const B: isize = 42; //~^ ERROR extern items cannot be `const` + //~| ERROR incorrect `static` inside `extern` block } diff --git a/src/test/ui/parser/foreign-const-semantic-fail.stderr b/src/test/ui/parser/foreign-const-semantic-fail.stderr index f364f11bb03..f529b3ad87b 100644 --- a/src/test/ui/parser/foreign-const-semantic-fail.stderr +++ b/src/test/ui/parser/foreign-const-semantic-fail.stderr @@ -18,5 +18,18 @@ LL | const B: isize = 42; | = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to 2 previous errors +error: incorrect `static` inside `extern` block + --> $DIR/foreign-const-semantic-fail.rs:6:11 + | +LL | extern { + | ------ `extern` blocks define existing foreign statics and statics inside of them cannot have a body +... +LL | const B: isize = 42; + | ^ -- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 3 previous errors From a05c83b2ebc4e85e32f723e708a40dbd3f165cd0 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 08:16:39 +0100 Subject: [PATCH 0472/1250] parse: use `parse_item_common` in `parse_assoc_item_`. --- src/librustc_expand/expand.rs | 8 +- src/librustc_parse/parser/item.rs | 216 ++++++------------ .../ui/async-await/no-unsafe-async.stderr | 5 + src/test/ui/did_you_mean/issue-40006.rs | 20 +- src/test/ui/did_you_mean/issue-40006.stderr | 92 +++++--- .../empty_generics.stderr | 5 + src/test/ui/issues/issue-58856-1.stderr | 6 + src/test/ui/issues/issue-58856-2.rs | 2 +- src/test/ui/issues/issue-58856-2.stderr | 12 +- src/test/ui/issues/issue-60075.rs | 5 +- src/test/ui/issues/issue-60075.stderr | 18 +- .../ui/parser/assoc-static-semantic-fail.rs | 4 + .../parser/assoc-static-semantic-fail.stderr | 62 +++-- .../ui/parser/attrs-after-extern-mod.stderr | 4 + .../ui/parser/default-on-wrong-item-kind.rs | 70 ++++++ .../parser/default-on-wrong-item-kind.stderr | 158 ++++++++++++- src/test/ui/parser/default-unmatched-assoc.rs | 16 ++ .../ui/parser/default-unmatched-assoc.stderr | 50 ++++ src/test/ui/parser/default.rs | 3 +- src/test/ui/parser/default.stderr | 19 +- src/test/ui/parser/extern-no-fn.stderr | 4 + src/test/ui/parser/issue-19398.rs | 2 +- src/test/ui/parser/issue-19398.stderr | 16 +- src/test/ui/parser/issue-20711-2.stderr | 6 + src/test/ui/parser/issue-20711.stderr | 5 + src/test/ui/parser/issue-21153.rs | 2 +- src/test/ui/parser/issue-21153.stderr | 16 +- src/test/ui/parser/issue-32446.stderr | 7 +- src/test/ui/parser/issue-41155.rs | 4 +- src/test/ui/parser/issue-41155.stderr | 20 +- src/test/ui/parser/issue-6610.stderr | 6 +- .../ui/parser/macro/trait-non-item-macros.rs | 11 +- .../parser/macro/trait-non-item-macros.stderr | 23 +- .../missing-close-brace-in-impl-trait.rs | 5 +- .../missing-close-brace-in-impl-trait.stderr | 22 +- .../missing-close-brace-in-trait.rs | 4 +- .../missing-close-brace-in-trait.stderr | 21 +- .../ui/parser/removed-syntax-static-fn.stderr | 5 + 38 files changed, 668 insertions(+), 286 deletions(-) create mode 100644 src/test/ui/parser/default-unmatched-assoc.rs create mode 100644 src/test/ui/parser/default-unmatched-assoc.stderr diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index df2753813f9..e5f957a63de 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -865,15 +865,15 @@ pub fn parse_ast_fragment<'a>( } AstFragmentKind::TraitItems => { let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_trait_item(&mut false)?); + while let Some(item) = this.parse_trait_item()? { + items.extend(item); } AstFragment::TraitItems(items) } AstFragmentKind::ImplItems => { let mut items = SmallVec::new(); - while this.token != token::Eof { - items.push(this.parse_impl_item(&mut false)?); + while let Some(item) = this.parse_impl_item()? { + items.extend(item); } AstFragment::ImplItems(items) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index ecd2049963b..8c5add46bfc 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -5,12 +5,12 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; use rustc_ast_pretty::pprust; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, PResult, StashKey}; +use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use syntax::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; -use syntax::ast::{AssocItem, AssocItemKind, Item, ItemKind, UseTree, UseTreeKind}; -use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe}; +use syntax::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind}; +use syntax::ast::{Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind}; use syntax::ast::{BindingMode, Block, FnDecl, FnSig, Mac, MacArgs, MacDelimiter, Param, SelfKind}; use syntax::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use syntax::ast::{FnHeader, ForeignItem, Mutability, Visibility, VisibilityKind}; @@ -81,7 +81,7 @@ impl<'a> Parser<'a> { Some(item) }); - let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed)?; + let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; if let Some(ref item) = item { self.error_on_illegal_default(item.defaultness); } @@ -91,21 +91,25 @@ impl<'a> Parser<'a> { fn parse_item_common( &mut self, mut attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, + mac_allowed: bool, + attrs_allowed: bool, + req_name: ReqName, ) -> PResult<'a, Option> { let lo = self.token.span; let vis = self.parse_visibility(FollowedByType::No)?; let mut def = self.parse_defaultness(); - let kind = self.parse_item_kind(&mut attrs, macros_allowed, lo, &vis, &mut def)?; + let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?; if let Some((ident, kind)) = kind { - return Ok(Some(self.mk_item(lo, ident, kind, vis, def, attrs))); + let span = lo.to(self.prev_span); + let id = DUMMY_NODE_ID; + let item = Item { ident, attrs, id, kind, vis, defaultness: def, span, tokens: None }; + return Ok(Some(item)); } // At this point, we have failed to parse an item. self.error_on_unmatched_vis(&vis); self.error_on_unmatched_defaultness(def); - if !attributes_allowed { + if !attrs_allowed { self.recover_attrs_no_item(&attrs)?; } Ok(None) @@ -151,6 +155,7 @@ impl<'a> Parser<'a> { lo: Span, vis: &Visibility, def: &mut Defaultness, + req_name: ReqName, ) -> PResult<'a, Option> { let info = if self.eat_keyword(kw::Use) { // USE ITEM @@ -159,7 +164,7 @@ impl<'a> Parser<'a> { (Ident::invalid(), ItemKind::Use(P(tree))) } else if self.check_fn_front_matter() { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, |_| true)?; + let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, req_name)?; (ident, ItemKind::Fn(sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -367,23 +372,6 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } - /// Given this code `path(`, it seems like this is not - /// setting the visibility of a macro invocation, - /// but rather a mistyped method declaration. - /// Create a diagnostic pointing out that `fn` is missing. - /// - /// ``` - /// x | pub path(&self) { - /// | ^ missing `fn`, `type`, `const`, or `static` - /// ``` - fn missing_nested_item_kind_err(&self, prev_span: Span) -> DiagnosticBuilder<'a> { - let sp = prev_span.between(self.token.span); - let expected_kinds = "missing `fn`, `type`, `const`, or `static`"; - let mut err = self.struct_span_err(sp, &format!("{} for item declaration", expected_kinds)); - err.span_label(sp, expected_kinds); - err - } - /// Parses an implementation item. /// /// ``` @@ -457,8 +445,7 @@ impl<'a> Parser<'a> { generics.where_clause = self.parse_where_clause()?; - let impl_items = - self.parse_item_list(attrs, |p, at_end| p.parse_impl_item(at_end).map(Some).map(Some))?; + let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item())?; let item_kind = match ty_second { Some(ty_second) => { @@ -517,7 +504,7 @@ impl<'a> Parser<'a> { fn parse_item_list( &mut self, attrs: &mut Vec, - mut parse_item: impl FnMut(&mut Parser<'a>, &mut bool) -> PResult<'a, Option>>, + mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option>>, ) -> PResult<'a, Vec> { let open_brace_span = self.token.span; self.expect(&token::OpenDelim(token::Brace))?; @@ -528,8 +515,7 @@ impl<'a> Parser<'a> { if self.recover_doc_comment_before_brace() { continue; } - let mut at_end = false; - match parse_item(self, &mut at_end) { + match parse_item(self) { Ok(None) => { // We have to bail or we'll potentially never make progress. let non_item_span = self.token.span; @@ -543,11 +529,11 @@ impl<'a> Parser<'a> { } Ok(Some(item)) => items.extend(item), Err(mut err) => { - err.emit(); - if !at_end { - self.consume_block(token::Brace, ConsumeClosingDelim::Yes); - break; - } + self.consume_block(token::Brace, ConsumeClosingDelim::Yes); + err.span_label(open_brace_span, "while parsing this item list starting here") + .span_label(self.prev_span, "the item list ends here") + .emit(); + break; } } } @@ -644,103 +630,69 @@ impl<'a> Parser<'a> { } else { // It's a normal trait. tps.where_clause = self.parse_where_clause()?; - let items = self.parse_item_list(attrs, |p, at_end| { - p.parse_trait_item(at_end).map(Some).map(Some) - })?; + let items = self.parse_item_list(attrs, |p| p.parse_trait_item())?; Ok((ident, ItemKind::Trait(is_auto, unsafety, tps, bounds, items))) } } - pub fn parse_impl_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { - maybe_whole!(self, NtImplItem, |x| x); - self.parse_assoc_item(at_end, |_| true) + pub fn parse_impl_item(&mut self) -> PResult<'a, Option>>> { + maybe_whole!(self, NtImplItem, |x| Some(Some(x))); + self.parse_assoc_item(|_| true) } - pub fn parse_trait_item(&mut self, at_end: &mut bool) -> PResult<'a, P> { - maybe_whole!(self, NtTraitItem, |x| x); + pub fn parse_trait_item(&mut self) -> PResult<'a, Option>>> { + maybe_whole!(self, NtTraitItem, |x| Some(Some(x))); // This is somewhat dubious; We don't want to allow // param names to be left off if there is a definition... // // We don't allow param names to be left off in edition 2018. - self.parse_assoc_item(at_end, |t| t.span.rust_2018()) + self.parse_assoc_item(|t| t.span.rust_2018()) } /// Parses associated items. - fn parse_assoc_item( - &mut self, - at_end: &mut bool, - req_name: ReqName, - ) -> PResult<'a, P> { + fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { let attrs = self.parse_outer_attributes()?; let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_assoc_item_(at_end, attrs, req_name); + let item = this.parse_assoc_item_(attrs, req_name); unclosed_delims.append(&mut this.unclosed_delims); item })?; self.unclosed_delims.append(&mut unclosed_delims); // See `parse_item` for why this clause is here. - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - self.error_on_assoc_static(&item); - Ok(P(item)) - } - - fn error_on_assoc_static(&self, item: &AssocItem) { - if let AssocItemKind::Static(..) = item.kind { - self.struct_span_err(item.span, "associated `static` items are not allowed").emit(); + if let Some(Some(item)) = &mut item { + if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { + item.tokens = Some(tokens); + } } + Ok(item) } fn parse_assoc_item_( &mut self, - at_end: &mut bool, - mut attrs: Vec, - req_name: ReqName, - ) -> PResult<'a, AssocItem> { - let lo = self.token.span; - let vis = self.parse_visibility(FollowedByType::No)?; - let defaultness = self.parse_defaultness(); - let (ident, kind) = self.parse_assoc_item_kind(at_end, &mut attrs, req_name, &vis)?; - let span = lo.to(self.prev_span); - let id = DUMMY_NODE_ID; - Ok(AssocItem { id, span, ident, attrs, vis, defaultness, kind, tokens: None }) - } - - fn parse_assoc_item_kind( - &mut self, - at_end: &mut bool, - attrs: &mut Vec, + attrs: Vec, req_name: ReqName, - vis: &Visibility, - ) -> PResult<'a, (Ident, AssocItemKind)> { - if self.eat_keyword(kw::Type) { - match self.parse_type_alias()? { - (ident, ItemKind::TyAlias(a, b, c)) => Ok((ident, AssocItemKind::TyAlias(a, b, c))), - _ => unreachable!(), - } - } else if self.check_fn_front_matter() { - let (ident, sig, generics, body) = self.parse_fn(at_end, attrs, req_name)?; - Ok((ident, AssocItemKind::Fn(sig, generics, body))) - } else if self.is_static_global() { - self.bump(); // `static` - let mutbl = self.parse_mutability(); - let (ident, ty, expr) = self.parse_item_const_common(Some(mutbl))?; - Ok((ident, AssocItemKind::Static(ty, mutbl, expr))) - } else if self.eat_keyword(kw::Const) { - let (ident, ty, expr) = self.parse_item_const_common(None)?; - Ok((ident, AssocItemKind::Const(ty, expr))) - } else if self.isnt_macro_invocation() { - Err(self.missing_nested_item_kind_err(self.prev_span)) - } else if self.token.is_path_start() { - let mac = self.parse_item_macro(&vis)?; - *at_end = true; - Ok((Ident::invalid(), AssocItemKind::Macro(mac))) - } else { - self.recover_attrs_no_item(attrs)?; - self.unexpected() - } + ) -> PResult<'a, Option>>> { + let it = self.parse_item_common(attrs, true, false, req_name)?; + Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { + let kind = match kind { + ItemKind::Mac(a) => AssocItemKind::Macro(a), + ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), + ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), + ItemKind::Const(a, c) => AssocItemKind::Const(a, c), + ItemKind::Static(a, _, b) => { + self.struct_span_err(span, "associated `static` items are not allowed").emit(); + AssocItemKind::Const(a, b) + } + _ => { + let span = self.sess.source_map().def_span(span); + self.struct_span_err(span, "item kind not supported in `trait` or `impl`") + .emit(); + return None; + } + }; + Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) + })) } /// Parses a `type` alias with the following grammar: @@ -907,7 +859,7 @@ impl<'a> Parser<'a> { /// ``` fn parse_item_foreign_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let abi = self.parse_abi(); // ABI? - let items = self.parse_item_list(attrs, |p, _| p.parse_foreign_item())?; + let items = self.parse_item_list(attrs, |p| p.parse_foreign_item())?; let module = ast::ForeignMod { abi, items }; Ok((Ident::invalid(), ItemKind::ForeignMod(module))) } @@ -917,17 +869,17 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); let attrs = self.parse_outer_attributes()?; - let it = self.parse_item_common(attrs, true, false)?; + let it = self.parse_item_common(attrs, true, false, |_| true)?; Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { self.error_on_illegal_default(defaultness); let kind = match kind { - ItemKind::Mac(a) => AssocItemKind::Macro(a), - ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), - ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), - ItemKind::Static(a, b, c) => AssocItemKind::Static(a, b, c), + ItemKind::Mac(a) => ForeignItemKind::Macro(a), + ItemKind::Fn(a, b, c) => ForeignItemKind::Fn(a, b, c), + ItemKind::TyAlias(a, b, c) => ForeignItemKind::TyAlias(a, b, c), + ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), ItemKind::Const(a, b) => { self.error_on_foreign_const(span, ident); - AssocItemKind::Static(a, Mutability::Not, b) + ForeignItemKind::Static(a, Mutability::Not, b) } _ => { let span = self.sess.source_map().def_span(span); @@ -989,22 +941,6 @@ impl<'a> Parser<'a> { /// /// When `m` is `"const"`, `$ident` may also be `"_"`. fn parse_item_const(&mut self, m: Option) -> PResult<'a, ItemInfo> { - let (id, ty, expr) = self.parse_item_const_common(m)?; - let item = match m { - Some(m) => ItemKind::Static(ty, m, expr), - None => ItemKind::Const(ty, expr), - }; - Ok((id, item)) - } - - /// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with - /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. - /// - /// When `m` is `"const"`, `$ident` may also be `"_"`. - fn parse_item_const_common( - &mut self, - m: Option, - ) -> PResult<'a, (Ident, P, Option>)> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; // Parse the type of a `const` or `static mut?` item. @@ -1017,7 +953,12 @@ impl<'a> Parser<'a> { let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - Ok((id, ty, expr)) + + let item = match m { + Some(m) => ItemKind::Static(ty, m, expr), + None => ItemKind::Const(ty, expr), + }; + Ok((id, item)) } /// We were supposed to parse `:` but the `:` was missing. @@ -1477,19 +1418,6 @@ impl<'a> Parser<'a> { } Ok(true) } - - fn mk_item( - &self, - lo: Span, - ident: Ident, - kind: K, - vis: Visibility, - defaultness: Defaultness, - attrs: Vec, - ) -> Item { - let span = lo.to(self.prev_span); - Item { ident, attrs, id: DUMMY_NODE_ID, kind, vis, defaultness, span, tokens: None } - } } /// The parsing configuration used to parse a parameter list (see `parse_fn_params`). diff --git a/src/test/ui/async-await/no-unsafe-async.stderr b/src/test/ui/async-await/no-unsafe-async.stderr index 2651588d597..c97b4ff0f49 100644 --- a/src/test/ui/async-await/no-unsafe-async.stderr +++ b/src/test/ui/async-await/no-unsafe-async.stderr @@ -1,8 +1,13 @@ error: expected one of `extern` or `fn`, found keyword `async` --> $DIR/no-unsafe-async.rs:7:12 | +LL | impl S { + | - while parsing this item list starting here +LL | #[cfg(FALSE)] LL | unsafe async fn g() {} | ^^^^^ expected one of `extern` or `fn` +LL | } + | - the item list ends here error: expected one of `extern` or `fn`, found keyword `async` --> $DIR/no-unsafe-async.rs:11:8 diff --git a/src/test/ui/did_you_mean/issue-40006.rs b/src/test/ui/did_you_mean/issue-40006.rs index 2ed682cea95..74f304d81a0 100644 --- a/src/test/ui/did_you_mean/issue-40006.rs +++ b/src/test/ui/did_you_mean/issue-40006.rs @@ -1,28 +1,28 @@ -impl dyn A { //~ ERROR missing +impl dyn A { Y -} +} //~ ERROR expected one of `!` or `::`, found `}` struct S; -trait X { //~ ERROR missing - X() {} +trait X { + X() {} //~ ERROR expected one of `!` or `::`, found `(` fn xxx() { ### } L = M; Z = { 2 + 3 }; ::Y (); } -trait A { //~ ERROR missing - X() {} +trait A { + X() {} //~ ERROR expected one of `!` or `::`, found `(` } trait B { fn xxx() { ### } //~ ERROR expected } -trait C { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration - L = M; +trait C { + L = M; //~ ERROR expected one of `!` or `::`, found `=` } -trait D { //~ ERROR missing `fn`, `type`, `const`, or `static` for item declaration - Z = { 2 + 3 }; +trait D { + Z = { 2 + 3 }; //~ ERROR expected one of `!` or `::`, found `=` } trait E { ::Y (); //~ ERROR expected one of diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 119e30a3e0f..613d7eee594 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,26 +1,36 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-40006.rs:1:13 +error: expected one of `!` or `::`, found `}` + --> $DIR/issue-40006.rs:3:1 | -LL | impl dyn A { - | _____________^ -LL | | Y - | |____^ missing `fn`, `type`, `const`, or `static` +LL | impl dyn A { + | - while parsing this item list starting here +LL | Y + | - expected one of `!` or `::` +LL | } + | ^ + | | + | unexpected token + | the item list ends here -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-40006.rs:7:10 +error: expected one of `!` or `::`, found `(` + --> $DIR/issue-40006.rs:8:6 | -LL | trait X { - | __________^ -LL | | X() {} - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait X { + | - while parsing this item list starting here +LL | X() {} + | ^ expected one of `!` or `::` +... +LL | } + | - the item list ends here -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-40006.rs:15:10 +error: expected one of `!` or `::`, found `(` + --> $DIR/issue-40006.rs:16:6 | -LL | trait A { - | __________^ -LL | | X() {} - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait A { + | - while parsing this item list starting here +LL | X() {} + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here error: expected `[`, found `#` --> $DIR/issue-40006.rs:19:17 @@ -28,33 +38,51 @@ error: expected `[`, found `#` LL | fn xxx() { ### } | ^ expected `[` -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-40006.rs:21:10 +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-40006.rs:22:7 | -LL | trait C { - | __________^ -LL | | L = M; - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait C { + | - while parsing this item list starting here +LL | L = M; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-40006.rs:24:10 +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-40006.rs:25:7 | -LL | trait D { - | __________^ -LL | | Z = { 2 + 3 }; - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait D { + | - while parsing this item list starting here +LL | Z = { 2 + 3 }; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here error: expected one of `!` or `::`, found `(` --> $DIR/issue-40006.rs:28:9 | +LL | trait E { + | - while parsing this item list starting here LL | ::Y (); | ^ expected one of `!` or `::` +LL | } + | - the item list ends here -error: missing `fn`, `type`, `const`, or `static` for item declaration +error: missing `fn` for method definition --> $DIR/issue-40006.rs:32:8 | +LL | impl S { + | - while parsing this item list starting here LL | pub hello_method(&self) { - | ^ missing `fn`, `type`, `const`, or `static` + | ^ +... +LL | } + | - the item list ends here + | +help: add `fn` here to parse `hello_method` as a public method + | +LL | pub fn hello_method(&self) { + | ^^ error[E0599]: no method named `hello_method` found for struct `S` in the current scope --> $DIR/issue-40006.rs:38:7 diff --git a/src/test/ui/generic-associated-types/empty_generics.stderr b/src/test/ui/generic-associated-types/empty_generics.stderr index d3acad47831..bd5708d8140 100644 --- a/src/test/ui/generic-associated-types/empty_generics.stderr +++ b/src/test/ui/generic-associated-types/empty_generics.stderr @@ -1,8 +1,13 @@ error: expected one of `>`, `const`, identifier, or lifetime, found `,` --> $DIR/empty_generics.rs:5:14 | +LL | trait Foo { + | - while parsing this item list starting here LL | type Bar<,>; | ^ expected one of `>`, `const`, identifier, or lifetime +LL | +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/issues/issue-58856-1.stderr b/src/test/ui/issues/issue-58856-1.stderr index 0ea6b017548..a8db8e8b41a 100644 --- a/src/test/ui/issues/issue-58856-1.stderr +++ b/src/test/ui/issues/issue-58856-1.stderr @@ -9,8 +9,14 @@ LL | fn b(self> error: expected `;` or `{`, found `>` --> $DIR/issue-58856-1.rs:3:14 | +LL | impl A { + | - while parsing this item list starting here +LL | LL | fn b(self> | ^ expected `;` or `{` +... +LL | } + | - the item list ends here error[E0412]: cannot find type `A` in this scope --> $DIR/issue-58856-1.rs:1:6 diff --git a/src/test/ui/issues/issue-58856-2.rs b/src/test/ui/issues/issue-58856-2.rs index 745f0300bd5..9356d57b0e5 100644 --- a/src/test/ui/issues/issue-58856-2.rs +++ b/src/test/ui/issues/issue-58856-2.rs @@ -9,6 +9,6 @@ impl Howness for () { Empty } } -//~^ ERROR expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, +//~^ ERROR non-item in item list fn main() {} diff --git a/src/test/ui/issues/issue-58856-2.stderr b/src/test/ui/issues/issue-58856-2.stderr index f4ca3c46ea2..303b5eacc32 100644 --- a/src/test/ui/issues/issue-58856-2.stderr +++ b/src/test/ui/issues/issue-58856-2.stderr @@ -7,13 +7,17 @@ LL | fn how_are_you(&self -> Empty { | | help: `)` may belong here | unclosed delimiter -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `)` +error: non-item in item list --> $DIR/issue-58856-2.rs:11:1 | -LL | } - | - expected one of 12 possible tokens +LL | impl Howness for () { + | - item list starts here +... LL | } - | ^ unexpected token + | ^ + | | + | non-item starts here + | item list ends here error[E0407]: method `how_are_you` is not a member of trait `Howness` --> $DIR/issue-58856-2.rs:6:5 diff --git a/src/test/ui/issues/issue-60075.rs b/src/test/ui/issues/issue-60075.rs index 1323f646be8..e89d78ee8a6 100644 --- a/src/test/ui/issues/issue-60075.rs +++ b/src/test/ui/issues/issue-60075.rs @@ -4,7 +4,8 @@ trait T { fn qux() -> Option { let _ = if true { }); -//~^ ERROR expected one of `async` -//~| ERROR expected one of `.`, `;`, `?`, `else`, or an operator, found `}` +//~^ ERROR non-item in item list +//~| ERROR mismatched closing delimiter: `)` +//~| ERROR expected one of `.`, `;` Some(4) } diff --git a/src/test/ui/issues/issue-60075.stderr b/src/test/ui/issues/issue-60075.stderr index bab50a53b1a..e3b7f4ad420 100644 --- a/src/test/ui/issues/issue-60075.stderr +++ b/src/test/ui/issues/issue-60075.stderr @@ -4,14 +4,26 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `}` LL | }); | ^ expected one of `.`, `;`, `?`, `else`, or an operator -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `;` +error: non-item in item list --> $DIR/issue-60075.rs:6:11 | +LL | trait T { + | - item list starts here +... +LL | }); + | ^ non-item starts here +... +LL | } + | - item list ends here + +error: mismatched closing delimiter: `)` + --> $DIR/issue-60075.rs:6:10 + | LL | fn qux() -> Option { | - unclosed delimiter LL | let _ = if true { LL | }); - | ^ help: `}` may belong here + | ^ mismatched closing delimiter -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs index cf3debd77cb..da4015a4620 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.rs +++ b/src/test/ui/parser/assoc-static-semantic-fail.rs @@ -10,10 +10,12 @@ impl S { //~^ ERROR associated `static` items are not allowed static IB: u8; //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body default static IC: u8 = 0; //~^ ERROR associated `static` items are not allowed pub(crate) default static ID: u8; //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body } trait T { @@ -35,9 +37,11 @@ impl T for S { //~^ ERROR associated `static` items are not allowed static TB: u8; //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body default static TC: u8 = 0; //~^ ERROR associated `static` items are not allowed pub default static TD: u8; //~^ ERROR associated `static` items are not allowed + //~| ERROR associated constant in `impl` without body //~| ERROR unnecessary visibility qualifier } diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr index dfd0053fda2..ca05b05e9b1 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.stderr +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -11,67 +11,83 @@ LL | static IB: u8; | ^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:13:5 + --> $DIR/assoc-static-semantic-fail.rs:14:5 | LL | default static IC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:15:5 + --> $DIR/assoc-static-semantic-fail.rs:16:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:20:5 + --> $DIR/assoc-static-semantic-fail.rs:22:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:22:5 + --> $DIR/assoc-static-semantic-fail.rs:24:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:24:5 + --> $DIR/assoc-static-semantic-fail.rs:26:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:27:5 + --> $DIR/assoc-static-semantic-fail.rs:29:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:34:5 + --> $DIR/assoc-static-semantic-fail.rs:36:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:36:5 + --> $DIR/assoc-static-semantic-fail.rs:38:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:38:5 + --> $DIR/assoc-static-semantic-fail.rs:41:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:40:5 + --> $DIR/assoc-static-semantic-fail.rs:43:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:11:5 + | +LL | static IB: u8; + | ^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:16:5 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:24:5 + --> $DIR/assoc-static-semantic-fail.rs:26:5 | LL | default static TC: u8 = 0; | -------^^^^^^^^^^^^^^^^^^^ @@ -79,7 +95,7 @@ LL | default static TC: u8 = 0; | `default` because of this error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:27:5 + --> $DIR/assoc-static-semantic-fail.rs:29:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^^-------^^^^^^^^^^^^^^^ @@ -87,17 +103,33 @@ LL | pub(crate) default static TD: u8; | `default` because of this error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:27:5 + --> $DIR/assoc-static-semantic-fail.rs:29:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^ +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:38:5 + | +LL | static TB: u8; + | ^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + +error: associated constant in `impl` without body + --> $DIR/assoc-static-semantic-fail.rs:43:5 + | +LL | pub default static TD: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:40:5 + --> $DIR/assoc-static-semantic-fail.rs:43:5 | LL | pub default static TD: u8; | ^^^ `pub` not permitted here because it's implied -error: aborting due to 16 previous errors +error: aborting due to 20 previous errors For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/attrs-after-extern-mod.stderr b/src/test/ui/parser/attrs-after-extern-mod.stderr index 6060f3afe1e..3862f5c379f 100644 --- a/src/test/ui/parser/attrs-after-extern-mod.stderr +++ b/src/test/ui/parser/attrs-after-extern-mod.stderr @@ -1,8 +1,12 @@ error: expected item after attributes --> $DIR/attrs-after-extern-mod.rs:6:5 | +LL | extern { + | - while parsing this item list starting here LL | #[cfg(stage37)] | ^^^^^^^^^^^^^^^ +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 0fe20473587..16bb7735c90 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -60,3 +60,73 @@ extern "C" { default macro_rules! foo {} //~ ERROR item cannot be `default` //~^ ERROR item kind not supported in `extern` block } + +#[cfg(FALSE)] +impl S { + default extern crate foo; + //~^ ERROR item kind not supported in `trait` or `impl` + default use foo; + //~^ ERROR item kind not supported in `trait` or `impl` + default static foo: u8; + //~^ ERROR associated `static` items are not allowed + default const foo: u8; + default fn foo(); + default mod foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default extern "C" {} + //~^ ERROR item kind not supported in `trait` or `impl` + default type foo = u8; + default enum foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default struct foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default union foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default trait foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default trait foo = Ord; + //~^ ERROR item kind not supported in `trait` or `impl` + default impl foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default!(); + default::foo::bar!(); + default macro foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default macro_rules! foo {} + //~^ ERROR item kind not supported in `trait` or `impl` +} + +#[cfg(FALSE)] +trait T { + default extern crate foo; + //~^ ERROR item kind not supported in `trait` or `impl` + default use foo; + //~^ ERROR item kind not supported in `trait` or `impl` + default static foo: u8; + //~^ ERROR associated `static` items are not allowed + default const foo: u8; + default fn foo(); + default mod foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default extern "C" {} + //~^ ERROR item kind not supported in `trait` or `impl` + default type foo = u8; + default enum foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default struct foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default union foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default trait foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default trait foo = Ord; + //~^ ERROR item kind not supported in `trait` or `impl` + default impl foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default!(); + default::foo::bar!(); + default macro foo {} + //~^ ERROR item kind not supported in `trait` or `impl` + default macro_rules! foo {} + //~^ ERROR item kind not supported in `trait` or `impl` +} diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index e089bbbddde..1812c45eba6 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -320,5 +320,161 @@ error: item kind not supported in `extern` block LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 43 previous errors +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:66:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:68:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/default-on-wrong-item-kind.rs:70:5 + | +LL | default static foo: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:74:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:76:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:79:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:81:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:83:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:85:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:87:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:89:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:93:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:95:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:101:5 + | +LL | default extern crate foo; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:103:5 + | +LL | default use foo; + | ^^^^^^^^^^^^^^^^ + +error: associated `static` items are not allowed + --> $DIR/default-on-wrong-item-kind.rs:105:5 + | +LL | default static foo: u8; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:109:5 + | +LL | default mod foo {} + | ^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:111:5 + | +LL | default extern "C" {} + | ^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:114:5 + | +LL | default enum foo {} + | ^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:116:5 + | +LL | default struct foo {} + | ^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:118:5 + | +LL | default union foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:120:5 + | +LL | default trait foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:122:5 + | +LL | default trait foo = Ord; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:124:5 + | +LL | default impl foo {} + | ^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:128:5 + | +LL | default macro foo {} + | ^^^^^^^^^^^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/default-on-wrong-item-kind.rs:130:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 69 previous errors diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs new file mode 100644 index 00000000000..bca6f5654db --- /dev/null +++ b/src/test/ui/parser/default-unmatched-assoc.rs @@ -0,0 +1,16 @@ +fn main() {} + +trait Foo { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR unmatched `default` + //~| ERROR non-item in item list +} + +struct S; +impl S { + default!(); //~ ERROR cannot find macro `default` in this scope + default do + //~^ ERROR unmatched `default` + //~| ERROR non-item in item list +} diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr new file mode 100644 index 00000000000..f3877f2ca6d --- /dev/null +++ b/src/test/ui/parser/default-unmatched-assoc.stderr @@ -0,0 +1,50 @@ +error: unmatched `default` + --> $DIR/default-unmatched-assoc.rs:5:5 + | +LL | default do + | ^^^^^^^ the unmatched `default` + +error: non-item in item list + --> $DIR/default-unmatched-assoc.rs:5:13 + | +LL | trait Foo { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: unmatched `default` + --> $DIR/default-unmatched-assoc.rs:13:5 + | +LL | default do + | ^^^^^^^ the unmatched `default` + +error: non-item in item list + --> $DIR/default-unmatched-assoc.rs:13:13 + | +LL | impl S { + | - item list starts here +LL | default!(); +LL | default do + | ^^ non-item starts here +... +LL | } + | - item list ends here + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-assoc.rs:12:5 + | +LL | default!(); + | ^^^^^^^ + +error: cannot find macro `default` in this scope + --> $DIR/default-unmatched-assoc.rs:4:5 + | +LL | default!(); + | ^^^^^^^ + +error: aborting due to 6 previous errors + diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 50952eef22f..bd9ed0f4524 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -20,7 +20,8 @@ impl Foo for u16 { impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` default pub fn foo() -> T { T::default() } - //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration + //~^ ERROR unmatched `default` + //~| ERROR non-item in item list } fn main() {} diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index 07b051ece2b..fbf8101c36a 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,19 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/default.rs:22:12 +error: unmatched `default` + --> $DIR/default.rs:22:5 | LL | default pub fn foo() -> T { T::default() } - | ^ missing `fn`, `type`, `const`, or `static` + | ^^^^^^^ the unmatched `default` + +error: non-item in item list + --> $DIR/default.rs:22:13 + | +LL | impl Foo for u32 { + | - item list starts here +LL | default pub fn foo() -> T { T::default() } + | ^^^ non-item starts here +... +LL | } + | - item list ends here error[E0449]: unnecessary visibility qualifier --> $DIR/default.rs:16:5 @@ -19,7 +30,7 @@ LL | fn foo() -> T; LL | impl Foo for u32 { | ^^^^^^^^^^^^^^^^ missing `foo` in implementation -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0046, E0449. For more information about an error, try `rustc --explain E0046`. diff --git a/src/test/ui/parser/extern-no-fn.stderr b/src/test/ui/parser/extern-no-fn.stderr index 02320125014..0151cb4235b 100644 --- a/src/test/ui/parser/extern-no-fn.stderr +++ b/src/test/ui/parser/extern-no-fn.stderr @@ -1,8 +1,12 @@ error: expected one of `!` or `::`, found `(` --> $DIR/extern-no-fn.rs:2:6 | +LL | extern { + | - while parsing this item list starting here LL | f(); | ^ expected one of `!` or `::` +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-19398.rs b/src/test/ui/parser/issue-19398.rs index 014c930ef82..46eb320a172 100644 --- a/src/test/ui/parser/issue-19398.rs +++ b/src/test/ui/parser/issue-19398.rs @@ -1,6 +1,6 @@ trait T { - //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration extern "Rust" unsafe fn foo(); + //~^ ERROR expected `{`, found keyword `unsafe` } fn main() {} diff --git a/src/test/ui/parser/issue-19398.stderr b/src/test/ui/parser/issue-19398.stderr index b38b39f9bd9..1da00960adf 100644 --- a/src/test/ui/parser/issue-19398.stderr +++ b/src/test/ui/parser/issue-19398.stderr @@ -1,11 +1,13 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-19398.rs:1:10 +error: expected `{`, found keyword `unsafe` + --> $DIR/issue-19398.rs:2:19 | -LL | trait T { - | __________^ -LL | | -LL | | extern "Rust" unsafe fn foo(); - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait T { + | - while parsing this item list starting here +LL | extern "Rust" unsafe fn foo(); + | ^^^^^^ expected `{` +LL | +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711-2.stderr b/src/test/ui/parser/issue-20711-2.stderr index 10ef31584de..12b18bbc594 100644 --- a/src/test/ui/parser/issue-20711-2.stderr +++ b/src/test/ui/parser/issue-20711-2.stderr @@ -1,8 +1,14 @@ error: expected item after attributes --> $DIR/issue-20711-2.rs:6:5 | +LL | impl Foo { + | - while parsing this item list starting here +... LL | #[stable(feature = "rust1", since = "1.0.0")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-20711.stderr b/src/test/ui/parser/issue-20711.stderr index 66768de5694..4af4b22bee2 100644 --- a/src/test/ui/parser/issue-20711.stderr +++ b/src/test/ui/parser/issue-20711.stderr @@ -1,8 +1,13 @@ error: expected item after attributes --> $DIR/issue-20711.rs:4:5 | +LL | impl Foo { + | - while parsing this item list starting here LL | #[stable(feature = "rust1", since = "1.0.0")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-21153.rs b/src/test/ui/parser/issue-21153.rs index 4fe05e6f041..bf5fdb1f3c6 100644 --- a/src/test/ui/parser/issue-21153.rs +++ b/src/test/ui/parser/issue-21153.rs @@ -1,6 +1,6 @@ trait MyTrait: Iterator { - //~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration Item = T; + //~^ ERROR expected one of `!` or `::`, found `=` } fn main() {} diff --git a/src/test/ui/parser/issue-21153.stderr b/src/test/ui/parser/issue-21153.stderr index e9824bd7290..cbfa9ded3c3 100644 --- a/src/test/ui/parser/issue-21153.stderr +++ b/src/test/ui/parser/issue-21153.stderr @@ -1,11 +1,13 @@ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/issue-21153.rs:1:29 +error: expected one of `!` or `::`, found `=` + --> $DIR/issue-21153.rs:2:10 | -LL | trait MyTrait: Iterator { - | _____________________________^ -LL | | -LL | | Item = T; - | |____^ missing `fn`, `type`, `const`, or `static` +LL | trait MyTrait: Iterator { + | - while parsing this item list starting here +LL | Item = T; + | ^ expected one of `!` or `::` +LL | +LL | } + | - the item list ends here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-32446.stderr b/src/test/ui/parser/issue-32446.stderr index d25828da0b9..7515369aaa0 100644 --- a/src/test/ui/parser/issue-32446.stderr +++ b/src/test/ui/parser/issue-32446.stderr @@ -1,8 +1,11 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, `}`, or identifier, found `...` +error: non-item in item list --> $DIR/issue-32446.rs:4:11 | LL | trait T { ... } - | ^^^ expected one of 12 possible tokens + | - ^^^ - item list ends here + | | | + | | non-item starts here + | item list starts here error: aborting due to previous error diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs index 3c24d2b447d..bed4805e7ce 100644 --- a/src/test/ui/parser/issue-41155.rs +++ b/src/test/ui/parser/issue-41155.rs @@ -1,7 +1,7 @@ struct S; impl S { - pub -} //~ ERROR expected one of + pub //~ ERROR unmatched visibility `pub` +} //~ ERROR non-item in item list fn main() {} diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index a91ef6c67e8..a9c1035f4d8 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,10 +1,22 @@ -error: expected one of `(`, `async`, `const`, `default`, `extern`, `fn`, `static`, `type`, `unsafe`, or identifier, found `}` +error: unmatched visibility `pub` + --> $DIR/issue-41155.rs:4:5 + | +LL | pub + | ^^^ the unmatched visibility + | + = help: you likely meant to define an item, e.g., `pub fn foo() {}` + +error: non-item in item list --> $DIR/issue-41155.rs:5:1 | +LL | impl S { + | - item list starts here LL | pub - | - expected one of 10 possible tokens LL | } - | ^ unexpected token + | ^ + | | + | non-item starts here + | item list ends here -error: aborting due to previous error +error: aborting due to 2 previous errors diff --git a/src/test/ui/parser/issue-6610.stderr b/src/test/ui/parser/issue-6610.stderr index 22d93bffead..a9804208946 100644 --- a/src/test/ui/parser/issue-6610.stderr +++ b/src/test/ui/parser/issue-6610.stderr @@ -2,7 +2,11 @@ error: expected `;` or `{`, found `}` --> $DIR/issue-6610.rs:1:20 | LL | trait Foo { fn a() } - | ^ expected `;` or `{` + | - ^ + | | | + | | expected `;` or `{` + | | the item list ends here + | while parsing this item list starting here error: aborting due to previous error diff --git a/src/test/ui/parser/macro/trait-non-item-macros.rs b/src/test/ui/parser/macro/trait-non-item-macros.rs index 5021886bf98..97fb564bf64 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.rs +++ b/src/test/ui/parser/macro/trait-non-item-macros.rs @@ -1,10 +1,13 @@ macro_rules! bah { - ($a:expr) => ($a) - //~^ ERROR expected one of `async` + ($a:expr) => { + $a + }; //~^ ERROR macro expansion ignores token `2` and any following } -trait bar { +trait Bar { bah!(2); } -fn main() {} +fn main() { + let _recovery_witness: () = 0; //~ ERROR mismatched types +} diff --git a/src/test/ui/parser/macro/trait-non-item-macros.stderr b/src/test/ui/parser/macro/trait-non-item-macros.stderr index c76b096a1eb..35e5bfe62f5 100644 --- a/src/test/ui/parser/macro/trait-non-item-macros.stderr +++ b/src/test/ui/parser/macro/trait-non-item-macros.stderr @@ -1,13 +1,22 @@ -error: expected one of `async`, `const`, `crate`, `default`, `extern`, `fn`, `pub`, `static`, `type`, `unsafe`, or identifier, found `2` - --> $DIR/trait-non-item-macros.rs:2:19 +error: macro expansion ignores token `2` and any following + --> $DIR/trait-non-item-macros.rs:3:9 | -LL | ($a:expr) => ($a) - | ^^ expected one of 11 possible tokens +LL | $a + | ^^ ... LL | bah!(2); - | -------- in this macro invocation + | -------- caused by the macro expansion here | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + = note: the usage of `bah!` is likely invalid in trait item context -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/trait-non-item-macros.rs:12:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index 748db8983b5..d85255328f7 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -3,12 +3,11 @@ fn main() {} impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} -//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration -trait T { +trait T { //~ ERROR item kind not supported in `trait` or `impl` fn foo(&self); } -pub(crate) struct Bar(); +pub(crate) struct Bar(); //~ ERROR item kind not supported in `trait` or `impl` //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index 240be39eace..2b72c06c9c7 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -1,5 +1,5 @@ error: this file contains an unclosed delimiter - --> $DIR/missing-close-brace-in-impl-trait.rs:14:52 + --> $DIR/missing-close-brace-in-impl-trait.rs:13:52 | LL | impl T for () { | - unclosed delimiter @@ -7,15 +7,17 @@ LL | impl T for () { LL | | ^ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/missing-close-brace-in-impl-trait.rs:5:17 +error: item kind not supported in `trait` or `impl` + --> $DIR/missing-close-brace-in-impl-trait.rs:7:1 | -LL | fn foo(&self) {} - | _________________^ -LL | | -LL | | -LL | | trait T { - | |_ missing `fn`, `type`, `const`, or `static` +LL | trait T { + | ^^^^^^^ + +error: item kind not supported in `trait` or `impl` + --> $DIR/missing-close-brace-in-impl-trait.rs:11:1 + | +LL | pub(crate) struct Bar(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0405]: cannot find trait `T` in this scope --> $DIR/missing-close-brace-in-impl-trait.rs:3:6 @@ -23,6 +25,6 @@ error[E0405]: cannot find trait `T` in this scope LL | impl T for () { | ^ not found in this scope -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0405`. diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index 4e8cc6489bc..b2515b17ff3 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -1,11 +1,11 @@ trait T { -//~^ ERROR `main` function not found in crate `missing_close_brace_in_trait` fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR missing `fn`, `type`, `const`, or `static` for item declaration +//~^ ERROR item kind not supported in `trait` or `impl` impl T for Bar { +//~^ ERROR item kind not supported in `trait` or `impl` fn foo(&self) {} } diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 54afad5755b..89bf2916510 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,24 +7,17 @@ LL | trait T { LL | fn main() {} | ^ -error: missing `fn`, `type`, `const`, or `static` for item declaration - --> $DIR/missing-close-brace-in-trait.rs:5:11 +error: item kind not supported in `trait` or `impl` + --> $DIR/missing-close-brace-in-trait.rs:4:1 | LL | pub(crate) struct Bar(); - | ^ missing `fn`, `type`, `const`, or `static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0601]: `main` function not found in crate `missing_close_brace_in_trait` - --> $DIR/missing-close-brace-in-trait.rs:1:1 +error: item kind not supported in `trait` or `impl` + --> $DIR/missing-close-brace-in-trait.rs:7:1 | -LL | / trait T { -LL | | -LL | | fn foo(&self); -LL | | -... | -LL | | -LL | | fn main() {} - | |________________________________________________________________^ consider adding a `main` function to `$DIR/missing-close-brace-in-trait.rs` +LL | impl T for Bar { + | ^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0601`. diff --git a/src/test/ui/parser/removed-syntax-static-fn.stderr b/src/test/ui/parser/removed-syntax-static-fn.stderr index dc5625bdade..04e34dc16a8 100644 --- a/src/test/ui/parser/removed-syntax-static-fn.stderr +++ b/src/test/ui/parser/removed-syntax-static-fn.stderr @@ -7,8 +7,13 @@ LL | static fn f() {} error: expected one of `:`, `;`, or `=`, found `f` --> $DIR/removed-syntax-static-fn.rs:4:15 | +LL | impl S { + | - while parsing this item list starting here LL | static fn f() {} | ^ expected one of `:`, `;`, or `=` +... +LL | } + | - the item list ends here error: missing type for `static` item --> $DIR/removed-syntax-static-fn.rs:4:12 From a3b08294141bb209f9cd6a0d0b9bf56890edc742 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 08:34:24 +0100 Subject: [PATCH 0473/1250] parse: move token hack into `parse_item_common`. --- src/librustc_parse/parser/item.rs | 86 +++++++++++-------------------- 1 file changed, 31 insertions(+), 55 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 8c5add46bfc..4bb376799ec 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -31,13 +31,33 @@ impl<'a> Parser<'a> { pub(super) fn parse_item_( &mut self, - attrs: Vec, + mut attrs: Vec, macros_allowed: bool, attributes_allowed: bool, ) -> PResult<'a, Option>> { + maybe_whole!(self, NtItem, |item| { + let mut item = item; + mem::swap(&mut item.attrs, &mut attrs); + item.attrs.extend(attrs); + Some(item) + }); + let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; + if let Some(ref item) = item { + self.error_on_illegal_default(item.defaultness); + } + Ok(item.map(P)) + } + + fn parse_item_common( + &mut self, + attrs: Vec, + mac_allowed: bool, + attrs_allowed: bool, + req_name: ReqName, + ) -> PResult<'a, Option> { let mut unclosed_delims = vec![]; - let (ret, tokens) = self.collect_tokens(|this| { - let item = this.parse_item_implementation(attrs, macros_allowed, attributes_allowed); + let (mut item, tokens) = self.collect_tokens(|this| { + let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); unclosed_delims.append(&mut this.unclosed_delims); item })?; @@ -57,38 +77,15 @@ impl<'a> Parser<'a> { // it (bad!). To work around this case for now we just avoid recording // `tokens` if we detect any inner attributes. This should help keep // expansion correct, but we should fix this bug one day! - Ok(ret.map(|item| { - item.map(|mut i| { - if !i.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - i.tokens = Some(tokens); - } - i - }) - })) - } - - /// Parses one of the items allowed by the flags. - fn parse_item_implementation( - &mut self, - mut attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, - ) -> PResult<'a, Option>> { - maybe_whole!(self, NtItem, |item| { - let mut item = item; - mem::swap(&mut item.attrs, &mut attrs); - item.attrs.extend(attrs); - Some(item) - }); - - let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; - if let Some(ref item) = item { - self.error_on_illegal_default(item.defaultness); + if let Some(item) = &mut item { + if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { + item.tokens = Some(tokens); + } } - Ok(item.map(P)) + Ok(item) } - fn parse_item_common( + fn parse_item_common_( &mut self, mut attrs: Vec, mac_allowed: bool, @@ -652,27 +649,6 @@ impl<'a> Parser<'a> { /// Parses associated items. fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { let attrs = self.parse_outer_attributes()?; - let mut unclosed_delims = vec![]; - let (mut item, tokens) = self.collect_tokens(|this| { - let item = this.parse_assoc_item_(attrs, req_name); - unclosed_delims.append(&mut this.unclosed_delims); - item - })?; - self.unclosed_delims.append(&mut unclosed_delims); - // See `parse_item` for why this clause is here. - if let Some(Some(item)) = &mut item { - if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) { - item.tokens = Some(tokens); - } - } - Ok(item) - } - - fn parse_assoc_item_( - &mut self, - attrs: Vec, - req_name: ReqName, - ) -> PResult<'a, Option>>> { let it = self.parse_item_common(attrs, true, false, req_name)?; Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { let kind = match kind { @@ -869,8 +845,8 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); let attrs = self.parse_outer_attributes()?; - let it = self.parse_item_common(attrs, true, false, |_| true)?; - Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { + let item = self.parse_item_common(attrs, true, false, |_| true)?; + Ok(item.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { self.error_on_illegal_default(defaultness); let kind = match kind { ItemKind::Mac(a) => ForeignItemKind::Macro(a), From abc46a579b336f7ac686b8f24c0ff31be8726038 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 08:55:01 +0100 Subject: [PATCH 0474/1250] parse: harden `default` test. --- .../ui/parser/default-on-wrong-item-kind.rs | 8 + .../parser/default-on-wrong-item-kind.stderr | 144 +++++++++++------- 2 files changed, 96 insertions(+), 56 deletions(-) diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 16bb7735c90..0951af1579b 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -22,6 +22,8 @@ mod free_items { default impl foo {} default!(); default::foo::bar!(); + default default!(); //~ ERROR item cannot be `default` + default default::foo::bar!(); //~ ERROR item cannot be `default` default macro foo {} //~ ERROR item cannot be `default` default macro_rules! foo {} //~ ERROR item cannot be `default` } @@ -55,6 +57,8 @@ extern "C" { //~^ ERROR item kind not supported in `extern` block default!(); default::foo::bar!(); + default default!(); //~ ERROR item cannot be `default` + default default::foo::bar!(); //~ ERROR item cannot be `default` default macro foo {} //~ ERROR item cannot be `default` //~^ ERROR item kind not supported in `extern` block default macro_rules! foo {} //~ ERROR item cannot be `default` @@ -90,6 +94,8 @@ impl S { //~^ ERROR item kind not supported in `trait` or `impl` default!(); default::foo::bar!(); + default default!(); + default default::foo::bar!(); default macro foo {} //~^ ERROR item kind not supported in `trait` or `impl` default macro_rules! foo {} @@ -125,6 +131,8 @@ trait T { //~^ ERROR item kind not supported in `trait` or `impl` default!(); default::foo::bar!(); + default default!(); + default default::foo::bar!(); default macro foo {} //~^ ERROR item kind not supported in `trait` or `impl` default macro_rules! foo {} diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index 1812c45eba6..6c4c108a28f 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -105,7 +105,7 @@ LL | default trait foo = Ord; error: item cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:25:5 | -LL | default macro foo {} +LL | default default!(); | ^^^^^^^ `default` because of this | = note: only associated `fn`, `const`, and `type` items can be `default` @@ -113,13 +113,29 @@ LL | default macro foo {} error: item cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:26:5 | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:27:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:28:5 + | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this | = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:31:5 + --> $DIR/default-on-wrong-item-kind.rs:33:5 | LL | default extern crate foo; | ^^^^^^^ `default` because of this @@ -127,13 +143,13 @@ LL | default extern crate foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:31:5 + --> $DIR/default-on-wrong-item-kind.rs:33:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:33:5 + --> $DIR/default-on-wrong-item-kind.rs:35:5 | LL | default use foo; | ^^^^^^^ `default` because of this @@ -141,13 +157,13 @@ LL | default use foo; = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:33:5 + --> $DIR/default-on-wrong-item-kind.rs:35:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:35:5 + --> $DIR/default-on-wrong-item-kind.rs:37:5 | LL | default static foo: u8; | ^^^^^^^ `default` because of this @@ -155,7 +171,7 @@ LL | default static foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:36:5 + --> $DIR/default-on-wrong-item-kind.rs:38:5 | LL | default const foo: u8; | ^^^^^^^ `default` because of this @@ -163,7 +179,7 @@ LL | default const foo: u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: extern items cannot be `const` - --> $DIR/default-on-wrong-item-kind.rs:36:19 + --> $DIR/default-on-wrong-item-kind.rs:38:19 | LL | default const foo: u8; | --------------^^^ @@ -173,7 +189,7 @@ LL | default const foo: u8; = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:38:5 + --> $DIR/default-on-wrong-item-kind.rs:40:5 | LL | default fn foo(); | ^^^^^^^ `default` because of this @@ -181,7 +197,7 @@ LL | default fn foo(); = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:39:5 + --> $DIR/default-on-wrong-item-kind.rs:41:5 | LL | default mod foo {} | ^^^^^^^ `default` because of this @@ -189,13 +205,13 @@ LL | default mod foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:39:5 + --> $DIR/default-on-wrong-item-kind.rs:41:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:41:5 + --> $DIR/default-on-wrong-item-kind.rs:43:5 | LL | default extern "C" {} | ^^^^^^^ `default` because of this @@ -203,13 +219,13 @@ LL | default extern "C" {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:41:5 + --> $DIR/default-on-wrong-item-kind.rs:43:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:43:5 + --> $DIR/default-on-wrong-item-kind.rs:45:5 | LL | default type foo = u8; | ^^^^^^^ `default` because of this @@ -217,7 +233,7 @@ LL | default type foo = u8; = note: only associated `fn`, `const`, and `type` items can be `default` error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:44:5 + --> $DIR/default-on-wrong-item-kind.rs:46:5 | LL | default enum foo {} | ^^^^^^^ `default` because of this @@ -225,13 +241,13 @@ LL | default enum foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:44:5 + --> $DIR/default-on-wrong-item-kind.rs:46:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:46:5 + --> $DIR/default-on-wrong-item-kind.rs:48:5 | LL | default struct foo {} | ^^^^^^^ `default` because of this @@ -239,13 +255,13 @@ LL | default struct foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:46:5 + --> $DIR/default-on-wrong-item-kind.rs:48:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:48:5 + --> $DIR/default-on-wrong-item-kind.rs:50:5 | LL | default union foo {} | ^^^^^^^ `default` because of this @@ -253,13 +269,13 @@ LL | default union foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:48:5 + --> $DIR/default-on-wrong-item-kind.rs:50:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:50:5 + --> $DIR/default-on-wrong-item-kind.rs:52:5 | LL | default trait foo {} | ^^^^^^^ `default` because of this @@ -267,13 +283,13 @@ LL | default trait foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:50:5 + --> $DIR/default-on-wrong-item-kind.rs:52:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:52:5 + --> $DIR/default-on-wrong-item-kind.rs:54:5 | LL | default trait foo = Ord; | ^^^^^^^ `default` because of this @@ -281,19 +297,35 @@ LL | default trait foo = Ord; = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:52:5 + --> $DIR/default-on-wrong-item-kind.rs:54:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:54:5 + --> $DIR/default-on-wrong-item-kind.rs:56:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:58:5 + --> $DIR/default-on-wrong-item-kind.rs:60:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:61:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:62:5 | LL | default macro foo {} | ^^^^^^^ `default` because of this @@ -301,13 +333,13 @@ LL | default macro foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:58:5 + --> $DIR/default-on-wrong-item-kind.rs:62:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:60:5 + --> $DIR/default-on-wrong-item-kind.rs:64:5 | LL | default macro_rules! foo {} | ^^^^^^^ `default` because of this @@ -315,166 +347,166 @@ LL | default macro_rules! foo {} = note: only associated `fn`, `const`, and `type` items can be `default` error: item kind not supported in `extern` block - --> $DIR/default-on-wrong-item-kind.rs:60:5 + --> $DIR/default-on-wrong-item-kind.rs:64:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:66:5 + --> $DIR/default-on-wrong-item-kind.rs:70:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:68:5 + --> $DIR/default-on-wrong-item-kind.rs:72:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/default-on-wrong-item-kind.rs:70:5 + --> $DIR/default-on-wrong-item-kind.rs:74:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:74:5 + --> $DIR/default-on-wrong-item-kind.rs:78:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:76:5 + --> $DIR/default-on-wrong-item-kind.rs:80:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:79:5 + --> $DIR/default-on-wrong-item-kind.rs:83:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:81:5 + --> $DIR/default-on-wrong-item-kind.rs:85:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:83:5 + --> $DIR/default-on-wrong-item-kind.rs:87:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:85:5 + --> $DIR/default-on-wrong-item-kind.rs:89:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:87:5 + --> $DIR/default-on-wrong-item-kind.rs:91:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:89:5 + --> $DIR/default-on-wrong-item-kind.rs:93:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:93:5 + --> $DIR/default-on-wrong-item-kind.rs:99:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:95:5 + --> $DIR/default-on-wrong-item-kind.rs:101:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:101:5 + --> $DIR/default-on-wrong-item-kind.rs:107:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:103:5 + --> $DIR/default-on-wrong-item-kind.rs:109:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/default-on-wrong-item-kind.rs:105:5 + --> $DIR/default-on-wrong-item-kind.rs:111:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:109:5 + --> $DIR/default-on-wrong-item-kind.rs:115:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:111:5 + --> $DIR/default-on-wrong-item-kind.rs:117:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:114:5 + --> $DIR/default-on-wrong-item-kind.rs:120:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:116:5 + --> $DIR/default-on-wrong-item-kind.rs:122:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:118:5 + --> $DIR/default-on-wrong-item-kind.rs:124:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:120:5 + --> $DIR/default-on-wrong-item-kind.rs:126:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:122:5 + --> $DIR/default-on-wrong-item-kind.rs:128:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:124:5 + --> $DIR/default-on-wrong-item-kind.rs:130:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:128:5 + --> $DIR/default-on-wrong-item-kind.rs:136:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ error: item kind not supported in `trait` or `impl` - --> $DIR/default-on-wrong-item-kind.rs:130:5 + --> $DIR/default-on-wrong-item-kind.rs:138:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 69 previous errors +error: aborting due to 73 previous errors From d446c73e6ab94fe37f7d7b8f2abf633ed6344c8a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 22 Feb 2020 10:03:10 +0100 Subject: [PATCH 0475/1250] parser: refactor away at_end --- src/librustc_parse/parser/item.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 4bb376799ec..52619866c4e 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -161,7 +161,7 @@ impl<'a> Parser<'a> { (Ident::invalid(), ItemKind::Use(P(tree))) } else if self.check_fn_front_matter() { // FUNCTION ITEM - let (ident, sig, generics, body) = self.parse_fn(&mut false, attrs, req_name)?; + let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?; (ident, ItemKind::Fn(sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { @@ -1406,7 +1406,6 @@ impl<'a> Parser<'a> { /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`. fn parse_fn( &mut self, - at_end: &mut bool, attrs: &mut Vec, req_name: ReqName, ) -> PResult<'a, (Ident, FnSig, Generics, Option>)> { @@ -1415,18 +1414,14 @@ impl<'a> Parser<'a> { let mut generics = self.parse_generics()?; // `<'a, T, ...>` let decl = self.parse_fn_decl(req_name, AllowPlus::Yes)?; // `(p: u8, ...)` generics.where_clause = self.parse_where_clause()?; // `where T: Ord` - let body = self.parse_fn_body(at_end, attrs)?; // `;` or `{ ... }`. + let body = self.parse_fn_body(attrs)?; // `;` or `{ ... }`. Ok((ident, FnSig { header, decl }, generics, body)) } /// Parse the "body" of a function. /// This can either be `;` when there's no body, /// or e.g. a block when the function is a provided one. - fn parse_fn_body( - &mut self, - at_end: &mut bool, - attrs: &mut Vec, - ) -> PResult<'a, Option>> { + fn parse_fn_body(&mut self, attrs: &mut Vec) -> PResult<'a, Option>> { let (inner_attrs, body) = match self.token.kind { token::Semi => { self.bump(); @@ -1446,7 +1441,6 @@ impl<'a> Parser<'a> { _ => return self.expected_semi_or_open_brace(), }; attrs.extend(inner_attrs); - *at_end = true; Ok(body) } From ab84914fe47aa2da615c9e759e686d1a45f8aae3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 04:49:26 +0100 Subject: [PATCH 0476/1250] parser: tweak unmatched wording --- src/librustc_parse/parser/item.rs | 11 ++++++----- src/test/ui/parser/default-unmatched-assoc.rs | 4 ++-- src/test/ui/parser/default-unmatched-assoc.stderr | 12 ++++++++---- src/test/ui/parser/default-unmatched-extern.rs | 2 +- src/test/ui/parser/default-unmatched-extern.stderr | 6 ++++-- src/test/ui/parser/default-unmatched.rs | 2 +- src/test/ui/parser/default-unmatched.stderr | 6 ++++-- src/test/ui/parser/default.rs | 2 +- src/test/ui/parser/default.stderr | 6 ++++-- src/test/ui/parser/duplicate-visibility.rs | 2 +- src/test/ui/parser/duplicate-visibility.stderr | 4 ++-- src/test/ui/parser/impl-parsing.rs | 2 +- src/test/ui/parser/impl-parsing.stderr | 6 ++++-- src/test/ui/parser/issue-41155.rs | 2 +- src/test/ui/parser/issue-41155.stderr | 4 ++-- src/test/ui/pub/pub-restricted-error-fn.rs | 2 +- src/test/ui/pub/pub-restricted-error-fn.stderr | 4 ++-- 17 files changed, 45 insertions(+), 32 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 52619866c4e..d2073a5473a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -119,17 +119,18 @@ impl<'a> Parser<'a> { } let vs = pprust::vis_to_string(&vis); let vs = vs.trim_end(); - self.struct_span_err(vis.span, &format!("unmatched visibility `{}`", vs)) - .span_label(vis.span, "the unmatched visibility") + self.struct_span_err(vis.span, &format!("visibility `{}` not followed by an item", vs)) + .span_label(vis.span, "the visibility") .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) .emit(); } /// Error in-case a `default` was parsed but no item followed. fn error_on_unmatched_defaultness(&self, def: Defaultness) { - if let Defaultness::Default(span) = def { - self.struct_span_err(span, "unmatched `default`") - .span_label(span, "the unmatched `default`") + if let Defaultness::Default(sp) = def { + self.struct_span_err(sp, "`default` not followed by an item") + .span_label(sp, "the `default` qualifier") + .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`") .emit(); } } diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs index bca6f5654db..0c8ee0f7800 100644 --- a/src/test/ui/parser/default-unmatched-assoc.rs +++ b/src/test/ui/parser/default-unmatched-assoc.rs @@ -3,7 +3,7 @@ fn main() {} trait Foo { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR unmatched `default` + //~^ ERROR `default` not followed by an item //~| ERROR non-item in item list } @@ -11,6 +11,6 @@ struct S; impl S { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR unmatched `default` + //~^ ERROR `default` not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr index f3877f2ca6d..22db46d63df 100644 --- a/src/test/ui/parser/default-unmatched-assoc.stderr +++ b/src/test/ui/parser/default-unmatched-assoc.stderr @@ -1,8 +1,10 @@ -error: unmatched `default` +error: `default` not followed by an item --> $DIR/default-unmatched-assoc.rs:5:5 | LL | default do - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: non-item in item list --> $DIR/default-unmatched-assoc.rs:5:13 @@ -16,11 +18,13 @@ LL | default do LL | } | - item list ends here -error: unmatched `default` +error: `default` not followed by an item --> $DIR/default-unmatched-assoc.rs:13:5 | LL | default do - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: non-item in item list --> $DIR/default-unmatched-assoc.rs:13:13 diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs index fbf87a892f0..784df9bc77e 100644 --- a/src/test/ui/parser/default-unmatched-extern.rs +++ b/src/test/ui/parser/default-unmatched-extern.rs @@ -3,6 +3,6 @@ fn main() {} extern "C" { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR unmatched `default` + //~^ ERROR `default` not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr index 00c8898e2ce..ffbfbc73c18 100644 --- a/src/test/ui/parser/default-unmatched-extern.stderr +++ b/src/test/ui/parser/default-unmatched-extern.stderr @@ -1,8 +1,10 @@ -error: unmatched `default` +error: `default` not followed by an item --> $DIR/default-unmatched-extern.rs:5:5 | LL | default do - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: non-item in item list --> $DIR/default-unmatched-extern.rs:5:13 diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs index 31696de0a5c..796e184a0d8 100644 --- a/src/test/ui/parser/default-unmatched.rs +++ b/src/test/ui/parser/default-unmatched.rs @@ -1,6 +1,6 @@ mod foo { default!(); // OK. default do - //~^ ERROR unmatched `default` + //~^ ERROR `default` not followed by an item //~| ERROR expected item, found reserved keyword `do` } diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr index 6e4ef7b79fc..26012557761 100644 --- a/src/test/ui/parser/default-unmatched.stderr +++ b/src/test/ui/parser/default-unmatched.stderr @@ -1,8 +1,10 @@ -error: unmatched `default` +error: `default` not followed by an item --> $DIR/default-unmatched.rs:3:5 | LL | default do - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: expected item, found reserved keyword `do` --> $DIR/default-unmatched.rs:3:13 diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index bd9ed0f4524..6cfa141478e 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -20,7 +20,7 @@ impl Foo for u16 { impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` default pub fn foo() -> T { T::default() } - //~^ ERROR unmatched `default` + //~^ ERROR `default` not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index fbf8101c36a..96b14b42767 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,8 +1,10 @@ -error: unmatched `default` +error: `default` not followed by an item --> $DIR/default.rs:22:5 | LL | default pub fn foo() -> T { T::default() } - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: non-item in item list --> $DIR/default.rs:22:13 diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index 949b6e1dc24..edea2d1e5e2 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -2,6 +2,6 @@ fn main() {} extern { pub pub fn foo(); - //~^ ERROR unmatched visibility `pub` + //~^ ERROR visibility `pub` not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index 2c79a343d05..d8e38046a6c 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,8 +1,8 @@ -error: unmatched visibility `pub` +error: visibility `pub` not followed by an item --> $DIR/duplicate-visibility.rs:4:5 | LL | pub pub fn foo(); - | ^^^ the unmatched visibility + | ^^^ the visibility | = help: you likely meant to define an item, e.g., `pub fn foo() {}` diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs index 662ed28f2f7..c2ed7531a94 100644 --- a/src/test/ui/parser/impl-parsing.rs +++ b/src/test/ui/parser/impl-parsing.rs @@ -7,4 +7,4 @@ impl ?Sized for Type {} //~ ERROR expected a trait, found type impl ?Sized for .. {} //~ ERROR expected a trait, found type default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` -//~^ ERROR unmatched `default` +//~^ ERROR `default` not followed by an item diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr index a5fc3e46896..ce673765aba 100644 --- a/src/test/ui/parser/impl-parsing.stderr +++ b/src/test/ui/parser/impl-parsing.stderr @@ -22,11 +22,13 @@ error: expected a trait, found type LL | impl ?Sized for .. {} | ^^^^^^ -error: unmatched `default` +error: `default` not followed by an item --> $DIR/impl-parsing.rs:9:1 | LL | default unsafe FAIL - | ^^^^^^^ the unmatched `default` + | ^^^^^^^ the `default` qualifier + | + = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default` error: expected item, found keyword `unsafe` --> $DIR/impl-parsing.rs:9:9 diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs index bed4805e7ce..5bfbe0c5e68 100644 --- a/src/test/ui/parser/issue-41155.rs +++ b/src/test/ui/parser/issue-41155.rs @@ -1,7 +1,7 @@ struct S; impl S { - pub //~ ERROR unmatched visibility `pub` + pub //~ ERROR visibility `pub` not followed by an item } //~ ERROR non-item in item list fn main() {} diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index a9c1035f4d8..09bbee51800 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,8 +1,8 @@ -error: unmatched visibility `pub` +error: visibility `pub` not followed by an item --> $DIR/issue-41155.rs:4:5 | LL | pub - | ^^^ the unmatched visibility + | ^^^ the visibility | = help: you likely meant to define an item, e.g., `pub fn foo() {}` diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs index 3f8904fbe79..73806fdfe72 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.rs +++ b/src/test/ui/pub/pub-restricted-error-fn.rs @@ -1,2 +1,2 @@ -pub(crate) () fn foo() {} //~ unmatched visibility +pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` not followed by an item //~^ ERROR expected item, found `(` diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index c0168b02da6..42d03941e41 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,8 +1,8 @@ -error: unmatched visibility `pub(crate)` +error: visibility `pub(crate)` not followed by an item --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} - | ^^^^^^^^^^ the unmatched visibility + | ^^^^^^^^^^ the visibility | = help: you likely meant to define an item, e.g., `pub(crate) fn foo() {}` From b01c1e2092b0d3c4e86aedf1e0875898fbde21e3 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 06:04:37 +0100 Subject: [PATCH 0477/1250] parser: tweak item kind wording --- src/librustc_expand/expand.rs | 4 +- src/librustc_hir/hir.rs | 10 +-- src/librustc_parse/parser/item.rs | 20 +++--- src/librustc_passes/dead.rs | 8 +-- src/librustc_passes/stability.rs | 2 +- src/libsyntax/ast.rs | 23 ++++-- .../ui/parser/default-on-wrong-item-kind.rs | 72 +++++++++---------- .../parser/default-on-wrong-item-kind.stderr | 72 +++++++++---------- .../missing-close-brace-in-impl-trait.rs | 4 +- .../missing-close-brace-in-impl-trait.stderr | 4 +- .../missing-close-brace-in-trait.rs | 4 +- .../missing-close-brace-in-trait.stderr | 4 +- 12 files changed, 115 insertions(+), 112 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index e5f957a63de..fce2a1d7a7e 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -378,8 +378,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.span_err( span, &format!( - "expected crate top-level item to be a module after macro expansion, found a {}", - kind.descriptive_variant() + "expected crate top-level item to be a module after macro expansion, found {} {}", + kind.article(), kind.descr() ), ); } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 8496a6ed23b..6d2f5ba6baf 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2500,16 +2500,16 @@ pub enum ItemKind<'hir> { } impl ItemKind<'_> { - pub fn descriptive_variant(&self) -> &str { + pub fn descr(&self) -> &str { match *self { ItemKind::ExternCrate(..) => "extern crate", - ItemKind::Use(..) => "use", + ItemKind::Use(..) => "`use` import", ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", - ItemKind::ForeignMod(..) => "foreign module", - ItemKind::GlobalAsm(..) => "global asm", + ItemKind::ForeignMod(..) => "extern block", + ItemKind::GlobalAsm(..) => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::OpaqueTy(..) => "opaque type", ItemKind::Enum(..) => "enum", @@ -2517,7 +2517,7 @@ impl ItemKind<'_> { ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Impl { .. } => "impl", + ItemKind::Impl { .. } => "implementation", } } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d2073a5473a..0e0017d4ee5 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -661,12 +661,7 @@ impl<'a> Parser<'a> { self.struct_span_err(span, "associated `static` items are not allowed").emit(); AssocItemKind::Const(a, b) } - _ => { - let span = self.sess.source_map().def_span(span); - self.struct_span_err(span, "item kind not supported in `trait` or `impl`") - .emit(); - return None; - } + _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"), }; Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) })) @@ -858,16 +853,19 @@ impl<'a> Parser<'a> { self.error_on_foreign_const(span, ident); ForeignItemKind::Static(a, Mutability::Not, b) } - _ => { - let span = self.sess.source_map().def_span(span); - self.struct_span_err(span, "item kind not supported in `extern` block").emit(); - return None; - } + _ => return self.error_bad_item_kind(span, &kind, "`extern` block"), }; Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) })) } + fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option { + let span = self.sess.source_map().def_span(span); + let msg = format!("{} not supported in {}", kind.descr(), ctx); + self.struct_span_err(span, &msg).emit(); + return None; + } + fn error_on_foreign_const(&self, span: Span, ident: Ident) { self.struct_span_err(ident.span, "extern items cannot be `const`") .span_suggestion( diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 25b8b8fcd44..e0eef1db0f0 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -601,13 +601,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { hir::ItemKind::Struct(..) => "constructed", // Issue #52325 _ => "used", }; - self.warn_dead_code( - item.hir_id, - span, - item.ident.name, - item.kind.descriptive_variant(), - participle, - ); + self.warn_dead_code(item.hir_id, span, item.ident.name, item.kind.descr(), participle); } else { // Only continue if we didn't warn intravisit::walk_item(self, item); diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 0c7f64fefd0..99fbac4568e 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -362,7 +362,7 @@ impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { // optional. They inherit stability from their parents when unannotated. hir::ItemKind::Impl { of_trait: None, .. } | hir::ItemKind::ForeignMod(..) => {} - _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descriptive_variant()), + _ => self.check_missing_stability(i.hir_id, i.span, i.kind.descr()), } intravisit::walk_item(self, i) diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index dd3319fcba1..f8a27cf7142 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2574,23 +2574,34 @@ pub enum ItemKind { } impl ItemKind { - pub fn descriptive_variant(&self) -> &str { - match *self { + pub fn article(&self) -> &str { + use ItemKind::*; + match self { + Use(..) | Static(..) | Const(..) | Fn(..) | Mod(..) | GlobalAsm(..) | TyAlias(..) + | Struct(..) | Union(..) | Trait(..) | TraitAlias(..) | MacroDef(..) => "a", + ExternCrate(..) | ForeignMod(..) | Mac(..) | Enum(..) | Impl { .. } => "an", + } + } + + pub fn descr(&self) -> &str { + match self { ItemKind::ExternCrate(..) => "extern crate", - ItemKind::Use(..) => "use", + ItemKind::Use(..) => "`use` import", ItemKind::Static(..) => "static item", ItemKind::Const(..) => "constant item", ItemKind::Fn(..) => "function", ItemKind::Mod(..) => "module", - ItemKind::ForeignMod(..) => "foreign module", - ItemKind::GlobalAsm(..) => "global asm", + ItemKind::ForeignMod(..) => "extern block", + ItemKind::GlobalAsm(..) => "global asm item", ItemKind::TyAlias(..) => "type alias", ItemKind::Enum(..) => "enum", ItemKind::Struct(..) => "struct", ItemKind::Union(..) => "union", ItemKind::Trait(..) => "trait", ItemKind::TraitAlias(..) => "trait alias", - ItemKind::Mac(..) | ItemKind::MacroDef(..) | ItemKind::Impl { .. } => "item", + ItemKind::Mac(..) => "item macro invocation", + ItemKind::MacroDef(..) => "macro definition", + ItemKind::Impl { .. } => "implementation", } } diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 0951af1579b..47b9e34305f 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -31,110 +31,110 @@ mod free_items { #[cfg(FALSE)] extern "C" { default extern crate foo; //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR extern crate not supported in `extern` block default use foo; //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR `use` import not supported in `extern` block default static foo: u8; //~ ERROR item cannot be `default` default const foo: u8; //~ ERROR item cannot be `default` //~^ ERROR extern items cannot be `const` default fn foo(); //~ ERROR item cannot be `default` default mod foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR module not supported in `extern` block default extern "C" {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR extern block not supported in `extern` block default type foo = u8; //~ ERROR item cannot be `default` default enum foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR enum not supported in `extern` block default struct foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR struct not supported in `extern` block default union foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR union not supported in `extern` block default trait foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR trait not supported in `extern` block default trait foo = Ord; //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR trait alias not supported in `extern` block default impl foo {} - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR implementation not supported in `extern` block default!(); default::foo::bar!(); default default!(); //~ ERROR item cannot be `default` default default::foo::bar!(); //~ ERROR item cannot be `default` default macro foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR macro definition not supported in `extern` block default macro_rules! foo {} //~ ERROR item cannot be `default` - //~^ ERROR item kind not supported in `extern` block + //~^ ERROR macro definition not supported in `extern` block } #[cfg(FALSE)] impl S { default extern crate foo; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR extern crate not supported in `trait` or `impl` default use foo; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR `use` import not supported in `trait` or `impl` default static foo: u8; //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); default mod foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR module not supported in `trait` or `impl` default extern "C" {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR extern block not supported in `trait` or `impl` default type foo = u8; default enum foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR enum not supported in `trait` or `impl` default struct foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR struct not supported in `trait` or `impl` default union foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR union not supported in `trait` or `impl` default trait foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR trait not supported in `trait` or `impl` default trait foo = Ord; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR trait alias not supported in `trait` or `impl` default impl foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR implementation not supported in `trait` or `impl` default!(); default::foo::bar!(); default default!(); default default::foo::bar!(); default macro foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR macro definition not supported in `trait` or `impl` default macro_rules! foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR macro definition not supported in `trait` or `impl` } #[cfg(FALSE)] trait T { default extern crate foo; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR extern crate not supported in `trait` or `impl` default use foo; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR `use` import not supported in `trait` or `impl` default static foo: u8; //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); default mod foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR module not supported in `trait` or `impl` default extern "C" {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR extern block not supported in `trait` or `impl` default type foo = u8; default enum foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR enum not supported in `trait` or `impl` default struct foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR struct not supported in `trait` or `impl` default union foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR union not supported in `trait` or `impl` default trait foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR trait not supported in `trait` or `impl` default trait foo = Ord; - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR trait alias not supported in `trait` or `impl` default impl foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR implementation not supported in `trait` or `impl` default!(); default::foo::bar!(); default default!(); default default::foo::bar!(); default macro foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR macro definition not supported in `trait` or `impl` default macro_rules! foo {} - //~^ ERROR item kind not supported in `trait` or `impl` + //~^ ERROR macro definition not supported in `trait` or `impl` } diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index 6c4c108a28f..ec569b43d70 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -142,7 +142,7 @@ LL | default extern crate foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: extern crate not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:33:5 | LL | default extern crate foo; @@ -156,7 +156,7 @@ LL | default use foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: `use` import not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:35:5 | LL | default use foo; @@ -204,7 +204,7 @@ LL | default mod foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: module not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:41:5 | LL | default mod foo {} @@ -218,7 +218,7 @@ LL | default extern "C" {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: extern block not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:43:5 | LL | default extern "C" {} @@ -240,7 +240,7 @@ LL | default enum foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: enum not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:46:5 | LL | default enum foo {} @@ -254,7 +254,7 @@ LL | default struct foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: struct not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:48:5 | LL | default struct foo {} @@ -268,7 +268,7 @@ LL | default union foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: union not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:50:5 | LL | default union foo {} @@ -282,7 +282,7 @@ LL | default trait foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: trait not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:52:5 | LL | default trait foo {} @@ -296,13 +296,13 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: trait alias not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:54:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `extern` block +error: implementation not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:56:5 | LL | default impl foo {} @@ -332,7 +332,7 @@ LL | default macro foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: macro definition not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:62:5 | LL | default macro foo {} @@ -346,19 +346,19 @@ LL | default macro_rules! foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item kind not supported in `extern` block +error: macro definition not supported in `extern` block --> $DIR/default-on-wrong-item-kind.rs:64:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: extern crate not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:70:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: `use` import not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:72:5 | LL | default use foo; @@ -370,73 +370,73 @@ error: associated `static` items are not allowed LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: module not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:78:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: extern block not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:80:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: enum not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:83:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: struct not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:85:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: union not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:87:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: trait not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:89:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: trait alias not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:91:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: implementation not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:93:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:99:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:101:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: extern crate not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:107:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: `use` import not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:109:5 | LL | default use foo; @@ -448,61 +448,61 @@ error: associated `static` items are not allowed LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: module not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:115:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: extern block not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:117:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: enum not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:120:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: struct not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:122:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: union not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:124:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: trait not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:126:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: trait alias not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:128:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: implementation not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:130:5 | LL | default impl foo {} | ^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:136:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:138:5 | LL | default macro_rules! foo {} diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index d85255328f7..b26e5134db6 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -4,10 +4,10 @@ impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} -trait T { //~ ERROR item kind not supported in `trait` or `impl` +trait T { //~ ERROR trait not supported in `trait` or `impl` fn foo(&self); } -pub(crate) struct Bar(); //~ ERROR item kind not supported in `trait` or `impl` +pub(crate) struct Bar(); //~ ERROR struct not supported in `trait` or `impl` //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index 2b72c06c9c7..b1bd1a784be 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -7,13 +7,13 @@ LL | impl T for () { LL | | ^ -error: item kind not supported in `trait` or `impl` +error: trait not supported in `trait` or `impl` --> $DIR/missing-close-brace-in-impl-trait.rs:7:1 | LL | trait T { | ^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: struct not supported in `trait` or `impl` --> $DIR/missing-close-brace-in-impl-trait.rs:11:1 | LL | pub(crate) struct Bar(); diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index b2515b17ff3..d52add27398 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -2,10 +2,10 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR item kind not supported in `trait` or `impl` +//~^ ERROR struct not supported in `trait` or `impl` impl T for Bar { -//~^ ERROR item kind not supported in `trait` or `impl` +//~^ ERROR implementation not supported in `trait` or `impl` fn foo(&self) {} } diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 89bf2916510..49c685f2549 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,13 +7,13 @@ LL | trait T { LL | fn main() {} | ^ -error: item kind not supported in `trait` or `impl` +error: struct not supported in `trait` or `impl` --> $DIR/missing-close-brace-in-trait.rs:4:1 | LL | pub(crate) struct Bar(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item kind not supported in `trait` or `impl` +error: implementation not supported in `trait` or `impl` --> $DIR/missing-close-brace-in-trait.rs:7:1 | LL | impl T for Bar { From 842027f35bd0c957fff862ef864f4fc57988ed7e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 06:53:59 +0100 Subject: [PATCH 0478/1250] parse: `NtItem` -> `parse_item_common`. --- src/librustc_parse/parser/item.rs | 17 +++++----- ...37-macros-cannot-interpolate-impl-items.rs | 34 +++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 0e0017d4ee5..6fa9e615b45 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -31,16 +31,10 @@ impl<'a> Parser<'a> { pub(super) fn parse_item_( &mut self, - mut attrs: Vec, + attrs: Vec, macros_allowed: bool, attributes_allowed: bool, ) -> PResult<'a, Option>> { - maybe_whole!(self, NtItem, |item| { - let mut item = item; - mem::swap(&mut item.attrs, &mut attrs); - item.attrs.extend(attrs); - Some(item) - }); let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; if let Some(ref item) = item { self.error_on_illegal_default(item.defaultness); @@ -50,11 +44,18 @@ impl<'a> Parser<'a> { fn parse_item_common( &mut self, - attrs: Vec, + mut attrs: Vec, mac_allowed: bool, attrs_allowed: bool, req_name: ReqName, ) -> PResult<'a, Option> { + maybe_whole!(self, NtItem, |item| { + let mut item = item; + mem::swap(&mut item.attrs, &mut attrs); + item.attrs.extend(attrs); + Some(item.into_inner()) + }); + let mut unclosed_delims = vec![]; let (mut item, tokens) = self.collect_tokens(|this| { let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name); diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs new file mode 100644 index 00000000000..8592f8a7287 --- /dev/null +++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items.rs @@ -0,0 +1,34 @@ +// check-pass + +fn main() {} + +macro_rules! mac_impl { + ($i:item) => { + struct S; + impl S { $i } + } +} + +mac_impl! { + fn foo() {} +} + +macro_rules! mac_trait { + ($i:item) => { + trait T { $i } + } +} + +mac_trait! { + fn foo() {} +} + +macro_rules! mac_extern { + ($i:item) => { + extern "C" { $i } + } +} + +mac_extern! { + fn foo(); +} From 62930d31514d6d9b4b0df3755d643f06f0d4212a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 10:24:30 +0100 Subject: [PATCH 0479/1250] parse/ast: move `Defaultness` into variants. --- src/librustc_ast_lowering/item.rs | 48 +-- src/librustc_ast_lowering/lib.rs | 4 +- src/librustc_ast_passes/ast_validation.rs | 27 +- src/librustc_ast_passes/feature_gate.rs | 8 +- src/librustc_ast_pretty/pprust.rs | 31 +- .../deriving/generic/mod.rs | 6 +- .../global_allocator.rs | 3 +- src/librustc_builtin_macros/global_asm.rs | 1 - src/librustc_builtin_macros/test.rs | 5 +- src/librustc_builtin_macros/test_harness.rs | 8 +- src/librustc_expand/build.rs | 4 +- src/librustc_expand/expand.rs | 1 - src/librustc_expand/placeholders.rs | 5 - src/librustc_interface/util.rs | 4 +- src/librustc_lint/builtin.rs | 2 +- .../rmeta/decoder/cstore_impl.rs | 1 - src/librustc_parse/parser/item.rs | 64 ++-- src/librustc_resolve/build_reduced_graph.rs | 4 +- src/librustc_resolve/def_collector.rs | 4 +- src/librustc_resolve/late.rs | 22 +- src/librustc_save_analysis/dump_visitor.rs | 25 +- src/librustc_save_analysis/lib.rs | 9 +- src/librustc_save_analysis/sig.rs | 8 +- src/libsyntax/ast.rs | 28 +- src/libsyntax/mut_visit.rs | 19 +- src/libsyntax/visit.rs | 16 +- src/test/ui/ast-json/ast-json-output.stdout | 2 +- .../ui/parser/assoc-static-semantic-fail.rs | 8 +- .../parser/assoc-static-semantic-fail.stderr | 94 +++-- .../ui/parser/assoc-static-syntactic-fail.rs | 6 + .../parser/assoc-static-syntactic-fail.stderr | 68 +++- .../ui/parser/default-on-wrong-item-kind.rs | 124 +++---- .../parser/default-on-wrong-item-kind.stderr | 330 ++++++++++++++---- 33 files changed, 630 insertions(+), 359 deletions(-) diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 3d6926df58d..b5e4fe90d0d 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -173,7 +173,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ids } - ItemKind::Const(ref ty, ..) => { + ItemKind::Const(_, ref ty, ..) => { let mut ids = smallvec![i.id]; if self.sess.features_untracked().impl_trait_in_bindings { let mut visitor = ImplTraitTypeIdVisitor { ids: &mut ids }; @@ -264,11 +264,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Static(ty, m, body_id) } - ItemKind::Const(ref t, ref e) => { + ItemKind::Const(_, ref t, ref e) => { let (ty, body_id) = self.lower_const_item(t, span, e.as_deref()); hir::ItemKind::Const(ty, body_id) } - ItemKind::Fn(FnSig { ref decl, header }, ref generics, ref body) => { + ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => { let fn_def_id = self.resolver.definitions().local_def_id(id); self.with_new_scopes(|this| { this.current_item = Some(ident.span); @@ -297,16 +297,16 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)), ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)), - ItemKind::TyAlias(ref generics, _, Some(ref ty)) => match ty.kind.opaque_top_hack() { + ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => match ty.kind.opaque_top_hack() { None => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); - let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); + let generics = self.lower_generics(gen, ImplTraitContext::disallowed()); hir::ItemKind::TyAlias(ty, generics) } Some(bounds) => { let ctx = || ImplTraitContext::OpaqueTy(None, hir::OpaqueTyOrigin::Misc); let ty = hir::OpaqueTy { - generics: self.lower_generics(generics, ctx()), + generics: self.lower_generics(gen, ctx()), bounds: self.lower_param_bounds(bounds, ctx()), impl_trait_fn: None, origin: hir::OpaqueTyOrigin::TypeAlias, @@ -314,7 +314,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::OpaqueTy(ty) } }, - ItemKind::TyAlias(ref generics, _, None) => { + ItemKind::TyAlias(_, ref generics, _, None) => { let ty = self.arena.alloc(self.ty(span, hir::TyKind::Err)); let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); hir::ItemKind::TyAlias(ty, generics) @@ -654,7 +654,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: i.ident, attrs: self.lower_attrs(&i.attrs), kind: match i.kind { - ForeignItemKind::Fn(ref sig, ref generics, _) => { + ForeignItemKind::Fn(_, ref sig, ref generics, _) => { let fdec = &sig.decl; let (generics, (fn_dec, fn_args)) = self.add_in_band_defs( generics, @@ -675,7 +675,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } - ForeignItemKind::Const(ref t, _) => { + ForeignItemKind::Const(_, ref t, _) => { // For recovery purposes. let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, Mutability::Not) @@ -758,24 +758,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, kind) = match i.kind { AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`. - | AssocItemKind::Const(ref ty, ref default) => { + | AssocItemKind::Const(_, ref ty, ref default) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) } - AssocItemKind::Fn(ref sig, ref generics, None) => { + AssocItemKind::Fn(_, ref sig, ref generics, None) => { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) } - AssocItemKind::Fn(ref sig, ref generics, Some(ref body)) => { + AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) } - AssocItemKind::TyAlias(ref generics, ref bounds, ref default) => { + AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = hir::TraitItemKind::Type( @@ -801,11 +801,11 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { let (kind, has_default) = match &i.kind { AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery. - | AssocItemKind::Const(_, default) => { + | AssocItemKind::Const(_, _, default) => { (hir::AssocItemKind::Const, default.is_some()) } - AssocItemKind::TyAlias(_, _, default) => (hir::AssocItemKind::Type, default.is_some()), - AssocItemKind::Fn(sig, _, default) => { + AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()), + AssocItemKind::Fn(_, sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) } AssocItemKind::Macro(..) => unimplemented!(), @@ -823,15 +823,15 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); - let (generics, kind) = match i.kind { - AssocItemKind::Static(ref ty, _, ref expr) | AssocItemKind::Const(ref ty, ref expr) => { + let (generics, kind) = match &i.kind { + AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); ( hir::Generics::empty(), hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())), ) } - AssocItemKind::Fn(ref sig, ref generics, ref body) => { + AssocItemKind::Fn(_, sig, generics, body) => { self.current_item = Some(i.span); let asyncness = sig.header.asyncness; let body_id = @@ -847,7 +847,7 @@ impl<'hir> LoweringContext<'_, 'hir> { (generics, hir::ImplItemKind::Method(sig, body_id)) } - AssocItemKind::TyAlias(ref generics, _, ref ty) => { + AssocItemKind::TyAlias(_, generics, _, ty) => { let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); let kind = match ty { None => { @@ -876,7 +876,7 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs: self.lower_attrs(&i.attrs), generics, vis: self.lower_visibility(&i.vis, None), - defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), + defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */), kind, span: i.span, } @@ -890,17 +890,17 @@ impl<'hir> LoweringContext<'_, 'hir> { ident: i.ident, span: i.span, vis: self.lower_visibility(&i.vis, Some(i.id)), - defaultness: self.lower_defaultness(i.defaultness, true /* [1] */), + defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */), kind: match &i.kind { AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery. | AssocItemKind::Const(..) => hir::AssocItemKind::Const, - AssocItemKind::TyAlias(_, _, ty) => { + AssocItemKind::TyAlias(.., ty) => { match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, Some(_) => hir::AssocItemKind::OpaqueTy, } } - AssocItemKind::Fn(sig, _, _) => { + AssocItemKind::Fn(_, sig, ..) => { hir::AssocItemKind::Method { has_self: sig.decl.has_self() } } AssocItemKind::Macro(..) => unimplemented!(), diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 9bb46009fe6..8bf9311bfc7 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -462,7 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ItemKind::Struct(_, ref generics) | ItemKind::Union(_, ref generics) | ItemKind::Enum(_, ref generics) - | ItemKind::TyAlias(ref generics, ..) + | ItemKind::TyAlias(_, ref generics, ..) | ItemKind::Trait(_, _, ref generics, ..) => { let def_id = self.lctx.resolver.definitions().local_def_id(item.id); let count = generics @@ -490,7 +490,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lctx.allocate_hir_id_counter(item.id); let owner = match (&item.kind, ctxt) { // Ignore patterns in trait methods without bodies. - (AssocItemKind::Fn(_, _, None), AssocCtxt::Trait) => None, + (AssocItemKind::Fn(_, _, _, None), AssocCtxt::Trait) => None, _ => Some(item.id), }; self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt)); diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index d385ea1a4a6..44fed6dee66 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -881,7 +881,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .emit(); } } - ItemKind::Fn(ref sig, ref generics, ref body) => { + ItemKind::Fn(def, ref sig, ref generics, ref body) => { + self.check_defaultness(item.span, def); self.check_const_fn_const_generic(item.span, sig, generics); if body.is_none() { @@ -965,7 +966,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.err_handler().span_err(item.span, "unions cannot have zero fields"); } } - ItemKind::Const(.., None) => { + ItemKind::Const(def, .., None) => { + self.check_defaultness(item.span, def); let msg = "free constant item without body"; self.error_item_without_body(item.span, "constant", msg, " = ;"); } @@ -973,7 +975,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let msg = "free static item without body"; self.error_item_without_body(item.span, "static", msg, " = ;"); } - ItemKind::TyAlias(_, ref bounds, ref body) => { + ItemKind::TyAlias(def, _, ref bounds, ref body) => { + self.check_defaultness(item.span, def); if body.is_none() { let msg = "free type alias without body"; self.error_item_without_body(item.span, "type", msg, " = ;"); @@ -988,11 +991,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { fn visit_foreign_item(&mut self, fi: &'a ForeignItem) { match &fi.kind { - ForeignItemKind::Fn(sig, _, body) => { + ForeignItemKind::Fn(def, sig, _, body) => { + self.check_defaultness(fi.span, *def); self.check_foreign_fn_bodyless(fi.ident, body.as_deref()); self.check_foreign_fn_headerless(fi.ident, fi.span, sig.header); } - ForeignItemKind::TyAlias(generics, bounds, body) => { + ForeignItemKind::TyAlias(def, generics, bounds, body) => { + self.check_defaultness(fi.span, *def); self.check_foreign_kind_bodyless(fi.ident, "type", body.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); self.check_foreign_ty_genericless(generics); @@ -1233,19 +1238,19 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } fn visit_assoc_item(&mut self, item: &'a AssocItem, ctxt: AssocCtxt) { - if ctxt == AssocCtxt::Trait { - self.check_defaultness(item.span, item.defaultness); + if ctxt == AssocCtxt::Trait || !self.in_trait_impl { + self.check_defaultness(item.span, item.kind.defaultness()); } if ctxt == AssocCtxt::Impl { match &item.kind { - AssocItemKind::Const(_, body) => { + AssocItemKind::Const(_, _, body) => { self.check_impl_item_provided(item.span, body, "constant", " = ;"); } - AssocItemKind::Fn(_, _, body) => { + AssocItemKind::Fn(_, _, _, body) => { self.check_impl_item_provided(item.span, body, "function", " { }"); } - AssocItemKind::TyAlias(_, bounds, body) => { + AssocItemKind::TyAlias(_, _, bounds, body) => { self.check_impl_item_provided(item.span, body, "type", " = ;"); self.check_type_no_bounds(bounds, "`impl`s"); } @@ -1255,7 +1260,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if ctxt == AssocCtxt::Trait || self.in_trait_impl { self.invalid_visibility(&item.vis, None); - if let AssocItemKind::Fn(sig, _, _) = &item.kind { + if let AssocItemKind::Fn(_, sig, _, _) = &item.kind { self.check_trait_fn_not_const(sig.header.constness); self.check_trait_fn_not_async(item.span, sig.header.asyncness); } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 586539d9b5e..33ff0bc451b 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -372,7 +372,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, decl_macro, i.span, msg); } - ast::ItemKind::TyAlias(_, _, Some(ref ty)) => self.check_impl_trait(&ty), + ast::ItemKind::TyAlias(_, _, _, Some(ref ty)) => self.check_impl_trait(&ty), _ => {} } @@ -543,17 +543,17 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { - if let ast::Defaultness::Default(_) = i.defaultness { + if let ast::Defaultness::Default(_) = i.kind.defaultness() { gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); } match i.kind { - ast::AssocItemKind::Fn(ref sig, _, _) => { + ast::AssocItemKind::Fn(_, ref sig, _, _) => { if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); } } - ast::AssocItemKind::TyAlias(ref generics, _, ref ty) => { + ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { gate_feature_post!( &self, diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 503310c6db5..2b223d92ff1 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1016,8 +1016,8 @@ impl<'a> State<'a> { } crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) { - let ast::Item { id, span, ident, attrs, kind, vis, defaultness, tokens: _ } = item; - self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis); + let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis); } fn print_nested_item_kind( @@ -1026,7 +1026,6 @@ impl<'a> State<'a> { span: Span, ident: ast::Ident, attrs: &[Attribute], - def: ast::Defaultness, kind: &ast::AssocItemKind, vis: &ast::Visibility, ) { @@ -1035,17 +1034,18 @@ impl<'a> State<'a> { self.maybe_print_comment(span.lo()); self.print_outer_attributes(attrs); match kind { - ast::ForeignItemKind::Fn(sig, gen, body) => { - self.print_fn_full(sig, ident, gen, vis, def, body.as_deref(), attrs); + ast::ForeignItemKind::Fn(def, sig, gen, body) => { + self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs); } - ast::ForeignItemKind::Const(ty, body) => { - self.print_item_const(ident, None, ty, body.as_deref(), vis, def); + ast::ForeignItemKind::Const(def, ty, body) => { + self.print_item_const(ident, None, ty, body.as_deref(), vis, *def); } ast::ForeignItemKind::Static(ty, mutbl, body) => { + let def = ast::Defaultness::Final; self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def); } - ast::ForeignItemKind::TyAlias(generics, bounds, ty) => { - self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, def); + ast::ForeignItemKind::TyAlias(def, generics, bounds, ty) => { + self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def); } ast::ForeignItemKind::Macro(m) => { self.print_mac(m); @@ -1146,12 +1146,10 @@ impl<'a> State<'a> { let def = ast::Defaultness::Final; self.print_item_const(item.ident, Some(mutbl), ty, body.as_deref(), &item.vis, def); } - ast::ItemKind::Const(ref ty, ref body) => { - let def = ast::Defaultness::Final; + ast::ItemKind::Const(def, ref ty, ref body) => { self.print_item_const(item.ident, None, ty, body.as_deref(), &item.vis, def); } - ast::ItemKind::Fn(ref sig, ref gen, ref body) => { - let def = ast::Defaultness::Final; + ast::ItemKind::Fn(def, ref sig, ref gen, ref body) => { let body = body.as_deref(); self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs); } @@ -1185,8 +1183,7 @@ impl<'a> State<'a> { self.s.word(ga.asm.to_string()); self.end(); } - ast::ItemKind::TyAlias(ref generics, ref bounds, ref ty) => { - let def = ast::Defaultness::Final; + ast::ItemKind::TyAlias(def, ref generics, ref bounds, ref ty) => { let ty = ty.as_deref(); self.print_associated_type(item.ident, generics, bounds, ty, &item.vis, def); } @@ -1461,8 +1458,8 @@ impl<'a> State<'a> { } crate fn print_assoc_item(&mut self, item: &ast::AssocItem) { - let ast::AssocItem { id, span, ident, attrs, defaultness, kind, vis, tokens: _ } = item; - self.print_nested_item_kind(*id, *span, *ident, attrs, *defaultness, kind, vis); + let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item; + self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis); } crate fn print_stmt(&mut self, st: &ast::Stmt) { diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 294b7463916..00ed05608b5 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -542,9 +542,9 @@ impl<'a> TraitDef<'a> { span: self.span, ident, vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, attrs: Vec::new(), kind: ast::AssocItemKind::TyAlias( + ast::Defaultness::Final, Generics::default(), Vec::new(), Some(type_def.to_ty(cx, self.span, type_ident, generics)), @@ -968,6 +968,7 @@ impl<'a> MethodDef<'a> { header: ast::FnHeader { unsafety, ext: ast::Extern::None, ..ast::FnHeader::default() }, decl: fn_decl, }; + let def = ast::Defaultness::Final; // Create the method. P(ast::AssocItem { @@ -975,9 +976,8 @@ impl<'a> MethodDef<'a> { attrs: self.attributes.clone(), span: trait_.span, vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, ident: method_ident, - kind: ast::AssocItemKind::Fn(sig, fn_generics, Some(body_block)), + kind: ast::AssocItemKind::Fn(def, sig, fn_generics, Some(body_block)), tokens: None, }) } diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs index 3ffb1d2206a..5a0b1a6b885 100644 --- a/src/librustc_builtin_macros/global_allocator.rs +++ b/src/librustc_builtin_macros/global_allocator.rs @@ -66,7 +66,8 @@ impl AllocFnFactory<'_, '_> { let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty)); let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() }; let sig = FnSig { decl, header }; - let kind = ItemKind::Fn(sig, Generics::default(), Some(self.cx.block_expr(output_expr))); + let block = Some(self.cx.block_expr(output_expr)); + let kind = ItemKind::Fn(ast::Defaultness::Final, sig, Generics::default(), block); let item = self.cx.item( self.span, self.cx.ident_of(&self.kind.fn_name(method.name), self.span), diff --git a/src/librustc_builtin_macros/global_asm.rs b/src/librustc_builtin_macros/global_asm.rs index 70b9fccbafc..052e62ee9ff 100644 --- a/src/librustc_builtin_macros/global_asm.rs +++ b/src/librustc_builtin_macros/global_asm.rs @@ -30,7 +30,6 @@ pub fn expand_global_asm<'cx>( id: ast::DUMMY_NODE_ID, kind: ast::ItemKind::GlobalAsm(P(global_asm)), vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, span: cx.with_def_site_ctxt(sp), tokens: None, })]), diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index e15405e1f0d..8407352f577 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -184,6 +184,7 @@ pub fn expand_test_or_bench( ], // const $ident: test::TestDescAndFn = ast::ItemKind::Const( + ast::Defaultness::Final, cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), // test::TestDescAndFn { Some( @@ -378,7 +379,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); let ref sd = cx.parse_sess.span_diagnostic; - if let ast::ItemKind::Fn(ref sig, ref generics, _) = i.kind { + if let ast::ItemKind::Fn(_, ref sig, ref generics, _) = i.kind { if let ast::Unsafe::Yes(span) = sig.header.unsafety { sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") .span_label(span, "`unsafe` because of this") @@ -427,7 +428,7 @@ fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { } fn has_bench_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { - let has_sig = if let ast::ItemKind::Fn(ref sig, _, _) = i.kind { + let has_sig = if let ast::ItemKind::Fn(_, ref sig, _, _) = i.kind { // N.B., inadequate check, but we're running // well before resolve, can't get too deep. sig.decl.inputs.len() == 1 diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 1d8ade1b2ba..4bbab0d2574 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -162,7 +162,7 @@ impl MutVisitor for EntryPointCleaner { // #[allow(dead_code)] to avoid printing warnings. let item = match entry::entry_point_type(&item, self.depth) { EntryPointType::MainNamed | EntryPointType::MainAttr | EntryPointType::Start => item - .map(|ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens }| { + .map(|ast::Item { id, ident, attrs, kind, vis, span, tokens }| { let allow_ident = Ident::new(sym::allow, self.def_site); let dc_nested = attr::mk_nested_word_item(Ident::from_str_and_span( "dead_code", @@ -176,7 +176,7 @@ impl MutVisitor for EntryPointCleaner { .chain(iter::once(allow_dead_code)) .collect(); - ast::Item { id, ident, attrs, kind, vis, defaultness, span, tokens } + ast::Item { id, ident, attrs, kind, vis, span, tokens } }), EntryPointType::None | EntryPointType::OtherMain => item, }; @@ -298,7 +298,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { let decl = ecx.fn_decl(vec![], ast::FnRetTy::Ty(main_ret_ty)); let sig = ast::FnSig { decl, header: ast::FnHeader::default() }; - let main = ast::ItemKind::Fn(sig, ast::Generics::default(), Some(main_body)); + let def = ast::Defaultness::Final; + let main = ast::ItemKind::Fn(def, sig, ast::Generics::default(), Some(main_body)); // Honor the reexport_test_harness_main attribute let main_id = match cx.reexport_test_harness_main { @@ -312,7 +313,6 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { id: ast::DUMMY_NODE_ID, kind: main, vis: respan(sp, ast::VisibilityKind::Public), - defaultness: ast::Defaultness::Final, span: sp, tokens: None, }); diff --git a/src/librustc_expand/build.rs b/src/librustc_expand/build.rs index 246b3bff71d..bd6823cd4e2 100644 --- a/src/librustc_expand/build.rs +++ b/src/librustc_expand/build.rs @@ -588,7 +588,6 @@ impl<'a> ExtCtxt<'a> { id: ast::DUMMY_NODE_ID, kind, vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, span, tokens: None, }) @@ -645,7 +644,8 @@ impl<'a> ExtCtxt<'a> { ty: P, expr: P, ) -> P { - self.item(span, name, Vec::new(), ast::ItemKind::Const(ty, Some(expr))) + let def = ast::Defaultness::Final; + self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr))) } pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute { diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index fce2a1d7a7e..bbea066b048 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -358,7 +358,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ident: Ident::invalid(), id: ast::DUMMY_NODE_ID, vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public), - defaultness: ast::Defaultness::Final, tokens: None, })]); diff --git a/src/librustc_expand/placeholders.rs b/src/librustc_expand/placeholders.rs index e7e4f482a5e..c323af4336a 100644 --- a/src/librustc_expand/placeholders.rs +++ b/src/librustc_expand/placeholders.rs @@ -26,7 +26,6 @@ pub fn placeholder( let ident = ast::Ident::invalid(); let attrs = Vec::new(); let vis = vis.unwrap_or_else(|| dummy_spanned(ast::VisibilityKind::Inherited)); - let defaultness = ast::Defaultness::Final; let span = DUMMY_SP; let expr_placeholder = || { P(ast::Expr { @@ -47,7 +46,6 @@ pub fn placeholder( span, ident, vis, - defaultness, attrs, kind: ast::ItemKind::Mac(mac_placeholder()), tokens: None, @@ -59,7 +57,6 @@ pub fn placeholder( vis, attrs, kind: ast::AssocItemKind::Macro(mac_placeholder()), - defaultness: ast::Defaultness::Final, tokens: None, })]), AstFragmentKind::ImplItems => AstFragment::ImplItems(smallvec![P(ast::AssocItem { @@ -69,7 +66,6 @@ pub fn placeholder( vis, attrs, kind: ast::AssocItemKind::Macro(mac_placeholder()), - defaultness: ast::Defaultness::Final, tokens: None, })]), AstFragmentKind::ForeignItems => { @@ -78,7 +74,6 @@ pub fn placeholder( span, ident, vis, - defaultness, attrs, kind: ast::ForeignItemKind::Macro(mac_placeholder()), tokens: None, diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 99e9878bfd8..c73f7aafb48 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -677,7 +677,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn visit_item_kind(&mut self, i: &mut ast::ItemKind) { let is_const = match i { ast::ItemKind::Static(..) | ast::ItemKind::Const(..) => true, - ast::ItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig), + ast::ItemKind::Fn(_, ref sig, _, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_visit_item_kind(i, s)) @@ -686,7 +686,7 @@ impl<'a> MutVisitor for ReplaceBodyWithLoop<'a, '_> { fn flat_map_trait_item(&mut self, i: P) -> SmallVec<[P; 1]> { let is_const = match i.kind { ast::AssocItemKind::Const(..) => true, - ast::AssocItemKind::Fn(ref sig, _, _) => Self::is_sig_const(sig), + ast::AssocItemKind::Fn(_, ref sig, _, _) => Self::is_sig_const(sig), _ => false, }; self.run(is_const, |s| noop_flat_map_assoc_item(i, s)) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 5c601803a77..ca3727d1755 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -640,7 +640,7 @@ declare_lint_pass!( impl EarlyLintPass for AnonymousParameters { fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::AssocItem) { match it.kind { - ast::AssocItemKind::Fn(ref sig, _, _) => { + ast::AssocItemKind::Fn(_, ref sig, _, _) => { for arg in sig.decl.inputs.iter() { match arg.pat.kind { ast::PatKind::Ident(_, ident, None) => { diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index 602be372573..fb7e5541e26 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -464,7 +464,6 @@ impl CStore { legacy: def.legacy, }), vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), - defaultness: ast::Defaultness::Final, tokens: None, }, data.root.edition, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 6fa9e615b45..451f1fdf14a 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -36,9 +36,6 @@ impl<'a> Parser<'a> { attributes_allowed: bool, ) -> PResult<'a, Option>> { let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; - if let Some(ref item) = item { - self.error_on_illegal_default(item.defaultness); - } Ok(item.map(P)) } @@ -98,9 +95,10 @@ impl<'a> Parser<'a> { let mut def = self.parse_defaultness(); let kind = self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, req_name)?; if let Some((ident, kind)) = kind { + self.error_on_unconsumed_default(def, &kind); let span = lo.to(self.prev_span); let id = DUMMY_NODE_ID; - let item = Item { ident, attrs, id, kind, vis, defaultness: def, span, tokens: None }; + let item = Item { ident, attrs, id, kind, vis, span, tokens: None }; return Ok(Some(item)); } @@ -137,9 +135,10 @@ impl<'a> Parser<'a> { } /// Error in-case `default` was parsed in an in-appropriate context. - fn error_on_illegal_default(&self, def: Defaultness) { + fn error_on_unconsumed_default(&self, def: Defaultness, kind: &ItemKind) { if let Defaultness::Default(span) = def { - self.struct_span_err(span, "item cannot be `default`") + let msg = format!("{} {} cannot be `default`", kind.article(), kind.descr()); + self.struct_span_err(span, &msg) .span_label(span, "`default` because of this") .note("only associated `fn`, `const`, and `type` items can be `default`") .emit(); @@ -156,6 +155,8 @@ impl<'a> Parser<'a> { def: &mut Defaultness, req_name: ReqName, ) -> PResult<'a, Option> { + let mut def = || mem::replace(def, Defaultness::Final); + let info = if self.eat_keyword(kw::Use) { // USE ITEM let tree = self.parse_use_tree()?; @@ -164,7 +165,7 @@ impl<'a> Parser<'a> { } else if self.check_fn_front_matter() { // FUNCTION ITEM let (ident, sig, generics, body) = self.parse_fn(attrs, req_name)?; - (ident, ItemKind::Fn(sig, generics, body)) + (ident, ItemKind::Fn(def(), sig, generics, body)) } else if self.eat_keyword(kw::Extern) { if self.eat_keyword(kw::Crate) { // EXTERN CRATE @@ -177,11 +178,13 @@ impl<'a> Parser<'a> { // STATIC ITEM self.bump(); // `static` let m = self.parse_mutability(); - self.parse_item_const(Some(m))? + let (ident, ty, expr) = self.parse_item_global(Some(m))?; + (ident, ItemKind::Static(ty, m, expr)) } else if let Const::Yes(const_span) = self.parse_constness() { // CONST ITEM self.recover_const_mut(const_span); - self.parse_item_const(None)? + let (ident, ty, expr) = self.parse_item_global(None)?; + (ident, ItemKind::Const(def(), ty, expr)) } else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() { // TRAIT ITEM self.parse_item_trait(attrs, lo)? @@ -189,13 +192,13 @@ impl<'a> Parser<'a> { || self.check_keyword(kw::Unsafe) && self.is_keyword_ahead(1, &[kw::Impl]) { // IMPL ITEM - self.parse_item_impl(attrs, mem::replace(def, Defaultness::Final))? + self.parse_item_impl(attrs, def())? } else if self.eat_keyword(kw::Mod) { // MODULE ITEM self.parse_item_mod(attrs)? } else if self.eat_keyword(kw::Type) { // TYPE ITEM - self.parse_type_alias()? + self.parse_type_alias(def())? } else if self.eat_keyword(kw::Enum) { // ENUM ITEM self.parse_item_enum()? @@ -652,19 +655,19 @@ impl<'a> Parser<'a> { fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { let attrs = self.parse_outer_attributes()?; let it = self.parse_item_common(attrs, true, false, req_name)?; - Ok(it.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { + Ok(it.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match kind { ItemKind::Mac(a) => AssocItemKind::Macro(a), - ItemKind::Fn(a, b, c) => AssocItemKind::Fn(a, b, c), - ItemKind::TyAlias(a, b, c) => AssocItemKind::TyAlias(a, b, c), - ItemKind::Const(a, c) => AssocItemKind::Const(a, c), + ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), + ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), ItemKind::Static(a, _, b) => { self.struct_span_err(span, "associated `static` items are not allowed").emit(); - AssocItemKind::Const(a, b) + AssocItemKind::Const(Defaultness::Final, a, b) } _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"), }; - Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) + Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) } @@ -673,7 +676,7 @@ impl<'a> Parser<'a> { /// TypeAlias = "type" Ident Generics {":" GenericBounds}? {"=" Ty}? ";" ; /// ``` /// The `"type"` has already been eaten. - fn parse_type_alias(&mut self) -> PResult<'a, (Ident, ItemKind)> { + fn parse_type_alias(&mut self, def: Defaultness) -> PResult<'a, ItemInfo> { let ident = self.parse_ident()?; let mut generics = self.parse_generics()?; @@ -685,7 +688,7 @@ impl<'a> Parser<'a> { let default = if self.eat(&token::Eq) { Some(self.parse_ty()?) } else { None }; self.expect_semi()?; - Ok((ident, ItemKind::TyAlias(generics, bounds, default))) + Ok((ident, ItemKind::TyAlias(def, generics, bounds, default))) } /// Parses a `UseTree`. @@ -843,20 +846,19 @@ impl<'a> Parser<'a> { let attrs = self.parse_outer_attributes()?; let item = self.parse_item_common(attrs, true, false, |_| true)?; - Ok(item.map(|Item { attrs, id, span, vis, ident, defaultness, kind, tokens }| { - self.error_on_illegal_default(defaultness); + Ok(item.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match kind { ItemKind::Mac(a) => ForeignItemKind::Macro(a), - ItemKind::Fn(a, b, c) => ForeignItemKind::Fn(a, b, c), - ItemKind::TyAlias(a, b, c) => ForeignItemKind::TyAlias(a, b, c), + ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), - ItemKind::Const(a, b) => { + ItemKind::Const(_, a, b) => { self.error_on_foreign_const(span, ident); ForeignItemKind::Static(a, Mutability::Not, b) } _ => return self.error_bad_item_kind(span, &kind, "`extern` block"), }; - Some(P(Item { attrs, id, span, vis, ident, defaultness, kind, tokens })) + Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) } @@ -916,7 +918,10 @@ impl<'a> Parser<'a> { /// `["const" | ("static" "mut"?)]` already parsed and stored in `m`. /// /// When `m` is `"const"`, `$ident` may also be `"_"`. - fn parse_item_const(&mut self, m: Option) -> PResult<'a, ItemInfo> { + fn parse_item_global( + &mut self, + m: Option, + ) -> PResult<'a, (Ident, P, Option>)> { let id = if m.is_none() { self.parse_ident_or_underscore() } else { self.parse_ident() }?; // Parse the type of a `const` or `static mut?` item. @@ -929,12 +934,7 @@ impl<'a> Parser<'a> { let expr = if self.eat(&token::Eq) { Some(self.parse_expr()?) } else { None }; self.expect_semi()?; - - let item = match m { - Some(m) => ItemKind::Static(ty, m, expr), - None => ItemKind::Const(ty, expr), - }; - Ok((id, item)) + Ok((id, ty, expr)) } /// We were supposed to parse `:` but the `:` was missing. diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 383bfe18fd0..a81caea4e41 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -718,7 +718,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // These items live in the type namespace. - ItemKind::TyAlias(_, _, ref ty) => { + ItemKind::TyAlias(_, _, _, ref ty) => { let def_kind = match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => DefKind::TyAlias, Some(_) => DefKind::OpaqueTy, @@ -1253,7 +1253,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { let (res, ns) = match item.kind { AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery. | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), - AssocItemKind::Fn(ref sig, _, _) => { + AssocItemKind::Fn(_, ref sig, _, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 60cba555121..30089633689 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -117,7 +117,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), - ItemKind::Fn(sig, generics, body) if sig.header.asyncness.is_async() => { + ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => { return self.visit_async_fn( i.id, i.ident.name, @@ -215,7 +215,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_data = match &i.kind { - AssocItemKind::Fn(FnSig { header, decl }, generics, body) + AssocItemKind::Fn(_, FnSig { header, decl }, generics, body) if header.asyncness.is_async() => { return self.visit_async_fn( diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 74628e6e5a0..5b5180a7e1a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -437,8 +437,8 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { match foreign_item.kind { - ForeignItemKind::Fn(_, ref generics, _) - | ForeignItemKind::TyAlias(ref generics, ..) => { + ForeignItemKind::Fn(_, _, ref generics, _) + | ForeignItemKind::TyAlias(_, ref generics, ..) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_foreign_item(this, foreign_item); }); @@ -797,7 +797,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { debug!("(resolving item) resolving {} ({:?})", name, item.kind); match item.kind { - ItemKind::TyAlias(ref generics, _, _) | ItemKind::Fn(_, ref generics, _) => { + ItemKind::TyAlias(_, ref generics, _, _) | ItemKind::Fn(_, _, ref generics, _) => { self.with_generic_param_rib(generics, ItemRibKind(HasGenericParams::Yes), |this| { visit::walk_item(this, item) }); @@ -837,7 +837,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_trait_items(trait_items, |this| { match &item.kind { AssocItemKind::Static(ty, _, default) - | AssocItemKind::Const(ty, default) => { + | AssocItemKind::Const(_, ty, default) => { this.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -845,10 +845,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { this.with_constant_rib(|this| this.visit_expr(expr)); } } - AssocItemKind::Fn(_, generics, _) => { + AssocItemKind::Fn(_, _, generics, _) => { walk_assoc_item(this, generics, item); } - AssocItemKind::TyAlias(generics, _, _) => { + AssocItemKind::TyAlias(_, generics, _, _) => { walk_assoc_item(this, generics, item); } AssocItemKind::Macro(_) => { @@ -878,7 +878,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }); } - ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(ref ty, ref expr) => { + ItemKind::Static(ref ty, _, ref expr) | ItemKind::Const(_, ref ty, ref expr) => { debug!("resolve_item ItemKind::Const"); self.with_item_rib(HasGenericParams::No, |this| { this.visit_ty(ty); @@ -1015,7 +1015,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_items .iter() .filter_map(|item| match &item.kind { - AssocItemKind::TyAlias(_, bounds, _) if bounds.len() == 0 => Some(item.ident), + AssocItemKind::TyAlias(_, _, bounds, _) if bounds.len() == 0 => { + Some(item.ident) + } _ => None, }) .collect(), @@ -1125,7 +1127,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { visit::walk_assoc_item(this, item, AssocCtxt::Impl) }); } - AssocItemKind::Fn(_, generics, _) => { + AssocItemKind::Fn(_, _, generics, _) => { // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, @@ -1148,7 +1150,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { }, ); } - AssocItemKind::TyAlias(generics, _, _) => { + AssocItemKind::TyAlias(_, generics, _, _) => { // We also need a new scope for the impl item type parameters. this.with_generic_param_rib( generics, diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index 442f3b695a2..b3a8657d80b 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1005,7 +1005,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { ast::AssocItemKind::Static(ref ty, _, ref expr) - | ast::AssocItemKind::Const(ref ty, ref expr) => { + | ast::AssocItemKind::Const(_, ref ty, ref expr) => { self.process_assoc_const( trait_item.id, trait_item.ident, @@ -1016,7 +1016,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &trait_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { + ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => { self.process_method( sig, body.as_ref().map(|x| &**x), @@ -1027,7 +1027,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { trait_item.span, ); } - ast::AssocItemKind::TyAlias(_, ref bounds, ref default_ty) => { + ast::AssocItemKind::TyAlias(_, _, ref bounds, ref default_ty) => { // FIXME do something with _bounds (for type refs) let name = trait_item.ident.name.to_string(); let qualname = format!( @@ -1076,7 +1076,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.process_macro_use(impl_item.span); match impl_item.kind { ast::AssocItemKind::Static(ref ty, _, ref expr) - | ast::AssocItemKind::Const(ref ty, ref expr) => { + | ast::AssocItemKind::Const(_, ref ty, ref expr) => { self.process_assoc_const( impl_item.id, impl_item.ident, @@ -1087,7 +1087,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { &impl_item.attrs, ); } - ast::AssocItemKind::Fn(ref sig, ref generics, ref body) => { + ast::AssocItemKind::Fn(_, ref sig, ref generics, ref body) => { self.process_method( sig, body.as_deref(), @@ -1098,8 +1098,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { impl_item.span, ); } - ast::AssocItemKind::TyAlias(_, _, None) => {} - ast::AssocItemKind::TyAlias(_, _, Some(ref ty)) => { + ast::AssocItemKind::TyAlias(_, _, _, None) => {} + ast::AssocItemKind::TyAlias(_, _, _, Some(ref ty)) => { // FIXME: uses of the assoc type should ideally point to this // 'def' and the name here should be a ref to the def in the // trait. @@ -1292,11 +1292,11 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { ); } } - Fn(ref sig, ref ty_params, ref body) => { + Fn(_, ref sig, ref ty_params, ref body) => { self.process_fn(item, &sig.decl, &sig.header, ty_params, body.as_deref()) } Static(ref typ, _, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), - Const(ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), + Const(_, ref typ, ref e) => self.process_static_or_const_item(item, typ, e.as_deref()), Struct(ref def, ref ty_params) | Union(ref def, ref ty_params) => { self.process_struct(item, def, ty_params) } @@ -1311,7 +1311,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.process_mod(item); visit::walk_mod(self, m); } - TyAlias(ref ty_params, _, ref ty) => { + TyAlias(_, ref ty_params, _, ref ty) => { let qualname = format!( "::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) @@ -1520,7 +1520,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { let access = access_from!(self.save_ctxt, item, hir_id); match item.kind { - ast::ForeignItemKind::Fn(ref sig, ref generics, _) => { + ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => { let decl = &sig.decl; if let Some(fn_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(fn_data, DefData, item.span); @@ -1537,7 +1537,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(_, ref ty, _) + | ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 43a0cfecd3e..b253559dd5c 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -133,7 +133,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) ); match item.kind { - ast::ForeignItemKind::Fn(ref sig, ref generics, _) => { + ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => { filter!(self.span_utils, item.ident.span); Some(Data::DefData(Def { @@ -151,7 +151,8 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Const(ref ty, _) | ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Const(_, ref ty, _) + | ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); @@ -180,7 +181,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { pub fn get_item_data(&self, item: &ast::Item) -> Option { match item.kind { - ast::ItemKind::Fn(ref sig, .., ref generics, _) => { + ast::ItemKind::Fn(_, ref sig, .., ref generics, _) => { let qualname = format!( "::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) @@ -227,7 +228,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ItemKind::Const(ref typ, _) => { + ast::ItemKind::Const(_, ref typ, _) => { let qualname = format!( "::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id)) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index a7a10c0be0d..9670fb1e2c4 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -345,7 +345,7 @@ impl Sig for ast::Item { Ok(extend_sig(ty, text, defs, vec![])) } - ast::ItemKind::Const(ref ty, ref expr) => { + ast::ItemKind::Const(_, ref ty, ref expr) => { let mut text = "const ".to_owned(); let name = self.ident.to_string(); let defs = vec![SigElement { @@ -369,7 +369,7 @@ impl Sig for ast::Item { Ok(extend_sig(ty, text, defs, vec![])) } - ast::ItemKind::Fn(ast::FnSig { ref decl, header }, ref generics, _) => { + ast::ItemKind::Fn(_, ast::FnSig { ref decl, header }, ref generics, _) => { let mut text = String::new(); if let ast::Const::Yes(_) = header.constness { text.push_str("const "); @@ -423,7 +423,7 @@ impl Sig for ast::Item { Ok(Signature { text, defs, refs: vec![] }) } - ast::ItemKind::TyAlias(ref generics, _, ref ty) => { + ast::ItemKind::TyAlias(_, ref generics, _, ref ty) => { let text = "type ".to_owned(); let mut sig = name_and_generics(text, offset, generics, self.id, self.ident, scx)?; @@ -732,7 +732,7 @@ impl Sig for ast::ForeignItem { fn make(&self, offset: usize, _parent_id: Option, scx: &SaveContext<'_, '_>) -> Result { let id = Some(self.id); match self.kind { - ast::ForeignItemKind::Fn(ref sig, ref generics, _) => { + ast::ForeignItemKind::Fn(_, ref sig, ref generics, _) => { let decl = &sig.decl; let mut text = String::new(); text.push_str("fn "); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index f8a27cf7142..19c705fa997 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -2421,9 +2421,6 @@ pub struct Item { /// The name of the item. /// It might be a dummy name in case of anonymous items. pub ident: Ident, - /// The `default`ness of this item. - /// This should only occur in syntactically well-formed code in associated contexts. - pub defaultness: Defaultness, pub kind: K, @@ -2509,11 +2506,11 @@ pub enum ItemKind { /// A constant item (`const`). /// /// E.g., `const FOO: i32 = 42;`. - Const(P, Option>), + Const(Defaultness, P, Option>), /// A function declaration (`fn`). /// /// E.g., `fn foo(bar: usize) -> usize { .. }`. - Fn(FnSig, Generics, Option>), + Fn(Defaultness, FnSig, Generics, Option>), /// A module declaration (`mod`). /// /// E.g., `mod foo;` or `mod foo { .. }`. @@ -2527,7 +2524,7 @@ pub enum ItemKind { /// A type alias (`type`). /// /// E.g., `type Foo = Bar;`. - TyAlias(Generics, GenericBounds, Option>), + TyAlias(Defaultness, Generics, GenericBounds, Option>), /// An enum definition (`enum`). /// /// E.g., `enum Foo { C, D }`. @@ -2607,8 +2604,8 @@ impl ItemKind { pub fn generics(&self) -> Option<&Generics> { match self { - Self::Fn(_, generics, _) - | Self::TyAlias(generics, ..) + Self::Fn(_, _, generics, _) + | Self::TyAlias(_, generics, ..) | Self::Enum(_, generics) | Self::Struct(_, generics) | Self::Union(_, generics) @@ -2640,13 +2637,22 @@ pub type AssocItem = Item; pub enum AssocItemKind { /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. - Const(P, Option>), + Const(Defaultness, P, Option>), /// A static item (`static FOO: u8`). Static(P, Mutability, Option>), /// A function. - Fn(FnSig, Generics, Option>), + Fn(Defaultness, FnSig, Generics, Option>), /// A type. - TyAlias(Generics, GenericBounds, Option>), + TyAlias(Defaultness, Generics, GenericBounds, Option>), /// A macro expanding to items. Macro(Mac), } + +impl AssocItemKind { + pub fn defaultness(&self) -> Defaultness { + match *self { + Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def, + Self::Macro(..) | Self::Static(..) => Defaultness::Final, + } + } +} diff --git a/src/libsyntax/mut_visit.rs b/src/libsyntax/mut_visit.rs index 048026cbb24..05bb07cd4b9 100644 --- a/src/libsyntax/mut_visit.rs +++ b/src/libsyntax/mut_visit.rs @@ -890,11 +890,11 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { match kind { ItemKind::ExternCrate(_orig_name) => {} ItemKind::Use(use_tree) => vis.visit_use_tree(use_tree), - ItemKind::Static(ty, _, expr) | ItemKind::Const(ty, expr) => { + ItemKind::Static(ty, _, expr) | ItemKind::Const(_, ty, expr) => { vis.visit_ty(ty); visit_opt(expr, |expr| vis.visit_expr(expr)); } - ItemKind::Fn(sig, generics, body) => { + ItemKind::Fn(_, sig, generics, body) => { visit_fn_sig(sig, vis); vis.visit_generics(generics); visit_opt(body, |body| vis.visit_block(body)); @@ -902,7 +902,7 @@ pub fn noop_visit_item_kind(kind: &mut ItemKind, vis: &mut T) { ItemKind::Mod(m) => vis.visit_mod(m), ItemKind::ForeignMod(nm) => vis.visit_foreign_mod(nm), ItemKind::GlobalAsm(_ga) => {} - ItemKind::TyAlias(generics, bounds, ty) => { + ItemKind::TyAlias(_, generics, bounds, ty) => { vis.visit_generics(generics); visit_bounds(bounds, vis); visit_opt(ty, |ty| vis.visit_ty(ty)); @@ -948,7 +948,7 @@ pub fn noop_flat_map_assoc_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let Item { id, ident, vis, defaultness: _, attrs, kind, span, tokens: _ } = item.deref_mut(); + let Item { id, ident, vis, attrs, kind, span, tokens: _ } = item.deref_mut(); walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } @@ -967,16 +967,16 @@ pub fn walk_nested_item( visitor.visit_vis(vis); visit_attrs(attrs, visitor); match kind { - AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { + AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } - AssocItemKind::Fn(sig, generics, body) => { + AssocItemKind::Fn(_, sig, generics, body) => { visitor.visit_generics(generics); visit_fn_sig(sig, visitor); visit_opt(body, |body| visitor.visit_block(body)); } - AssocItemKind::TyAlias(generics, bounds, ty) => { + AssocItemKind::TyAlias(_, generics, bounds, ty) => { visitor.visit_generics(generics); visit_bounds(bounds, visitor); visit_opt(ty, |ty| visitor.visit_ty(ty)); @@ -1003,7 +1003,6 @@ pub fn noop_visit_crate(krate: &mut Crate, vis: &mut T) { attrs, id: DUMMY_NODE_ID, vis: respan(span.shrink_to_lo(), VisibilityKind::Public), - defaultness: Defaultness::Final, span, kind: ItemKind::Mod(module), tokens: None, @@ -1031,7 +1030,7 @@ pub fn noop_flat_map_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut(); + let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); visitor.visit_ident(ident); visit_attrs(attrs, visitor); visitor.visit_id(id); @@ -1049,7 +1048,7 @@ pub fn noop_flat_map_foreign_item( mut item: P, visitor: &mut T, ) -> SmallVec<[P; 1]> { - let Item { ident, attrs, id, kind, vis, defaultness: _, span, tokens: _ } = item.deref_mut(); + let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); walk_nested_item(visitor, id, span, ident, vis, attrs, kind); smallvec![item] } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 244cb80064e..96149ad7947 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -298,11 +298,11 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { } } ItemKind::Use(ref use_tree) => visitor.visit_use_tree(use_tree, item.id, false), - ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(ref typ, ref expr) => { + ItemKind::Static(ref typ, _, ref expr) | ItemKind::Const(_, ref typ, ref expr) => { visitor.visit_ty(typ); walk_list!(visitor, visit_expr, expr); } - ItemKind::Fn(ref sig, ref generics, ref body) => { + ItemKind::Fn(_, ref sig, ref generics, ref body) => { visitor.visit_generics(generics); let kind = FnKind::Fn(FnCtxt::Free, item.ident, sig, &item.vis, body.as_deref()); visitor.visit_fn(kind, item.span, item.id) @@ -312,7 +312,7 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) { walk_list!(visitor, visit_foreign_item, &foreign_module.items); } ItemKind::GlobalAsm(ref ga) => visitor.visit_global_asm(ga), - ItemKind::TyAlias(ref generics, ref bounds, ref ty) => { + ItemKind::TyAlias(_, ref generics, ref bounds, ref ty) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); @@ -526,7 +526,7 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - let ForeignItem { id, span, ident, vis, defaultness: _, attrs, kind, tokens: _ } = item; + let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign); } @@ -610,7 +610,7 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa } pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { - let AssocItem { id, span, ident, vis, attrs, kind, tokens: _, defaultness: _ } = item; + let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt)); } @@ -628,16 +628,16 @@ fn walk_nested_item<'a, V: Visitor<'a>>( visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); match kind { - AssocItemKind::Const(ty, expr) | AssocItemKind::Static(ty, _, expr) => { + AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } - AssocItemKind::Fn(sig, generics, body) => { + AssocItemKind::Fn(_, sig, generics, body) => { visitor.visit_generics(generics); let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref()); visitor.visit_fn(kind, span, id); } - AssocItemKind::TyAlias(generics, bounds, ty) => { + AssocItemKind::TyAlias(_, generics, bounds, ty) => { visitor.visit_generics(generics); walk_list!(visitor, visit_param_bound, bounds); walk_list!(visitor, visit_ty, ty); diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout index bbda63955e0..35e418696f1 100644 --- a/src/test/ui/ast-json/ast-json-output.stdout +++ b/src/test/ui/ast-json/ast-json-output.stdout @@ -1 +1 @@ -{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"defaultness":"Final","kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]} +{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[],"span":{"lo":0,"hi":0},"proc_macros":[]} diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs index da4015a4620..215a2921315 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.rs +++ b/src/test/ui/parser/assoc-static-semantic-fail.rs @@ -13,9 +13,11 @@ impl S { //~| ERROR associated constant in `impl` without body default static IC: u8 = 0; //~^ ERROR associated `static` items are not allowed + //~| ERROR a static item cannot be `default` pub(crate) default static ID: u8; //~^ ERROR associated `static` items are not allowed //~| ERROR associated constant in `impl` without body + //~| ERROR a static item cannot be `default` } trait T { @@ -25,11 +27,11 @@ trait T { //~^ ERROR associated `static` items are not allowed default static TC: u8 = 0; //~^ ERROR associated `static` items are not allowed - //~| ERROR `default` is only allowed on items in + //~| ERROR a static item cannot be `default` pub(crate) default static TD: u8; //~^ ERROR associated `static` items are not allowed - //~| ERROR `default` is only allowed on items in //~| ERROR unnecessary visibility qualifier + //~| ERROR a static item cannot be `default` } impl T for S { @@ -40,8 +42,10 @@ impl T for S { //~| ERROR associated constant in `impl` without body default static TC: u8 = 0; //~^ ERROR associated `static` items are not allowed + //~| ERROR a static item cannot be `default` pub default static TD: u8; //~^ ERROR associated `static` items are not allowed //~| ERROR associated constant in `impl` without body //~| ERROR unnecessary visibility qualifier + //~| ERROR a static item cannot be `default` } diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr index ca05b05e9b1..612297c9cd8 100644 --- a/src/test/ui/parser/assoc-static-semantic-fail.stderr +++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr @@ -10,62 +10,110 @@ error: associated `static` items are not allowed LL | static IB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:14:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed --> $DIR/assoc-static-semantic-fail.rs:14:5 | LL | default static IC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:17:16 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:16:5 + --> $DIR/assoc-static-semantic-fail.rs:17:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:22:5 + --> $DIR/assoc-static-semantic-fail.rs:24:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:24:5 + --> $DIR/assoc-static-semantic-fail.rs:26:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:28:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:26:5 + --> $DIR/assoc-static-semantic-fail.rs:28:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:31:16 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:29:5 + --> $DIR/assoc-static-semantic-fail.rs:31:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:36:5 + --> $DIR/assoc-static-semantic-fail.rs:38:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:38:5 + --> $DIR/assoc-static-semantic-fail.rs:40:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:43:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:41:5 + --> $DIR/assoc-static-semantic-fail.rs:43:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-semantic-fail.rs:46:9 + | +LL | pub default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-semantic-fail.rs:43:5 + --> $DIR/assoc-static-semantic-fail.rs:46:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -79,37 +127,21 @@ LL | static IB: u8; | help: provide a definition for the constant: `= ;` error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:16:5 + --> $DIR/assoc-static-semantic-fail.rs:17:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- | | | help: provide a definition for the constant: `= ;` -error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:26:5 - | -LL | default static TC: u8 = 0; - | -------^^^^^^^^^^^^^^^^^^^ - | | - | `default` because of this - -error: `default` is only allowed on items in `impl` definitions - --> $DIR/assoc-static-semantic-fail.rs:29:5 - | -LL | pub(crate) default static TD: u8; - | ^^^^^^^^^^^-------^^^^^^^^^^^^^^^ - | | - | `default` because of this - error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:29:5 + --> $DIR/assoc-static-semantic-fail.rs:31:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^ error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:38:5 + --> $DIR/assoc-static-semantic-fail.rs:40:5 | LL | static TB: u8; | ^^^^^^^^^^^^^- @@ -117,7 +149,7 @@ LL | static TB: u8; | help: provide a definition for the constant: `= ;` error: associated constant in `impl` without body - --> $DIR/assoc-static-semantic-fail.rs:43:5 + --> $DIR/assoc-static-semantic-fail.rs:46:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -125,11 +157,11 @@ LL | pub default static TD: u8; | help: provide a definition for the constant: `= ;` error[E0449]: unnecessary visibility qualifier - --> $DIR/assoc-static-semantic-fail.rs:43:5 + --> $DIR/assoc-static-semantic-fail.rs:46:5 | LL | pub default static TD: u8; | ^^^ `pub` not permitted here because it's implied -error: aborting due to 20 previous errors +error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0449`. diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.rs b/src/test/ui/parser/assoc-static-syntactic-fail.rs index 8f042767e55..492f2ea16ef 100644 --- a/src/test/ui/parser/assoc-static-syntactic-fail.rs +++ b/src/test/ui/parser/assoc-static-syntactic-fail.rs @@ -7,7 +7,9 @@ impl S { static IA: u8 = 0; //~ ERROR associated `static` items are not allowed static IB: u8; //~ ERROR associated `static` items are not allowed default static IC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` pub(crate) default static ID: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` } #[cfg(FALSE)] @@ -15,7 +17,9 @@ trait T { static TA: u8 = 0; //~ ERROR associated `static` items are not allowed static TB: u8; //~ ERROR associated `static` items are not allowed default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` pub(crate) default static TD: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` } #[cfg(FALSE)] @@ -23,5 +27,7 @@ impl T for S { static TA: u8 = 0; //~ ERROR associated `static` items are not allowed static TB: u8; //~ ERROR associated `static` items are not allowed default static TC: u8 = 0; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` pub default static TD: u8; //~ ERROR associated `static` items are not allowed + //~^ ERROR a static item cannot be `default` } diff --git a/src/test/ui/parser/assoc-static-syntactic-fail.stderr b/src/test/ui/parser/assoc-static-syntactic-fail.stderr index bb1e5c4be2e..e9723614512 100644 --- a/src/test/ui/parser/assoc-static-syntactic-fail.stderr +++ b/src/test/ui/parser/assoc-static-syntactic-fail.stderr @@ -10,65 +10,113 @@ error: associated `static` items are not allowed LL | static IB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:9:5 + | +LL | default static IC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed --> $DIR/assoc-static-syntactic-fail.rs:9:5 | LL | default static IC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:11:16 + | +LL | pub(crate) default static ID: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:10:5 + --> $DIR/assoc-static-syntactic-fail.rs:11:5 | LL | pub(crate) default static ID: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:15:5 + --> $DIR/assoc-static-syntactic-fail.rs:17:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:16:5 + --> $DIR/assoc-static-syntactic-fail.rs:18:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:19:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:17:5 + --> $DIR/assoc-static-syntactic-fail.rs:19:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:21:16 + | +LL | pub(crate) default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:18:5 + --> $DIR/assoc-static-syntactic-fail.rs:21:5 | LL | pub(crate) default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:23:5 + --> $DIR/assoc-static-syntactic-fail.rs:27:5 | LL | static TA: u8 = 0; | ^^^^^^^^^^^^^^^^^^ error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:24:5 + --> $DIR/assoc-static-syntactic-fail.rs:28:5 | LL | static TB: u8; | ^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:29:5 + | +LL | default static TC: u8 = 0; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:25:5 + --> $DIR/assoc-static-syntactic-fail.rs:29:5 | LL | default static TC: u8 = 0; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/assoc-static-syntactic-fail.rs:31:9 + | +LL | pub default static TD: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed - --> $DIR/assoc-static-syntactic-fail.rs:26:5 + --> $DIR/assoc-static-syntactic-fail.rs:31:5 | LL | pub default static TD: u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 18 previous errors diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 47b9e34305f..982ee6d83b3 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -6,135 +6,135 @@ fn main() {} #[cfg(FALSE)] mod free_items { - default extern crate foo; //~ ERROR item cannot be `default` - default use foo; //~ ERROR item cannot be `default` - default static foo: u8; //~ ERROR item cannot be `default` - default const foo: u8; //~ ERROR item cannot be `default` - default fn foo(); //~ ERROR item cannot be `default` - default mod foo {} //~ ERROR item cannot be `default` - default extern "C" {} //~ ERROR item cannot be `default` - default type foo = u8; //~ ERROR item cannot be `default` - default enum foo {} //~ ERROR item cannot be `default` - default struct foo {} //~ ERROR item cannot be `default` - default union foo {} //~ ERROR item cannot be `default` - default trait foo {} //~ ERROR item cannot be `default` - default trait foo = Ord; //~ ERROR item cannot be `default` + default extern crate foo; //~ ERROR an extern crate cannot be `default` + default use foo; //~ ERROR a `use` import cannot be `default` + default static foo: u8; //~ ERROR a static item cannot be `default` + default const foo: u8; + default fn foo(); + default mod foo {} //~ ERROR a module cannot be `default` + default extern "C" {} //~ ERROR an extern block cannot be `default` + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` + default struct foo {} //~ ERROR a struct cannot be `default` + default union foo {} //~ ERROR a union cannot be `default` + default trait foo {} //~ ERROR a trait cannot be `default` + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` default impl foo {} default!(); default::foo::bar!(); - default default!(); //~ ERROR item cannot be `default` - default default::foo::bar!(); //~ ERROR item cannot be `default` - default macro foo {} //~ ERROR item cannot be `default` - default macro_rules! foo {} //~ ERROR item cannot be `default` + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` } #[cfg(FALSE)] extern "C" { - default extern crate foo; //~ ERROR item cannot be `default` + default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate not supported in `extern` block - default use foo; //~ ERROR item cannot be `default` + default use foo; //~ ERROR a `use` import cannot be `default` //~^ ERROR `use` import not supported in `extern` block - default static foo: u8; //~ ERROR item cannot be `default` - default const foo: u8; //~ ERROR item cannot be `default` + default static foo: u8; //~ ERROR a static item cannot be `default` + default const foo: u8; //~^ ERROR extern items cannot be `const` - default fn foo(); //~ ERROR item cannot be `default` - default mod foo {} //~ ERROR item cannot be `default` + default fn foo(); + default mod foo {} //~ ERROR a module cannot be `default` //~^ ERROR module not supported in `extern` block - default extern "C" {} //~ ERROR item cannot be `default` + default extern "C" {} //~ ERROR an extern block cannot be `default` //~^ ERROR extern block not supported in `extern` block - default type foo = u8; //~ ERROR item cannot be `default` - default enum foo {} //~ ERROR item cannot be `default` + default type foo = u8; + default enum foo {} //~ ERROR an enum cannot be `default` //~^ ERROR enum not supported in `extern` block - default struct foo {} //~ ERROR item cannot be `default` + default struct foo {} //~ ERROR a struct cannot be `default` //~^ ERROR struct not supported in `extern` block - default union foo {} //~ ERROR item cannot be `default` + default union foo {} //~ ERROR a union cannot be `default` //~^ ERROR union not supported in `extern` block - default trait foo {} //~ ERROR item cannot be `default` + default trait foo {} //~ ERROR a trait cannot be `default` //~^ ERROR trait not supported in `extern` block - default trait foo = Ord; //~ ERROR item cannot be `default` + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias not supported in `extern` block default impl foo {} //~^ ERROR implementation not supported in `extern` block default!(); default::foo::bar!(); - default default!(); //~ ERROR item cannot be `default` - default default::foo::bar!(); //~ ERROR item cannot be `default` - default macro foo {} //~ ERROR item cannot be `default` + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `extern` block - default macro_rules! foo {} //~ ERROR item cannot be `default` + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `extern` block } #[cfg(FALSE)] impl S { - default extern crate foo; + default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate not supported in `trait` or `impl` - default use foo; + default use foo; //~ ERROR a `use` import cannot be `default` //~^ ERROR `use` import not supported in `trait` or `impl` - default static foo: u8; + default static foo: u8; //~ ERROR a static item cannot be `default` //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); - default mod foo {} + default mod foo {}//~ ERROR a module cannot be `default` //~^ ERROR module not supported in `trait` or `impl` - default extern "C" {} + default extern "C" {} //~ ERROR an extern block cannot be `default` //~^ ERROR extern block not supported in `trait` or `impl` default type foo = u8; - default enum foo {} + default enum foo {} //~ ERROR an enum cannot be `default` //~^ ERROR enum not supported in `trait` or `impl` - default struct foo {} + default struct foo {} //~ ERROR a struct cannot be `default` //~^ ERROR struct not supported in `trait` or `impl` - default union foo {} + default union foo {} //~ ERROR a union cannot be `default` //~^ ERROR union not supported in `trait` or `impl` - default trait foo {} + default trait foo {} //~ ERROR a trait cannot be `default` //~^ ERROR trait not supported in `trait` or `impl` - default trait foo = Ord; + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias not supported in `trait` or `impl` default impl foo {} //~^ ERROR implementation not supported in `trait` or `impl` default!(); default::foo::bar!(); - default default!(); - default default::foo::bar!(); - default macro foo {} + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `trait` or `impl` - default macro_rules! foo {} + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `trait` or `impl` } #[cfg(FALSE)] trait T { - default extern crate foo; + default extern crate foo; //~ ERROR an extern crate cannot be `default` //~^ ERROR extern crate not supported in `trait` or `impl` - default use foo; + default use foo; //~ ERROR a `use` import cannot be `default` //~^ ERROR `use` import not supported in `trait` or `impl` - default static foo: u8; + default static foo: u8; //~ ERROR a static item cannot be `default` //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); - default mod foo {} + default mod foo {}//~ ERROR a module cannot be `default` //~^ ERROR module not supported in `trait` or `impl` - default extern "C" {} + default extern "C" {} //~ ERROR an extern block cannot be `default` //~^ ERROR extern block not supported in `trait` or `impl` default type foo = u8; - default enum foo {} + default enum foo {} //~ ERROR an enum cannot be `default` //~^ ERROR enum not supported in `trait` or `impl` - default struct foo {} + default struct foo {} //~ ERROR a struct cannot be `default` //~^ ERROR struct not supported in `trait` or `impl` - default union foo {} + default union foo {} //~ ERROR a union cannot be `default` //~^ ERROR union not supported in `trait` or `impl` - default trait foo {} + default trait foo {} //~ ERROR a trait cannot be `default` //~^ ERROR trait not supported in `trait` or `impl` - default trait foo = Ord; + default trait foo = Ord; //~ ERROR a trait alias cannot be `default` //~^ ERROR trait alias not supported in `trait` or `impl` default impl foo {} //~^ ERROR implementation not supported in `trait` or `impl` default!(); default::foo::bar!(); - default default!(); - default default::foo::bar!(); - default macro foo {} + default default!(); //~ ERROR an item macro invocation cannot be `default` + default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` + default macro foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `trait` or `impl` - default macro_rules! foo {} + default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` //~^ ERROR macro definition not supported in `trait` or `impl` } diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index ec569b43d70..d0f3ad4d72b 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -1,4 +1,4 @@ -error: item cannot be `default` +error: an extern crate cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:9:5 | LL | default extern crate foo; @@ -6,7 +6,7 @@ LL | default extern crate foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a `use` import cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:10:5 | LL | default use foo; @@ -14,7 +14,7 @@ LL | default use foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a static item cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:11:5 | LL | default static foo: u8; @@ -22,23 +22,7 @@ LL | default static foo: u8; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:12:5 - | -LL | default const foo: u8; - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:13:5 - | -LL | default fn foo(); - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - -error: item cannot be `default` +error: a module cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:14:5 | LL | default mod foo {} @@ -46,7 +30,7 @@ LL | default mod foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: an extern block cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:15:5 | LL | default extern "C" {} @@ -54,15 +38,7 @@ LL | default extern "C" {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:16:5 - | -LL | default type foo = u8; - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - -error: item cannot be `default` +error: an enum cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:17:5 | LL | default enum foo {} @@ -70,7 +46,7 @@ LL | default enum foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a struct cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:18:5 | LL | default struct foo {} @@ -78,7 +54,7 @@ LL | default struct foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a union cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:19:5 | LL | default union foo {} @@ -86,7 +62,7 @@ LL | default union foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a trait cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:20:5 | LL | default trait foo {} @@ -94,7 +70,7 @@ LL | default trait foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a trait alias cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:21:5 | LL | default trait foo = Ord; @@ -102,7 +78,7 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: an item macro invocation cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:25:5 | LL | default default!(); @@ -110,7 +86,7 @@ LL | default default!(); | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: an item macro invocation cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:26:5 | LL | default default::foo::bar!(); @@ -118,7 +94,7 @@ LL | default default::foo::bar!(); | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a macro definition cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:27:5 | LL | default macro foo {} @@ -126,7 +102,7 @@ LL | default macro foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a macro definition cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:28:5 | LL | default macro_rules! foo {} @@ -134,7 +110,7 @@ LL | default macro_rules! foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: an extern crate cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:33:5 | LL | default extern crate foo; @@ -148,7 +124,7 @@ error: extern crate not supported in `extern` block LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a `use` import cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:35:5 | LL | default use foo; @@ -162,7 +138,7 @@ error: `use` import not supported in `extern` block LL | default use foo; | ^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a static item cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:37:5 | LL | default static foo: u8; @@ -170,14 +146,6 @@ LL | default static foo: u8; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:38:5 - | -LL | default const foo: u8; - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - error: extern items cannot be `const` --> $DIR/default-on-wrong-item-kind.rs:38:19 | @@ -188,15 +156,7 @@ LL | default const foo: u8; | = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:40:5 - | -LL | default fn foo(); - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - -error: item cannot be `default` +error: a module cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:41:5 | LL | default mod foo {} @@ -210,7 +170,7 @@ error: module not supported in `extern` block LL | default mod foo {} | ^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: an extern block cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:43:5 | LL | default extern "C" {} @@ -224,15 +184,7 @@ error: extern block not supported in `extern` block LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ -error: item cannot be `default` - --> $DIR/default-on-wrong-item-kind.rs:45:5 - | -LL | default type foo = u8; - | ^^^^^^^ `default` because of this - | - = note: only associated `fn`, `const`, and `type` items can be `default` - -error: item cannot be `default` +error: an enum cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:46:5 | LL | default enum foo {} @@ -246,7 +198,7 @@ error: enum not supported in `extern` block LL | default enum foo {} | ^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a struct cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:48:5 | LL | default struct foo {} @@ -260,7 +212,7 @@ error: struct not supported in `extern` block LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a union cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:50:5 | LL | default union foo {} @@ -274,7 +226,7 @@ error: union not supported in `extern` block LL | default union foo {} | ^^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a trait cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:52:5 | LL | default trait foo {} @@ -288,7 +240,7 @@ error: trait not supported in `extern` block LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a trait alias cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:54:5 | LL | default trait foo = Ord; @@ -308,7 +260,7 @@ error: implementation not supported in `extern` block LL | default impl foo {} | ^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: an item macro invocation cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:60:5 | LL | default default!(); @@ -316,7 +268,7 @@ LL | default default!(); | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: an item macro invocation cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:61:5 | LL | default default::foo::bar!(); @@ -324,7 +276,7 @@ LL | default default::foo::bar!(); | = note: only associated `fn`, `const`, and `type` items can be `default` -error: item cannot be `default` +error: a macro definition cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:62:5 | LL | default macro foo {} @@ -338,7 +290,7 @@ error: macro definition not supported in `extern` block LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ -error: item cannot be `default` +error: a macro definition cannot be `default` --> $DIR/default-on-wrong-item-kind.rs:64:5 | LL | default macro_rules! foo {} @@ -352,60 +304,140 @@ error: macro definition not supported in `extern` block LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:70:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: extern crate not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:70:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:72:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: `use` import not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:72:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:74:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed --> $DIR/default-on-wrong-item-kind.rs:74:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:78:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: module not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:78:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:80:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: extern block not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:80:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:83:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: enum not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:83:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:85:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: struct not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:85:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:87:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: union not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:87:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:89:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: trait not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:89:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:91:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: trait alias not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:91:5 | @@ -418,72 +450,184 @@ error: implementation not supported in `trait` or `impl` LL | default impl foo {} | ^^^^^^^^^^^^^^^^ +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:97:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:98:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:99:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:99:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:101:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:101:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ +error: an extern crate cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:107:5 + | +LL | default extern crate foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: extern crate not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:107:5 | LL | default extern crate foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^ +error: a `use` import cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:109:5 + | +LL | default use foo; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: `use` import not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:109:5 | LL | default use foo; | ^^^^^^^^^^^^^^^^ +error: a static item cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:111:5 + | +LL | default static foo: u8; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: associated `static` items are not allowed --> $DIR/default-on-wrong-item-kind.rs:111:5 | LL | default static foo: u8; | ^^^^^^^^^^^^^^^^^^^^^^^ +error: a module cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:115:5 + | +LL | default mod foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: module not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:115:5 | LL | default mod foo {} | ^^^^^^^^^^^^^^^ +error: an extern block cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:117:5 + | +LL | default extern "C" {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: extern block not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:117:5 | LL | default extern "C" {} | ^^^^^^^^^^^^^^^^^^ +error: an enum cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:120:5 + | +LL | default enum foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: enum not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:120:5 | LL | default enum foo {} | ^^^^^^^^^^^^^^^^ +error: a struct cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:122:5 + | +LL | default struct foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: struct not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:122:5 | LL | default struct foo {} | ^^^^^^^^^^^^^^^^^^ +error: a union cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:124:5 + | +LL | default union foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: union not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:124:5 | LL | default union foo {} | ^^^^^^^^^^^^^^^^^ +error: a trait cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:126:5 + | +LL | default trait foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: trait not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:126:5 | LL | default trait foo {} | ^^^^^^^^^^^^^^^^^ +error: a trait alias cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:128:5 + | +LL | default trait foo = Ord; + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: trait alias not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:128:5 | @@ -496,17 +640,49 @@ error: implementation not supported in `trait` or `impl` LL | default impl foo {} | ^^^^^^^^^^^^^^^^ +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:134:5 + | +LL | default default!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: an item macro invocation cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:135:5 + | +LL | default default::foo::bar!(); + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:136:5 + | +LL | default macro foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:136:5 | LL | default macro foo {} | ^^^^^^^^^^^^^^^^^ +error: a macro definition cannot be `default` + --> $DIR/default-on-wrong-item-kind.rs:138:5 + | +LL | default macro_rules! foo {} + | ^^^^^^^ `default` because of this + | + = note: only associated `fn`, `const`, and `type` items can be `default` + error: macro definition not supported in `trait` or `impl` --> $DIR/default-on-wrong-item-kind.rs:138:5 | LL | default macro_rules! foo {} | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 73 previous errors +error: aborting due to 95 previous errors From e66a39bb65eb4a7fb1813993e10fc1af5bdac9bc Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 11:52:57 +0100 Subject: [PATCH 0480/1250] parse: tweak `parse_item_` for more reuse. --- src/librustc_parse/parser/item.rs | 24 +++++++----------------- src/librustc_parse/parser/stmt.rs | 4 ++-- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 451f1fdf14a..c85b4c22d01 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -25,21 +25,15 @@ pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { pub fn parse_item(&mut self) -> PResult<'a, Option>> { - let attrs = self.parse_outer_attributes()?; - self.parse_item_(attrs, true, false) + self.parse_item_(|_| true).map(|i| i.map(P)) } - pub(super) fn parse_item_( - &mut self, - attrs: Vec, - macros_allowed: bool, - attributes_allowed: bool, - ) -> PResult<'a, Option>> { - let item = self.parse_item_common(attrs, macros_allowed, attributes_allowed, |_| true)?; - Ok(item.map(P)) + fn parse_item_(&mut self, req_name: ReqName) -> PResult<'a, Option> { + let attrs = self.parse_outer_attributes()?; + self.parse_item_common(attrs, true, false, req_name) } - fn parse_item_common( + pub(super) fn parse_item_common( &mut self, mut attrs: Vec, mac_allowed: bool, @@ -653,9 +647,7 @@ impl<'a> Parser<'a> { /// Parses associated items. fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { - let attrs = self.parse_outer_attributes()?; - let it = self.parse_item_common(attrs, true, false, req_name)?; - Ok(it.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { + Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match kind { ItemKind::Mac(a) => AssocItemKind::Macro(a), ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), @@ -844,9 +836,7 @@ impl<'a> Parser<'a> { pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { maybe_whole!(self, NtForeignItem, |item| Some(Some(item))); - let attrs = self.parse_outer_attributes()?; - let item = self.parse_item_common(attrs, true, false, |_| true)?; - Ok(item.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { + Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { let kind = match kind { ItemKind::Mac(a) => ForeignItemKind::Macro(a), ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 0ce0e0df66a..bbfbe9c20df 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -81,11 +81,11 @@ impl<'a> Parser<'a> { // FIXME: Bad copy of attrs let old_directory_ownership = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_(attrs.clone(), false, true)?; + let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?; self.directory.ownership = old_directory_ownership; if let Some(item) = item { - return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(item)))); + return Ok(Some(self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))))); } // Do not attempt to parse an expression if we're done here. From fde5939d1c843c3ede7f6ea0eef704f52854b45d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 12:54:00 +0100 Subject: [PATCH 0481/1250] parse: tweak diagnostic wordings --- src/librustc_parse/parser/item.rs | 10 +-- .../ui/parser/default-on-wrong-item-kind.rs | 72 +++++++++---------- .../parser/default-on-wrong-item-kind.stderr | 72 +++++++++---------- src/test/ui/parser/default-unmatched-assoc.rs | 4 +- .../ui/parser/default-unmatched-assoc.stderr | 4 +- .../ui/parser/default-unmatched-extern.rs | 2 +- .../ui/parser/default-unmatched-extern.stderr | 2 +- src/test/ui/parser/default-unmatched.rs | 2 +- src/test/ui/parser/default-unmatched.stderr | 2 +- src/test/ui/parser/default.rs | 2 +- src/test/ui/parser/default.stderr | 2 +- src/test/ui/parser/duplicate-visibility.rs | 2 +- .../ui/parser/duplicate-visibility.stderr | 2 +- src/test/ui/parser/impl-parsing.rs | 2 +- src/test/ui/parser/impl-parsing.stderr | 2 +- src/test/ui/parser/issue-41155.rs | 2 +- src/test/ui/parser/issue-41155.stderr | 2 +- .../missing-close-brace-in-impl-trait.rs | 4 +- .../missing-close-brace-in-impl-trait.stderr | 4 +- .../missing-close-brace-in-trait.rs | 4 +- .../missing-close-brace-in-trait.stderr | 4 +- src/test/ui/pub/pub-restricted-error-fn.rs | 2 +- .../ui/pub/pub-restricted-error-fn.stderr | 2 +- 23 files changed, 103 insertions(+), 103 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index c85b4c22d01..d6da6270541 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -112,7 +112,7 @@ impl<'a> Parser<'a> { } let vs = pprust::vis_to_string(&vis); let vs = vs.trim_end(); - self.struct_span_err(vis.span, &format!("visibility `{}` not followed by an item", vs)) + self.struct_span_err(vis.span, &format!("visibility `{}` is not followed by an item", vs)) .span_label(vis.span, "the visibility") .help(&format!("you likely meant to define an item, e.g., `{} fn foo() {{}}`", vs)) .emit(); @@ -121,7 +121,7 @@ impl<'a> Parser<'a> { /// Error in-case a `default` was parsed but no item followed. fn error_on_unmatched_defaultness(&self, def: Defaultness) { if let Defaultness::Default(sp) = def { - self.struct_span_err(sp, "`default` not followed by an item") + self.struct_span_err(sp, "`default` is not followed by an item") .span_label(sp, "the `default` qualifier") .note("only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`") .emit(); @@ -657,7 +657,7 @@ impl<'a> Parser<'a> { self.struct_span_err(span, "associated `static` items are not allowed").emit(); AssocItemKind::Const(Defaultness::Final, a, b) } - _ => return self.error_bad_item_kind(span, &kind, "`trait` or `impl`"), + _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) @@ -846,7 +846,7 @@ impl<'a> Parser<'a> { self.error_on_foreign_const(span, ident); ForeignItemKind::Static(a, Mutability::Not, b) } - _ => return self.error_bad_item_kind(span, &kind, "`extern` block"), + _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) @@ -854,7 +854,7 @@ impl<'a> Parser<'a> { fn error_bad_item_kind(&self, span: Span, kind: &ItemKind, ctx: &str) -> Option { let span = self.sess.source_map().def_span(span); - let msg = format!("{} not supported in {}", kind.descr(), ctx); + let msg = format!("{} is not supported in {}", kind.descr(), ctx); self.struct_span_err(span, &msg).emit(); return None; } diff --git a/src/test/ui/parser/default-on-wrong-item-kind.rs b/src/test/ui/parser/default-on-wrong-item-kind.rs index 982ee6d83b3..98a95cfa35a 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.rs +++ b/src/test/ui/parser/default-on-wrong-item-kind.rs @@ -31,110 +31,110 @@ mod free_items { #[cfg(FALSE)] extern "C" { default extern crate foo; //~ ERROR an extern crate cannot be `default` - //~^ ERROR extern crate not supported in `extern` block + //~^ ERROR extern crate is not supported in `extern` blocks default use foo; //~ ERROR a `use` import cannot be `default` - //~^ ERROR `use` import not supported in `extern` block + //~^ ERROR `use` import is not supported in `extern` blocks default static foo: u8; //~ ERROR a static item cannot be `default` default const foo: u8; //~^ ERROR extern items cannot be `const` default fn foo(); default mod foo {} //~ ERROR a module cannot be `default` - //~^ ERROR module not supported in `extern` block + //~^ ERROR module is not supported in `extern` blocks default extern "C" {} //~ ERROR an extern block cannot be `default` - //~^ ERROR extern block not supported in `extern` block + //~^ ERROR extern block is not supported in `extern` blocks default type foo = u8; default enum foo {} //~ ERROR an enum cannot be `default` - //~^ ERROR enum not supported in `extern` block + //~^ ERROR enum is not supported in `extern` blocks default struct foo {} //~ ERROR a struct cannot be `default` - //~^ ERROR struct not supported in `extern` block + //~^ ERROR struct is not supported in `extern` blocks default union foo {} //~ ERROR a union cannot be `default` - //~^ ERROR union not supported in `extern` block + //~^ ERROR union is not supported in `extern` blocks default trait foo {} //~ ERROR a trait cannot be `default` - //~^ ERROR trait not supported in `extern` block + //~^ ERROR trait is not supported in `extern` blocks default trait foo = Ord; //~ ERROR a trait alias cannot be `default` - //~^ ERROR trait alias not supported in `extern` block + //~^ ERROR trait alias is not supported in `extern` blocks default impl foo {} - //~^ ERROR implementation not supported in `extern` block + //~^ ERROR implementation is not supported in `extern` blocks default!(); default::foo::bar!(); default default!(); //~ ERROR an item macro invocation cannot be `default` default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` default macro foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `extern` block + //~^ ERROR macro definition is not supported in `extern` blocks default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `extern` block + //~^ ERROR macro definition is not supported in `extern` blocks } #[cfg(FALSE)] impl S { default extern crate foo; //~ ERROR an extern crate cannot be `default` - //~^ ERROR extern crate not supported in `trait` or `impl` + //~^ ERROR extern crate is not supported in `trait`s or `impl`s default use foo; //~ ERROR a `use` import cannot be `default` - //~^ ERROR `use` import not supported in `trait` or `impl` + //~^ ERROR `use` import is not supported in `trait`s or `impl`s default static foo: u8; //~ ERROR a static item cannot be `default` //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); default mod foo {}//~ ERROR a module cannot be `default` - //~^ ERROR module not supported in `trait` or `impl` + //~^ ERROR module is not supported in `trait`s or `impl`s default extern "C" {} //~ ERROR an extern block cannot be `default` - //~^ ERROR extern block not supported in `trait` or `impl` + //~^ ERROR extern block is not supported in `trait`s or `impl`s default type foo = u8; default enum foo {} //~ ERROR an enum cannot be `default` - //~^ ERROR enum not supported in `trait` or `impl` + //~^ ERROR enum is not supported in `trait`s or `impl`s default struct foo {} //~ ERROR a struct cannot be `default` - //~^ ERROR struct not supported in `trait` or `impl` + //~^ ERROR struct is not supported in `trait`s or `impl`s default union foo {} //~ ERROR a union cannot be `default` - //~^ ERROR union not supported in `trait` or `impl` + //~^ ERROR union is not supported in `trait`s or `impl`s default trait foo {} //~ ERROR a trait cannot be `default` - //~^ ERROR trait not supported in `trait` or `impl` + //~^ ERROR trait is not supported in `trait`s or `impl`s default trait foo = Ord; //~ ERROR a trait alias cannot be `default` - //~^ ERROR trait alias not supported in `trait` or `impl` + //~^ ERROR trait alias is not supported in `trait`s or `impl`s default impl foo {} - //~^ ERROR implementation not supported in `trait` or `impl` + //~^ ERROR implementation is not supported in `trait`s or `impl`s default!(); default::foo::bar!(); default default!(); //~ ERROR an item macro invocation cannot be `default` default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` default macro foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `trait` or `impl` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `trait` or `impl` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s } #[cfg(FALSE)] trait T { default extern crate foo; //~ ERROR an extern crate cannot be `default` - //~^ ERROR extern crate not supported in `trait` or `impl` + //~^ ERROR extern crate is not supported in `trait`s or `impl`s default use foo; //~ ERROR a `use` import cannot be `default` - //~^ ERROR `use` import not supported in `trait` or `impl` + //~^ ERROR `use` import is not supported in `trait`s or `impl`s default static foo: u8; //~ ERROR a static item cannot be `default` //~^ ERROR associated `static` items are not allowed default const foo: u8; default fn foo(); default mod foo {}//~ ERROR a module cannot be `default` - //~^ ERROR module not supported in `trait` or `impl` + //~^ ERROR module is not supported in `trait`s or `impl`s default extern "C" {} //~ ERROR an extern block cannot be `default` - //~^ ERROR extern block not supported in `trait` or `impl` + //~^ ERROR extern block is not supported in `trait`s or `impl`s default type foo = u8; default enum foo {} //~ ERROR an enum cannot be `default` - //~^ ERROR enum not supported in `trait` or `impl` + //~^ ERROR enum is not supported in `trait`s or `impl`s default struct foo {} //~ ERROR a struct cannot be `default` - //~^ ERROR struct not supported in `trait` or `impl` + //~^ ERROR struct is not supported in `trait`s or `impl`s default union foo {} //~ ERROR a union cannot be `default` - //~^ ERROR union not supported in `trait` or `impl` + //~^ ERROR union is not supported in `trait`s or `impl`s default trait foo {} //~ ERROR a trait cannot be `default` - //~^ ERROR trait not supported in `trait` or `impl` + //~^ ERROR trait is not supported in `trait`s or `impl`s default trait foo = Ord; //~ ERROR a trait alias cannot be `default` - //~^ ERROR trait alias not supported in `trait` or `impl` + //~^ ERROR trait alias is not supported in `trait`s or `impl`s default impl foo {} - //~^ ERROR implementation not supported in `trait` or `impl` + //~^ ERROR implementation is not supported in `trait`s or `impl`s default!(); default::foo::bar!(); default default!(); //~ ERROR an item macro invocation cannot be `default` default default::foo::bar!(); //~ ERROR an item macro invocation cannot be `default` default macro foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `trait` or `impl` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s default macro_rules! foo {} //~ ERROR a macro definition cannot be `default` - //~^ ERROR macro definition not supported in `trait` or `impl` + //~^ ERROR macro definition is not supported in `trait`s or `impl`s } diff --git a/src/test/ui/parser/default-on-wrong-item-kind.stderr b/src/test/ui/parser/default-on-wrong-item-kind.stderr index d0f3ad4d72b..9788bd64725 100644 --- a/src/test/ui/parser/default-on-wrong-item-kind.stderr +++ b/src/test/ui/parser/default-on-wrong-item-kind.stderr @@ -118,7 +118,7 @@ LL | default extern crate foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern crate not supported in `extern` block +error: extern crate is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:33:5 | LL | default extern crate foo; @@ -132,7 +132,7 @@ LL | default use foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: `use` import not supported in `extern` block +error: `use` import is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:35:5 | LL | default use foo; @@ -164,7 +164,7 @@ LL | default mod foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: module not supported in `extern` block +error: module is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:41:5 | LL | default mod foo {} @@ -178,7 +178,7 @@ LL | default extern "C" {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern block not supported in `extern` block +error: extern block is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:43:5 | LL | default extern "C" {} @@ -192,7 +192,7 @@ LL | default enum foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: enum not supported in `extern` block +error: enum is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:46:5 | LL | default enum foo {} @@ -206,7 +206,7 @@ LL | default struct foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: struct not supported in `extern` block +error: struct is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:48:5 | LL | default struct foo {} @@ -220,7 +220,7 @@ LL | default union foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: union not supported in `extern` block +error: union is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:50:5 | LL | default union foo {} @@ -234,7 +234,7 @@ LL | default trait foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait not supported in `extern` block +error: trait is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:52:5 | LL | default trait foo {} @@ -248,13 +248,13 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait alias not supported in `extern` block +error: trait alias is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:54:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: implementation not supported in `extern` block +error: implementation is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:56:5 | LL | default impl foo {} @@ -284,7 +284,7 @@ LL | default macro foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `extern` block +error: macro definition is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:62:5 | LL | default macro foo {} @@ -298,7 +298,7 @@ LL | default macro_rules! foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `extern` block +error: macro definition is not supported in `extern` blocks --> $DIR/default-on-wrong-item-kind.rs:64:5 | LL | default macro_rules! foo {} @@ -312,7 +312,7 @@ LL | default extern crate foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern crate not supported in `trait` or `impl` +error: extern crate is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:70:5 | LL | default extern crate foo; @@ -326,7 +326,7 @@ LL | default use foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: `use` import not supported in `trait` or `impl` +error: `use` import is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:72:5 | LL | default use foo; @@ -354,7 +354,7 @@ LL | default mod foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: module not supported in `trait` or `impl` +error: module is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:78:5 | LL | default mod foo {} @@ -368,7 +368,7 @@ LL | default extern "C" {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern block not supported in `trait` or `impl` +error: extern block is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:80:5 | LL | default extern "C" {} @@ -382,7 +382,7 @@ LL | default enum foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: enum not supported in `trait` or `impl` +error: enum is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:83:5 | LL | default enum foo {} @@ -396,7 +396,7 @@ LL | default struct foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: struct not supported in `trait` or `impl` +error: struct is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:85:5 | LL | default struct foo {} @@ -410,7 +410,7 @@ LL | default union foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: union not supported in `trait` or `impl` +error: union is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:87:5 | LL | default union foo {} @@ -424,7 +424,7 @@ LL | default trait foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait not supported in `trait` or `impl` +error: trait is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:89:5 | LL | default trait foo {} @@ -438,13 +438,13 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait alias not supported in `trait` or `impl` +error: trait alias is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:91:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: implementation not supported in `trait` or `impl` +error: implementation is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:93:5 | LL | default impl foo {} @@ -474,7 +474,7 @@ LL | default macro foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `trait` or `impl` +error: macro definition is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:99:5 | LL | default macro foo {} @@ -488,7 +488,7 @@ LL | default macro_rules! foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `trait` or `impl` +error: macro definition is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:101:5 | LL | default macro_rules! foo {} @@ -502,7 +502,7 @@ LL | default extern crate foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern crate not supported in `trait` or `impl` +error: extern crate is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:107:5 | LL | default extern crate foo; @@ -516,7 +516,7 @@ LL | default use foo; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: `use` import not supported in `trait` or `impl` +error: `use` import is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:109:5 | LL | default use foo; @@ -544,7 +544,7 @@ LL | default mod foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: module not supported in `trait` or `impl` +error: module is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:115:5 | LL | default mod foo {} @@ -558,7 +558,7 @@ LL | default extern "C" {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: extern block not supported in `trait` or `impl` +error: extern block is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:117:5 | LL | default extern "C" {} @@ -572,7 +572,7 @@ LL | default enum foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: enum not supported in `trait` or `impl` +error: enum is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:120:5 | LL | default enum foo {} @@ -586,7 +586,7 @@ LL | default struct foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: struct not supported in `trait` or `impl` +error: struct is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:122:5 | LL | default struct foo {} @@ -600,7 +600,7 @@ LL | default union foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: union not supported in `trait` or `impl` +error: union is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:124:5 | LL | default union foo {} @@ -614,7 +614,7 @@ LL | default trait foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait not supported in `trait` or `impl` +error: trait is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:126:5 | LL | default trait foo {} @@ -628,13 +628,13 @@ LL | default trait foo = Ord; | = note: only associated `fn`, `const`, and `type` items can be `default` -error: trait alias not supported in `trait` or `impl` +error: trait alias is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:128:5 | LL | default trait foo = Ord; | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: implementation not supported in `trait` or `impl` +error: implementation is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:130:5 | LL | default impl foo {} @@ -664,7 +664,7 @@ LL | default macro foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `trait` or `impl` +error: macro definition is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:136:5 | LL | default macro foo {} @@ -678,7 +678,7 @@ LL | default macro_rules! foo {} | = note: only associated `fn`, `const`, and `type` items can be `default` -error: macro definition not supported in `trait` or `impl` +error: macro definition is not supported in `trait`s or `impl`s --> $DIR/default-on-wrong-item-kind.rs:138:5 | LL | default macro_rules! foo {} diff --git a/src/test/ui/parser/default-unmatched-assoc.rs b/src/test/ui/parser/default-unmatched-assoc.rs index 0c8ee0f7800..168ea3e76f6 100644 --- a/src/test/ui/parser/default-unmatched-assoc.rs +++ b/src/test/ui/parser/default-unmatched-assoc.rs @@ -3,7 +3,7 @@ fn main() {} trait Foo { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR `default` not followed by an item + //~^ ERROR `default` is not followed by an item //~| ERROR non-item in item list } @@ -11,6 +11,6 @@ struct S; impl S { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR `default` not followed by an item + //~^ ERROR `default` is not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default-unmatched-assoc.stderr b/src/test/ui/parser/default-unmatched-assoc.stderr index 22db46d63df..c8d1769cb5a 100644 --- a/src/test/ui/parser/default-unmatched-assoc.stderr +++ b/src/test/ui/parser/default-unmatched-assoc.stderr @@ -1,4 +1,4 @@ -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/default-unmatched-assoc.rs:5:5 | LL | default do @@ -18,7 +18,7 @@ LL | default do LL | } | - item list ends here -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/default-unmatched-assoc.rs:13:5 | LL | default do diff --git a/src/test/ui/parser/default-unmatched-extern.rs b/src/test/ui/parser/default-unmatched-extern.rs index 784df9bc77e..8d0ea590f57 100644 --- a/src/test/ui/parser/default-unmatched-extern.rs +++ b/src/test/ui/parser/default-unmatched-extern.rs @@ -3,6 +3,6 @@ fn main() {} extern "C" { default!(); //~ ERROR cannot find macro `default` in this scope default do - //~^ ERROR `default` not followed by an item + //~^ ERROR `default` is not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default-unmatched-extern.stderr b/src/test/ui/parser/default-unmatched-extern.stderr index ffbfbc73c18..bb4efd51631 100644 --- a/src/test/ui/parser/default-unmatched-extern.stderr +++ b/src/test/ui/parser/default-unmatched-extern.stderr @@ -1,4 +1,4 @@ -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/default-unmatched-extern.rs:5:5 | LL | default do diff --git a/src/test/ui/parser/default-unmatched.rs b/src/test/ui/parser/default-unmatched.rs index 796e184a0d8..49346e5c631 100644 --- a/src/test/ui/parser/default-unmatched.rs +++ b/src/test/ui/parser/default-unmatched.rs @@ -1,6 +1,6 @@ mod foo { default!(); // OK. default do - //~^ ERROR `default` not followed by an item + //~^ ERROR `default` is not followed by an item //~| ERROR expected item, found reserved keyword `do` } diff --git a/src/test/ui/parser/default-unmatched.stderr b/src/test/ui/parser/default-unmatched.stderr index 26012557761..331e003f63c 100644 --- a/src/test/ui/parser/default-unmatched.stderr +++ b/src/test/ui/parser/default-unmatched.stderr @@ -1,4 +1,4 @@ -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/default-unmatched.rs:3:5 | LL | default do diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs index 6cfa141478e..64ba4b55311 100644 --- a/src/test/ui/parser/default.rs +++ b/src/test/ui/parser/default.rs @@ -20,7 +20,7 @@ impl Foo for u16 { impl Foo for u32 { //~ ERROR not all trait items implemented, missing: `foo` default pub fn foo() -> T { T::default() } - //~^ ERROR `default` not followed by an item + //~^ ERROR `default` is not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr index 96b14b42767..15c49e8b627 100644 --- a/src/test/ui/parser/default.stderr +++ b/src/test/ui/parser/default.stderr @@ -1,4 +1,4 @@ -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/default.rs:22:5 | LL | default pub fn foo() -> T { T::default() } diff --git a/src/test/ui/parser/duplicate-visibility.rs b/src/test/ui/parser/duplicate-visibility.rs index edea2d1e5e2..31318ae3a09 100644 --- a/src/test/ui/parser/duplicate-visibility.rs +++ b/src/test/ui/parser/duplicate-visibility.rs @@ -2,6 +2,6 @@ fn main() {} extern { pub pub fn foo(); - //~^ ERROR visibility `pub` not followed by an item + //~^ ERROR visibility `pub` is not followed by an item //~| ERROR non-item in item list } diff --git a/src/test/ui/parser/duplicate-visibility.stderr b/src/test/ui/parser/duplicate-visibility.stderr index d8e38046a6c..36b9efd9dca 100644 --- a/src/test/ui/parser/duplicate-visibility.stderr +++ b/src/test/ui/parser/duplicate-visibility.stderr @@ -1,4 +1,4 @@ -error: visibility `pub` not followed by an item +error: visibility `pub` is not followed by an item --> $DIR/duplicate-visibility.rs:4:5 | LL | pub pub fn foo(); diff --git a/src/test/ui/parser/impl-parsing.rs b/src/test/ui/parser/impl-parsing.rs index c2ed7531a94..80ce8885570 100644 --- a/src/test/ui/parser/impl-parsing.rs +++ b/src/test/ui/parser/impl-parsing.rs @@ -7,4 +7,4 @@ impl ?Sized for Type {} //~ ERROR expected a trait, found type impl ?Sized for .. {} //~ ERROR expected a trait, found type default unsafe FAIL //~ ERROR expected item, found keyword `unsafe` -//~^ ERROR `default` not followed by an item +//~^ ERROR `default` is not followed by an item diff --git a/src/test/ui/parser/impl-parsing.stderr b/src/test/ui/parser/impl-parsing.stderr index ce673765aba..755addf1452 100644 --- a/src/test/ui/parser/impl-parsing.stderr +++ b/src/test/ui/parser/impl-parsing.stderr @@ -22,7 +22,7 @@ error: expected a trait, found type LL | impl ?Sized for .. {} | ^^^^^^ -error: `default` not followed by an item +error: `default` is not followed by an item --> $DIR/impl-parsing.rs:9:1 | LL | default unsafe FAIL diff --git a/src/test/ui/parser/issue-41155.rs b/src/test/ui/parser/issue-41155.rs index 5bfbe0c5e68..5a7488e6ffc 100644 --- a/src/test/ui/parser/issue-41155.rs +++ b/src/test/ui/parser/issue-41155.rs @@ -1,7 +1,7 @@ struct S; impl S { - pub //~ ERROR visibility `pub` not followed by an item + pub //~ ERROR visibility `pub` is not followed by an item } //~ ERROR non-item in item list fn main() {} diff --git a/src/test/ui/parser/issue-41155.stderr b/src/test/ui/parser/issue-41155.stderr index 09bbee51800..8491afae230 100644 --- a/src/test/ui/parser/issue-41155.stderr +++ b/src/test/ui/parser/issue-41155.stderr @@ -1,4 +1,4 @@ -error: visibility `pub` not followed by an item +error: visibility `pub` is not followed by an item --> $DIR/issue-41155.rs:4:5 | LL | pub diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs index b26e5134db6..8f46970b1af 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.rs @@ -4,10 +4,10 @@ impl T for () { //~ ERROR cannot find trait `T` in this scope fn foo(&self) {} -trait T { //~ ERROR trait not supported in `trait` or `impl` +trait T { //~ ERROR trait is not supported in `trait`s or `impl`s fn foo(&self); } -pub(crate) struct Bar(); //~ ERROR struct not supported in `trait` or `impl` +pub(crate) struct Bar(); //~ ERROR struct is not supported in `trait`s or `impl`s //~ ERROR this file contains an unclosed delimiter diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr index b1bd1a784be..1655a968395 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-impl-trait.stderr @@ -7,13 +7,13 @@ LL | impl T for () { LL | | ^ -error: trait not supported in `trait` or `impl` +error: trait is not supported in `trait`s or `impl`s --> $DIR/missing-close-brace-in-impl-trait.rs:7:1 | LL | trait T { | ^^^^^^^ -error: struct not supported in `trait` or `impl` +error: struct is not supported in `trait`s or `impl`s --> $DIR/missing-close-brace-in-impl-trait.rs:11:1 | LL | pub(crate) struct Bar(); diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs index d52add27398..b6932deb5c0 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.rs @@ -2,10 +2,10 @@ trait T { fn foo(&self); pub(crate) struct Bar(); -//~^ ERROR struct not supported in `trait` or `impl` +//~^ ERROR struct is not supported in `trait`s or `impl`s impl T for Bar { -//~^ ERROR implementation not supported in `trait` or `impl` +//~^ ERROR implementation is not supported in `trait`s or `impl`s fn foo(&self) {} } diff --git a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr index 49c685f2549..43a3883357a 100644 --- a/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr +++ b/src/test/ui/parser/mismatched-braces/missing-close-brace-in-trait.stderr @@ -7,13 +7,13 @@ LL | trait T { LL | fn main() {} | ^ -error: struct not supported in `trait` or `impl` +error: struct is not supported in `trait`s or `impl`s --> $DIR/missing-close-brace-in-trait.rs:4:1 | LL | pub(crate) struct Bar(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: implementation not supported in `trait` or `impl` +error: implementation is not supported in `trait`s or `impl`s --> $DIR/missing-close-brace-in-trait.rs:7:1 | LL | impl T for Bar { diff --git a/src/test/ui/pub/pub-restricted-error-fn.rs b/src/test/ui/pub/pub-restricted-error-fn.rs index 73806fdfe72..fc1aeae2b0c 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.rs +++ b/src/test/ui/pub/pub-restricted-error-fn.rs @@ -1,2 +1,2 @@ -pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` not followed by an item +pub(crate) () fn foo() {} //~ ERROR visibility `pub(crate)` is not followed by an item //~^ ERROR expected item, found `(` diff --git a/src/test/ui/pub/pub-restricted-error-fn.stderr b/src/test/ui/pub/pub-restricted-error-fn.stderr index 42d03941e41..0511a821a7a 100644 --- a/src/test/ui/pub/pub-restricted-error-fn.stderr +++ b/src/test/ui/pub/pub-restricted-error-fn.stderr @@ -1,4 +1,4 @@ -error: visibility `pub(crate)` not followed by an item +error: visibility `pub(crate)` is not followed by an item --> $DIR/pub-restricted-error-fn.rs:1:1 | LL | pub(crate) () fn foo() {} From 1c75f5aaa177734c8dbdab91612a8d59b519bf07 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 23 Feb 2020 13:04:46 +0100 Subject: [PATCH 0482/1250] parse: test bad variants wrt. issue 48137. --- ...not-interpolate-impl-items-bad-variants.rs | 44 +++++++++++++++ ...interpolate-impl-items-bad-variants.stderr | 53 +++++++++++++++++++ 2 files changed, 97 insertions(+) create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs create mode 100644 src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs new file mode 100644 index 00000000000..48a679b2d09 --- /dev/null +++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs @@ -0,0 +1,44 @@ +fn main() {} + +macro_rules! expand_to_enum { + () => { + enum BadE {} + //~^ ERROR enum is not supported in `trait`s or `impl`s + //~| ERROR enum is not supported in `trait`s or `impl`s + //~| ERROR enum is not supported in `extern` blocks + }; +} + +macro_rules! mac_impl { + ($($i:item)*) => { + struct S; + impl S { $($i)* } + } +} + +mac_impl! { + struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s + expand_to_enum!(); +} + +macro_rules! mac_trait { + ($($i:item)*) => { + trait T { $($i)* } + } +} + +mac_trait! { + struct BadS; //~ ERROR struct is not supported in `trait`s or `impl`s + expand_to_enum!(); +} + +macro_rules! mac_extern { + ($($i:item)*) => { + extern "C" { $($i)* } + } +} + +mac_extern! { + struct BadS; //~ ERROR struct is not supported in `extern` blocks + expand_to_enum!(); +} diff --git a/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr new file mode 100644 index 00000000000..bfd27a1a41e --- /dev/null +++ b/src/test/ui/parser/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr @@ -0,0 +1,53 @@ +error: struct is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:20:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ------------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:31:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + +error: enum is not supported in `trait`s or `impl`s + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ------------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: struct is not supported in `extern` blocks + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:42:5 + | +LL | struct BadS; + | ^^^^^^^^^^^^ + +error: enum is not supported in `extern` blocks + --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 + | +LL | enum BadE {} + | ^^^^^^^^^ +... +LL | expand_to_enum!(); + | ------------------ in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + From 9c3ee1bc351fcfabcfd47947dc44b0c020427181 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sun, 23 Feb 2020 23:59:39 -0800 Subject: [PATCH 0483/1250] Bump core::primitive to 1.43 --- src/libcore/lib.rs | 2 +- src/libcore/primitive.rs | 34 +++++++++++++++++----------------- src/libstd/lib.rs | 2 +- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 257a6d371b7..b939462afc7 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -262,7 +262,7 @@ mod bool; mod tuple; mod unit; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub mod primitive; // Pull in the `core_arch` crate directly into libcore. The contents of diff --git a/src/libcore/primitive.rs b/src/libcore/primitive.rs index d37bbfaf5df..e20b2c5c938 100644 --- a/src/libcore/primitive.rs +++ b/src/libcore/primitive.rs @@ -31,37 +31,37 @@ //! # trait QueryId { const SOME_PROPERTY: core::primitive::bool; } //! ``` -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use bool; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use char; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use f32; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use f64; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use i128; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use i16; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use i32; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use i64; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use i8; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use isize; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use str; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use u128; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use u16; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use u32; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use u64; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use u8; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use usize; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 2b54481ab56..a495d29cc47 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -550,7 +550,7 @@ pub use core::{ trace_macros, }; -#[stable(feature = "core_primitive", since = "1.42.0")] +#[stable(feature = "core_primitive", since = "1.43.0")] pub use core::primitive; // Include a number of private modules that exist solely to provide From a2a89800011d448e0d0ce040ece9b5a144ce66b3 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 24 Feb 2020 09:13:13 +0100 Subject: [PATCH 0484/1250] Update Clippy --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 8fbb23f2549..fc5d0cc583c 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 8fbb23f2549e75b89967f09b9293607bd3bb96a6 +Subproject commit fc5d0cc583cb1cd35d58fdb7f3e0cfa12dccd6c0 From f85b0c456f763a70a8eae0e4a9daf6a4005ef87a Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 24 Feb 2020 18:06:42 +0900 Subject: [PATCH 0485/1250] Remove use of `unwrap()` from save-analysis --- src/librustc_save_analysis/lib.rs | 19 +++++++++++-------- src/test/ui/assign-to-method.rs | 2 ++ src/test/ui/assign-to-method.stderr | 4 ++-- src/test/ui/issues/issue-3763.rs | 2 ++ src/test/ui/issues/issue-3763.stderr | 10 +++++----- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b253559dd5c..a46be2dcd82 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -533,14 +533,17 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { match self.tables.expr_ty_adjusted(&hir_node).kind { ty::Adt(def, _) if !def.is_enum() => { let variant = &def.non_enum_variant(); - let index = self.tcx.find_field_index(ident, variant).unwrap(); - filter!(self.span_utils, ident.span); - let span = self.span_from_span(ident.span); - return Some(Data::RefData(Ref { - kind: RefKind::Variable, - span, - ref_id: id_from_def_id(variant.fields[index].did), - })); + if let Some(index) = self.tcx.find_field_index(ident, variant) { + filter!(self.span_utils, ident.span); + let span = self.span_from_span(ident.span); + return Some(Data::RefData(Ref { + kind: RefKind::Variable, + span, + ref_id: id_from_def_id(variant.fields[index].did), + })); + } + + None } ty::Tuple(..) => None, _ => { diff --git a/src/test/ui/assign-to-method.rs b/src/test/ui/assign-to-method.rs index 95f066c382c..dec09625225 100644 --- a/src/test/ui/assign-to-method.rs +++ b/src/test/ui/assign-to-method.rs @@ -1,3 +1,5 @@ +// compile-flags: -Zsave-analysis + struct Cat { meows : usize, diff --git a/src/test/ui/assign-to-method.stderr b/src/test/ui/assign-to-method.stderr index feceadb6722..b9ef49acd6d 100644 --- a/src/test/ui/assign-to-method.stderr +++ b/src/test/ui/assign-to-method.stderr @@ -1,5 +1,5 @@ error[E0615]: attempted to take value of method `speak` on type `Cat` - --> $DIR/assign-to-method.rs:20:8 + --> $DIR/assign-to-method.rs:22:8 | LL | nyan.speak = || println!("meow"); | ^^^^^ @@ -7,7 +7,7 @@ LL | nyan.speak = || println!("meow"); = help: methods are immutable and cannot be assigned to error[E0615]: attempted to take value of method `speak` on type `Cat` - --> $DIR/assign-to-method.rs:21:8 + --> $DIR/assign-to-method.rs:23:8 | LL | nyan.speak += || println!("meow"); | ^^^^^ diff --git a/src/test/ui/issues/issue-3763.rs b/src/test/ui/issues/issue-3763.rs index 5d17a30ab36..a220151c416 100644 --- a/src/test/ui/issues/issue-3763.rs +++ b/src/test/ui/issues/issue-3763.rs @@ -1,3 +1,5 @@ +// compile-flags: -Zsave-analysis + mod my_mod { pub struct MyStruct { priv_field: isize diff --git a/src/test/ui/issues/issue-3763.stderr b/src/test/ui/issues/issue-3763.stderr index 50169286b1c..3db962142b5 100644 --- a/src/test/ui/issues/issue-3763.stderr +++ b/src/test/ui/issues/issue-3763.stderr @@ -1,29 +1,29 @@ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:15:19 + --> $DIR/issue-3763.rs:17:19 | LL | let _woohoo = (&my_struct).priv_field; | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:18:19 + --> $DIR/issue-3763.rs:20:19 | LL | let _woohoo = (Box::new(my_struct)).priv_field; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0624]: method `happyfun` is private - --> $DIR/issue-3763.rs:21:18 + --> $DIR/issue-3763.rs:23:18 | LL | (&my_struct).happyfun(); | ^^^^^^^^ error[E0624]: method `happyfun` is private - --> $DIR/issue-3763.rs:23:27 + --> $DIR/issue-3763.rs:25:27 | LL | (Box::new(my_struct)).happyfun(); | ^^^^^^^^ error[E0616]: field `priv_field` of struct `my_mod::MyStruct` is private - --> $DIR/issue-3763.rs:24:16 + --> $DIR/issue-3763.rs:26:16 | LL | let nope = my_struct.priv_field; | ^^^^^^^^^^^^^^^^^^^^ From 59261f0a7cf264f16e2b6a4e87d4249b212e920e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 22 Feb 2020 20:19:49 +0300 Subject: [PATCH 0486/1250] Add some missing support for `NtIdent` --- src/librustc_expand/mbe/macro_parser.rs | 6 +++ src/librustc_parse/parser/diagnostics.rs | 7 ++- src/libsyntax/token.rs | 54 +++++++++++------------- src/libsyntax/util/literal.rs | 13 ++++-- 4 files changed, 44 insertions(+), 36 deletions(-) diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 6599e92222c..b0bbed6fabf 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -753,6 +753,12 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na fn get_macro_name(token: &Token) -> Option<(Name, bool)> { match token.kind { token::Ident(name, is_raw) if name != kw::Underscore => Some((name, is_raw)), + token::Interpolated(ref nt) => match **nt { + token::NtIdent(ident, is_raw) if ident.name != kw::Underscore => { + Some((ident.name, is_raw)) + } + _ => None, + }, _ => None, } } diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 018aef3c13c..09b47df2b19 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -13,7 +13,7 @@ use syntax::ast::{ }; use syntax::ast::{AttrVec, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind}; use syntax::ptr::P; -use syntax::token::{self, token_can_begin_expr, TokenKind}; +use syntax::token::{self, TokenKind}; use syntax::util::parser::AssocOp; use log::{debug, trace}; @@ -900,8 +900,7 @@ impl<'a> Parser<'a> { } else if !sm.is_multiline(self.prev_span.until(self.token.span)) { // The current token is in the same line as the prior token, not recoverable. } else if self.look_ahead(1, |t| { - t == &token::CloseDelim(token::Brace) - || token_can_begin_expr(t) && t.kind != token::Colon + t == &token::CloseDelim(token::Brace) || t.can_begin_expr() && t.kind != token::Colon }) && [token::Comma, token::Colon].contains(&self.token.kind) { // Likely typo: `,` → `;` or `:` → `;`. This is triggered if the current token is @@ -919,7 +918,7 @@ impl<'a> Parser<'a> { } else if self.look_ahead(0, |t| { t == &token::CloseDelim(token::Brace) || ( - token_can_begin_expr(t) && t != &token::Semi && t != &token::Pound + t.can_begin_expr() && t != &token::Semi && t != &token::Pound // Avoid triggering with too many trailing `#` in raw string. ) }) { diff --git a/src/libsyntax/token.rs b/src/libsyntax/token.rs index 6eeee498815..bfb1a0e70f6 100644 --- a/src/libsyntax/token.rs +++ b/src/libsyntax/token.rs @@ -147,36 +147,30 @@ impl Lit { pub fn ident_can_begin_expr(name: ast::Name, span: Span, is_raw: bool) -> bool { let ident_token = Token::new(Ident(name, is_raw), span); - token_can_begin_expr(&ident_token) -} -pub fn token_can_begin_expr(ident_token: &Token) -> bool { !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() - || match ident_token.kind { - TokenKind::Ident(ident, _) => [ - kw::Async, - kw::Do, - kw::Box, - kw::Break, - kw::Continue, - kw::False, - kw::For, - kw::If, - kw::Let, - kw::Loop, - kw::Match, - kw::Move, - kw::Return, - kw::True, - kw::Unsafe, - kw::While, - kw::Yield, - kw::Static, - ] - .contains(&ident), - _ => false, - } + || [ + kw::Async, + kw::Do, + kw::Box, + kw::Break, + kw::Continue, + kw::False, + kw::For, + kw::If, + kw::Let, + kw::Loop, + kw::Match, + kw::Move, + kw::Return, + kw::True, + kw::Unsafe, + kw::While, + kw::Yield, + kw::Static, + ] + .contains(&name) } fn ident_can_begin_type(name: ast::Name, span: Span, is_raw: bool) -> bool { @@ -369,8 +363,8 @@ impl Token { Lifetime(..) | // labeled loop Pound => true, // expression attributes Interpolated(ref nt) => match **nt { + NtIdent(ident, is_raw) => ident_can_begin_expr(ident.name, ident.span, is_raw), NtLiteral(..) | - NtIdent(..) | NtExpr(..) | NtBlock(..) | NtPath(..) | @@ -397,7 +391,8 @@ impl Token { Lt | BinOp(Shl) | // associated path ModSep => true, // global path Interpolated(ref nt) => match **nt { - NtIdent(..) | NtTy(..) | NtPath(..) | NtLifetime(..) => true, + NtIdent(ident, is_raw) => ident_can_begin_type(ident.name, ident.span, is_raw), + NtTy(..) | NtPath(..) | NtLifetime(..) => true, _ => false, }, _ => false, @@ -442,6 +437,7 @@ impl Token { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, Interpolated(ref nt) => match &**nt { + NtIdent(ident, false) if ident.name.is_bool_lit() => true, NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)), _ => false, }, diff --git a/src/libsyntax/util/literal.rs b/src/libsyntax/util/literal.rs index 0c611adc06b..ecf17efc4e0 100644 --- a/src/libsyntax/util/literal.rs +++ b/src/libsyntax/util/literal.rs @@ -197,10 +197,17 @@ impl Lit { } token::Literal(lit) => lit, token::Interpolated(ref nt) => { - if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { - if let ast::ExprKind::Lit(lit) = &expr.kind { - return Ok(lit.clone()); + match &**nt { + token::NtIdent(ident, false) if ident.name.is_bool_lit() => { + let lit = token::Lit::new(token::Bool, ident.name, None); + return Lit::from_lit_token(lit, ident.span); } + token::NtExpr(expr) | token::NtLiteral(expr) => { + if let ast::ExprKind::Lit(lit) = &expr.kind { + return Ok(lit.clone()); + } + } + _ => {} } return Err(LitError::NotLiteral); } From b2605c118de31db9d61a9f7d0d158b9bf35f7a4a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 24 Feb 2020 13:04:13 +0300 Subject: [PATCH 0487/1250] parser: `token` -> `normalized_token`, `nonnormalized_token` -> `token` --- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_expand/mbe/macro_parser.rs | 3 +- src/librustc_parse/parser/diagnostics.rs | 6 +-- src/librustc_parse/parser/expr.rs | 39 +++++++-------- src/librustc_parse/parser/item.rs | 14 +++--- src/librustc_parse/parser/mod.rs | 48 +++++++++---------- src/librustc_parse/parser/path.rs | 7 ++- src/librustc_parse/parser/ty.rs | 7 ++- .../ui/borrowck/move-error-snippets.stderr | 20 ++++---- .../directory_ownership/macro-expanded-mod.rs | 3 +- .../macro-expanded-mod.stderr | 9 +++- src/test/ui/hygiene/fields-definition.stderr | 4 +- src/test/ui/issues/issue-39848.rs | 3 +- src/test/ui/issues/issue-39848.stderr | 12 +++-- 14 files changed, 88 insertions(+), 89 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index a9298abe2d7..072c987a523 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -158,7 +158,7 @@ fn parse_args<'a>( } // accept trailing commas if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { named = true; - let name = if let token::Ident(name, _) = p.token.kind { + let name = if let token::Ident(name, _) = p.normalized_token.kind { p.bump(); name } else { diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index b0bbed6fabf..2a53d600c5b 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -889,9 +889,8 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, // this could be handled like a token, since it is one sym::ident => { if let Some((name, is_raw)) = get_macro_name(&p.token) { - let span = p.token.span; p.bump(); - token::NtIdent(Ident::new(name, span), is_raw) + token::NtIdent(Ident::new(name, p.normalized_prev_token.span), is_raw) } else { let token_str = pprust::token_to_string(&p.token); let msg = &format!("expected ident, found {}", &token_str); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 09b47df2b19..00f5fb97052 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -192,12 +192,12 @@ impl<'a> Parser<'a> { TokenKind::CloseDelim(token::DelimToken::Brace), TokenKind::CloseDelim(token::DelimToken::Paren), ]; - if let token::Ident(name, false) = self.token.kind { - if Ident::new(name, self.token.span).is_raw_guess() + if let token::Ident(name, false) = self.normalized_token.kind { + if Ident::new(name, self.normalized_token.span).is_raw_guess() && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) { err.span_suggestion( - self.token.span, + self.normalized_token.span, "you can escape reserved keywords to use them as identifiers", format!("r#{}", name), Applicability::MaybeIncorrect, diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3ae97ed5f88..859e53127b7 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -97,15 +97,14 @@ impl<'a> Parser<'a> { fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P> { match self.parse_expr() { Ok(expr) => Ok(expr), - Err(mut err) => match self.token.kind { + Err(mut err) => match self.normalized_token.kind { token::Ident(name, false) if name == kw::Underscore && self.look_ahead(1, |t| t == &token::Comma) => { // Special-case handling of `foo(_, _, _)` err.emit(); - let sp = self.token.span; self.bump(); - Ok(self.mk_expr(sp, ExprKind::Err, AttrVec::new())) + Ok(self.mk_expr(self.prev_token.span, ExprKind::Err, AttrVec::new())) } _ => Err(err), }, @@ -166,7 +165,7 @@ impl<'a> Parser<'a> { while let Some(op) = self.check_assoc_op() { // Adjust the span for interpolated LHS to point to the `$lhs` token // and not to what it refers to. - let lhs_span = match self.unnormalized_prev_token.kind { + let lhs_span = match self.prev_token.kind { TokenKind::Interpolated(..) => self.prev_span, _ => lhs.span, }; @@ -337,7 +336,7 @@ impl<'a> Parser<'a> { /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively. fn check_assoc_op(&self) -> Option> { Some(Spanned { - node: match (AssocOp::from_token(&self.token), &self.token.kind) { + node: match (AssocOp::from_token(&self.token), &self.normalized_token.kind) { (Some(op), _) => op, (None, token::Ident(sym::and, false)) => { self.error_bad_logical_op("and", "&&", "conjunction"); @@ -349,7 +348,7 @@ impl<'a> Parser<'a> { } _ => return None, }, - span: self.token.span, + span: self.normalized_token.span, }) } @@ -441,7 +440,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_or_use_outer_attributes(attrs)?; let lo = self.token.span; // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() - let (hi, ex) = match self.token.kind { + let (hi, ex) = match self.normalized_token.kind { token::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr` token::Tilde => self.recover_tilde_expr(lo), // `~expr` token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-expr` @@ -527,7 +526,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, (Span, P)> { expr.map(|e| { ( - match self.unnormalized_prev_token.kind { + match self.prev_token.kind { TokenKind::Interpolated(..) => self.prev_span, _ => e.span, }, @@ -708,7 +707,7 @@ impl<'a> Parser<'a> { } fn parse_dot_suffix_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { - match self.token.kind { + match self.normalized_token.kind { token::Ident(..) => self.parse_dot_suffix(base, lo), token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix)) @@ -777,8 +776,8 @@ impl<'a> Parser<'a> { field: Symbol, suffix: Option, ) -> P { - let span = self.token.span; self.bump(); + let span = self.prev_token.span; let field = ExprKind::Field(base, Ident::new(field, span)); self.expect_no_suffix(span, "a tuple index", suffix); self.mk_expr(lo.to(span), field, AttrVec::new()) @@ -802,7 +801,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.token.span.rust_2018() && self.eat_keyword(kw::Await) { + if self.normalized_token.span.rust_2018() && self.eat_keyword(kw::Await) { return self.mk_await_expr(self_arg, lo); } @@ -916,7 +915,7 @@ impl<'a> Parser<'a> { // | ^ expected expression self.bump(); Ok(self.mk_expr_err(self.token.span)) - } else if self.token.span.rust_2018() { + } else if self.normalized_token.span.rust_2018() { // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. if self.check_keyword(kw::Async) { if self.is_async_block() { @@ -1346,7 +1345,7 @@ impl<'a> Parser<'a> { if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; let asyncness = - if self.token.span.rust_2018() { self.parse_asyncness() } else { Async::No }; + if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No }; if asyncness.is_async() { // Feature-gate `async ||` closures. self.sess.gated_spans.gate(sym::async_closure, self.prev_span); @@ -1560,9 +1559,8 @@ impl<'a> Parser<'a> { fn eat_label(&mut self) -> Option

", render_spotlight_traits(it));
+    write!(w, "
");
     render_attributes(w, it, false);
     write!(
         w,
@@ -2527,13 +2527,7 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait)
         let item_type = m.type_();
         let id = cx.derive_id(format!("{}.{}", item_type, name));
         let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space()));
-        write!(
-            w,
-            "

{extra}", - extra = render_spotlight_traits(m), - id = id, - ns_id = ns_id - ); + write!(w, "

", id = id, ns_id = ns_id); render_assoc_item(w, m, AssocItemLink::Anchor(Some(&id)), ItemType::Impl); write!(w, ""); render_stability_since(w, m, t); @@ -3519,76 +3513,6 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool) -> bool { } } -fn render_spotlight_traits(item: &clean::Item) -> String { - match item.inner { - clean::FunctionItem(clean::Function { ref decl, .. }) - | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) - | clean::MethodItem(clean::Method { ref decl, .. }) - | clean::ForeignFunctionItem(clean::Function { ref decl, .. }) => spotlight_decl(decl), - _ => String::new(), - } -} - -fn spotlight_decl(decl: &clean::FnDecl) -> String { - let mut out = Buffer::html(); - let mut trait_ = String::new(); - - if let Some(did) = decl.output.def_id() { - let c = cache(); - if let Some(impls) = c.impls.get(&did) { - for i in impls { - let impl_ = i.inner_impl(); - if impl_.trait_.def_id().map_or(false, |d| c.traits[&d].is_spotlight) { - if out.is_empty() { - out.push_str(&format!( - "

Important traits for {}

\ - ", - impl_.for_.print() - )); - trait_.push_str(&impl_.for_.print().to_string()); - } - - //use the "where" class here to make it small - out.push_str(&format!( - "{}", - impl_.print() - )); - let t_did = impl_.trait_.def_id().unwrap(); - for it in &impl_.items { - if let clean::TypedefItem(ref tydef, _) = it.inner { - out.push_str(" "); - assoc_type( - &mut out, - it, - &[], - Some(&tydef.type_), - AssocItemLink::GotoSource(t_did, &FxHashSet::default()), - "", - ); - out.push_str(";"); - } - } - } - } - } - } - - if !out.is_empty() { - out.insert_str( - 0, - &format!( - "
ⓘ\ - Important traits for {}
\ -
", - trait_ - ), - ); - out.push_str("
"); - } - - out.into_inner() -} - fn render_impl( w: &mut Buffer, cx: &Context, @@ -3695,14 +3619,13 @@ fn render_impl( (true, " hidden") }; match item.inner { - clean::MethodItem(clean::Method { ref decl, .. }) - | clean::TyMethodItem(clean::TyMethod { ref decl, .. }) => { + clean::MethodItem(clean::Method { .. }) + | clean::TyMethodItem(clean::TyMethod { .. }) => { // Only render when the method is not static or we allow static methods if render_method_item { let id = cx.derive_id(format!("{}.{}", item_type, name)); let ns_id = cx.derive_id(format!("{}.{}", name, item_type.name_space())); write!(w, "

", id, item_type, extra_class); - write!(w, "{}", spotlight_decl(decl)); write!(w, "", ns_id); render_assoc_item(w, item, link.anchor(&id), ItemType::Impl); write!(w, ""); diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 2870c6e0a61..a799aed6985 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -341,7 +341,6 @@ function getSearchElement() { function handleEscape(ev) { var help = getHelpElement(); var search = getSearchElement(); - hideModal(); if (hasClass(help, "hidden") === false) { displayHelp(false, ev, help); } else if (hasClass(search, "hidden") === false) { @@ -373,7 +372,6 @@ function getSearchElement() { case "s": case "S": displayHelp(false, ev); - hideModal(); ev.preventDefault(); focusSearchBar(); break; @@ -386,7 +384,6 @@ function getSearchElement() { case "?": if (ev.shiftKey) { - hideModal(); displayHelp(true, ev); } break; @@ -2504,31 +2501,6 @@ function getSearchElement() { lineNumbersFunc(e); }); - function showModal(content) { - var modal = document.createElement("div"); - modal.id = "important"; - addClass(modal, "modal"); - modal.innerHTML = "
✕" + - "
" + content + - "
"; - document.getElementsByTagName("body")[0].appendChild(modal); - document.getElementById("modal-close").onclick = hideModal; - modal.onclick = hideModal; - } - - function hideModal() { - var modal = document.getElementById("important"); - if (modal) { - modal.parentNode.removeChild(modal); - } - } - - onEachLazy(document.getElementsByClassName("important-traits"), function(e) { - e.onclick = function() { - showModal(e.lastElementChild.innerHTML); - }; - }); - // In the search display, allows to switch between tabs. function printTab(nb) { if (nb === 0 || nb === 1 || nb === 2) { diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index 0dfe82c5014..f05db6c2185 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -143,12 +143,9 @@ code, pre, a.test-arrow { border-radius: 3px; padding: 0 0.1em; } -.docblock pre code, .docblock-short pre code, .docblock code.spotlight { +.docblock pre code, .docblock-short pre code { padding: 0; } -.docblock code.spotlight :last-child { - padding-bottom: 0.6em; -} pre { padding: 14px; } @@ -503,7 +500,7 @@ h4 > code, h3 > code, .invisible > code { font-size: 0.8em; } -.content .methods > div:not(.important-traits) { +.content .methods > div { margin-left: 40px; margin-bottom: 15px; } @@ -1072,7 +1069,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { border-style: solid; } -.important-traits .tooltip .tooltiptext { +.tooltip .tooltiptext { border: 1px solid; } @@ -1117,17 +1114,6 @@ pre.rust { font-size: 16px; } -.important-traits { - cursor: pointer; - z-index: 2; -} - -h4 > .important-traits { - position: absolute; - left: -44px; - top: 2px; -} - #all-types { text-align: center; border: 1px solid; @@ -1354,12 +1340,6 @@ h4 > .important-traits { z-index: 1; } - h4 > .important-traits { - position: absolute; - left: -22px; - top: 24px; - } - #titles > div > div.count { float: left; width: 100%; @@ -1462,82 +1442,12 @@ h4 > .important-traits { } } -.modal { - position: fixed; - width: 100vw; - height: 100vh; - z-index: 10000; - top: 0; - left: 0; -} - -.modal-content { - display: block; - max-width: 60%; - min-width: 200px; - padding: 8px; - top: 40%; - position: absolute; - left: 50%; - transform: translate(-50%, -40%); - border: 1px solid; - border-radius: 4px; - border-top-right-radius: 0; -} - -.modal-content > .docblock { - margin: 0; -} - h3.important { margin: 0; margin-bottom: 13px; font-size: 19px; } -.modal-content > .docblock > code.content { - margin: 0; - padding: 0; - font-size: 20px; -} - -.modal-content > .close { - position: absolute; - font-weight: 900; - right: -25px; - top: -1px; - font-size: 18px; - width: 25px; - padding-right: 2px; - border-top-right-radius: 5px; - border-bottom-right-radius: 5px; - text-align: center; - border: 1px solid; - border-right: 0; - cursor: pointer; -} - -.modal-content > .whiter { - height: 25px; - position: absolute; - width: 3px; - right: -2px; - top: 0px; -} - -#main > div.important-traits { - position: absolute; - left: -24px; - margin-top: 16px; -} - -.content > .methods > .method > div.important-traits { - position: absolute; - font-weight: 400; - left: -42px; - margin-top: 2px; -} - kbd { display: inline-block; padding: 3px 5px; diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index 9a0e7bbabcb..e7041d54c6b 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -298,12 +298,6 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits .tooltip .tooltiptext { - background-color: white; - color: black; - border-color: black; -} - #titles > div:not(.selected) { background-color: #252525; border-top-color: #252525; @@ -317,33 +311,6 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } -.modal { - background-color: rgba(0,0,0,0.3); -} - -.modal-content { - background-color: #272727; - border-color: #999; -} - -.modal-content > .close { - background-color: #272727; - border-color: #999; -} - -.modal-content > .close:hover { - background-color: #ff1f1f; - color: white; -} - -.modal-content > .whiter { - background-color: #272727; -} - -.modal-content > .close:hover + .whiter { - background-color: #ff1f1f; -} - @media (max-width: 700px) { .sidebar-menu { background-color: #505050; diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index ca8ea1c456a..a1efef6701f 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -292,12 +292,6 @@ pre.ignore:hover, .information:hover + pre.ignore { border-color: transparent black transparent transparent; } -.important-traits .tooltip .tooltiptext { - background-color: white; - color: black; - border-color: black; -} - #titles > div:not(.selected) { background-color: #e6e6e6; border-top-color: #e6e6e6; @@ -311,33 +305,6 @@ pre.ignore:hover, .information:hover + pre.ignore { color: #888; } -.modal { - background-color: rgba(0,0,0,0.3); -} - -.modal-content { - background-color: #eee; - border-color: #999; -} - -.modal-content > .close { - background-color: #eee; - border-color: #999; -} - -.modal-content > .close:hover { - background-color: #ff1f1f; - color: white; -} - -.modal-content > .whiter { - background-color: #eee; -} - -.modal-content > .close:hover + .whiter { - background-color: #ff1f1f; -} - @media (max-width: 700px) { .sidebar-menu { background-color: #F1F1F1; diff --git a/src/test/rustdoc/doc-spotlight.rs b/src/test/rustdoc/doc-spotlight.rs deleted file mode 100644 index ddd46c3c215..00000000000 --- a/src/test/rustdoc/doc-spotlight.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![feature(doc_spotlight)] - -pub struct Wrapper { - inner: T, -} - -impl SomeTrait for Wrapper {} - -#[doc(spotlight)] -pub trait SomeTrait { - // @has doc_spotlight/trait.SomeTrait.html - // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' - fn wrap_me(self) -> Wrapper where Self: Sized { - Wrapper { - inner: self, - } - } -} - -pub struct SomeStruct; -impl SomeTrait for SomeStruct {} - -impl SomeStruct { - // @has doc_spotlight/struct.SomeStruct.html - // @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' - // @has - '//code[@class="content"]' 'impl SomeTrait for Wrapper' - pub fn new() -> SomeStruct { - SomeStruct - } -} - -// @has doc_spotlight/fn.bare_fn.html -// @has - '//code[@class="content"]' 'impl SomeTrait for SomeStruct' -pub fn bare_fn() -> SomeStruct { - SomeStruct -} diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs b/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs deleted file mode 100644 index 452b45b3445..00000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.rs +++ /dev/null @@ -1,4 +0,0 @@ -#[doc(spotlight)] //~ ERROR: `#[doc(spotlight)]` is experimental -trait SomeTrait {} - -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr b/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr deleted file mode 100644 index 010d74054a4..00000000000 --- a/src/test/ui/feature-gates/feature-gate-doc_spotlight.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: `#[doc(spotlight)]` is experimental - --> $DIR/feature-gate-doc_spotlight.rs:1:1 - | -LL | #[doc(spotlight)] - | ^^^^^^^^^^^^^^^^^ - | - = note: see issue #45040 for more information - = help: add `#![feature(doc_spotlight)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From 13c6d5819aae3c0de6a90e7f17ea967bf4487cbb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Feb 2020 14:38:30 +0100 Subject: [PATCH 0544/1250] Remove spotlight usage --- src/libcore/future/future.rs | 1 - src/libcore/iter/traits/iterator.rs | 1 - src/libcore/lib.rs | 1 - src/librustc_ast_passes/feature_gate.rs | 1 - src/librustc_span/symbol.rs | 2 -- src/libstd/io/mod.rs | 2 -- src/libstd/lib.rs | 1 - 7 files changed, 9 deletions(-) diff --git a/src/libcore/future/future.rs b/src/libcore/future/future.rs index f14ed38b9b0..00a171e6b5f 100644 --- a/src/libcore/future/future.rs +++ b/src/libcore/future/future.rs @@ -24,7 +24,6 @@ use crate::task::{Context, Poll}; /// `.await` the value. /// /// [`Waker`]: ../task/struct.Waker.html -#[doc(spotlight)] #[must_use = "futures do nothing unless you `.await` or poll them"] #[stable(feature = "futures_api", since = "1.36.0")] #[lang = "future_trait"] diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 1d055676c77..83c9a5fbe15 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -92,7 +92,6 @@ fn _assert_is_object_safe(_: &dyn Iterator) {} label = "`{Self}` is not an iterator", message = "`{Self}` is not an iterator" )] -#[doc(spotlight)] #[must_use = "iterators are lazy and do nothing unless consumed"] pub trait Iterator { /// The type of the elements being iterated over. diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index bca96b77812..21806fad8ff 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -90,7 +90,6 @@ #![feature(custom_inner_attributes)] #![feature(decl_macro)] #![feature(doc_cfg)] -#![feature(doc_spotlight)] #![feature(extern_types)] #![feature(fundamental)] #![feature(intrinsics)] diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 3c924847a73..2146eec338f 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -245,7 +245,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { include => external_doc cfg => doc_cfg masked => doc_masked - spotlight => doc_spotlight alias => doc_alias keyword => doc_keyword ); diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 97708d91d7e..42e92b60d69 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -269,7 +269,6 @@ symbols! { doc_cfg, doc_keyword, doc_masked, - doc_spotlight, doctest, document_private_items, dotdoteq_in_patterns, @@ -688,7 +687,6 @@ symbols! { Some, specialization, speed, - spotlight, sse4a_target_feature, stable, staged_api, diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 67b382c7a84..1f88a6a5576 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -497,7 +497,6 @@ where /// [`&str`]: ../../std/primitive.str.html /// [slice]: ../../std/primitive.slice.html #[stable(feature = "rust1", since = "1.0.0")] -#[doc(spotlight)] pub trait Read { /// Pull some bytes from this source into the specified buffer, returning /// how many bytes were read. @@ -1228,7 +1227,6 @@ impl Initializer { /// /// [`write_all`]: #method.write_all #[stable(feature = "rust1", since = "1.0.0")] -#[doc(spotlight)] pub trait Write { /// Write a buffer into this writer, returning how many bytes were written. /// diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 799585ffc0a..f482eb6b2ee 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -256,7 +256,6 @@ #![feature(doc_cfg)] #![feature(doc_keyword)] #![feature(doc_masked)] -#![feature(doc_spotlight)] #![feature(dropck_eyepatch)] #![feature(duration_constants)] #![feature(exact_size_is_empty)] From 7c84ba112429eb9bc0b99a6fe32a453c920a764c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 26 Feb 2020 13:03:46 +0100 Subject: [PATCH 0545/1250] use char instead of &str for single char patterns --- src/librustc_builtin_macros/asm.rs | 8 ++++---- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_utils/link.rs | 2 +- src/librustc_driver/args.rs | 2 +- src/librustc_driver/lib.rs | 2 +- src/librustc_expand/proc_macro_server.rs | 4 ++-- src/librustc_hir/hir.rs | 2 +- src/librustc_incremental/assert_module_sources.rs | 2 +- src/librustc_incremental/persist/fs.rs | 6 +++--- src/librustc_interface/util.rs | 2 +- src/librustc_llvm/build.rs | 2 +- .../borrow_check/diagnostics/region_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/transform/mod.rs | 2 +- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_passes/dead.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_target/abi/mod.rs | 6 +++--- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/demand.rs | 4 ++-- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/op.rs | 6 +++--- src/librustc_typeck/collect.rs | 4 ++-- src/librustdoc/html/markdown.rs | 2 +- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/render/cache.rs | 4 ++-- src/librustdoc/markdown.rs | 2 +- src/libstd/io/mod.rs | 4 ++-- 30 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index 4723544316f..9f98cf253c9 100644 --- a/src/librustc_builtin_macros/asm.rs +++ b/src/librustc_builtin_macros/asm.rs @@ -182,7 +182,7 @@ fn parse_inline_asm<'a>( }; let is_rw = output.is_some(); - let is_indirect = constraint_str.contains("*"); + let is_indirect = constraint_str.contains('*'); outputs.push(ast::InlineAsmOutput { constraint: output.unwrap_or(constraint), expr, @@ -199,7 +199,7 @@ fn parse_inline_asm<'a>( let constraint = parse_asm_str(&mut p)?; - if constraint.as_str().starts_with("=") { + if constraint.as_str().starts_with('=') { struct_span_err!( cx.parse_sess.span_diagnostic, p.prev_span, @@ -207,7 +207,7 @@ fn parse_inline_asm<'a>( "input operand constraint contains '='" ) .emit(); - } else if constraint.as_str().starts_with("+") { + } else if constraint.as_str().starts_with('+') { struct_span_err!( cx.parse_sess.span_diagnostic, p.prev_span, @@ -234,7 +234,7 @@ fn parse_inline_asm<'a>( if OPTIONS.iter().any(|&opt| s == opt) { cx.span_warn(p.prev_span, "expected a clobber, found an option"); - } else if s.as_str().starts_with("{") || s.as_str().ends_with("}") { + } else if s.as_str().starts_with('{') || s.as_str().ends_with('}') { struct_span_err!( cx.parse_sess.span_diagnostic, p.prev_span, diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index a9298abe2d7..e1d30674186 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -894,7 +894,7 @@ pub fn expand_preparsed_format_args( }; let (is_literal, fmt_snippet) = match ecx.source_map().span_to_snippet(fmt_sp) { - Ok(s) => (s.starts_with("\"") || s.starts_with("r#"), Some(s)), + Ok(s) => (s.starts_with('"') || s.starts_with("r#"), Some(s)), _ => (false, None), }; diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index d7297ed4176..6b136aeb8d9 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -917,7 +917,7 @@ impl ThinLTOImports { if line.is_empty() { let importing_module = current_module.take().expect("Importing module not set"); imports.insert(importing_module, mem::replace(&mut current_imports, vec![])); - } else if line.starts_with(" ") { + } else if line.starts_with(' ') { // Space marks an imported module assert_ne!(current_module, None); current_imports.push(line.trim().to_string()); diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index 4dab4545b42..92cbc42388d 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -78,7 +78,7 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: } if let Input::File(ref path) = *input { if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { - if s.starts_with("-") { + if s.starts_with('-') { let msg = format!( "crate names cannot start with a `-`, but \ `{}` has a leading hyphen", diff --git a/src/librustc_driver/args.rs b/src/librustc_driver/args.rs index 5e2c43596db..5686819c61b 100644 --- a/src/librustc_driver/args.rs +++ b/src/librustc_driver/args.rs @@ -4,7 +4,7 @@ use std::fs; use std::io; pub fn arg_expand(arg: String) -> Result, Error> { - if arg.starts_with("@") { + if arg.starts_with('@') { let path = &arg[1..]; let file = match fs::read_to_string(path) { Ok(file) => file, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f68ea7e0770..410439360d7 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -521,7 +521,7 @@ fn stdout_isatty() -> bool { fn handle_explain(registry: Registry, code: &str, output: ErrorOutputType) { let normalised = - if code.starts_with("E") { code.to_string() } else { format!("E{0:0>4}", code) }; + if code.starts_with('E') { code.to_string() } else { format!("E{0:0>4}", code) }; match registry.find_description(&normalised) { Some(ref description) => { let mut is_in_code_block = false; diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index a7397e576b1..21fd4449307 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -209,7 +209,7 @@ impl ToInternal for TokenTree { TokenTree::Literal(self::Literal { lit: token::Lit { kind: token::Integer, symbol, suffix }, span, - }) if symbol.as_str().starts_with("-") => { + }) if symbol.as_str().starts_with('-') => { let minus = BinOp(BinOpToken::Minus); let symbol = Symbol::intern(&symbol.as_str()[1..]); let integer = TokenKind::lit(token::Integer, symbol, suffix); @@ -220,7 +220,7 @@ impl ToInternal for TokenTree { TokenTree::Literal(self::Literal { lit: token::Lit { kind: token::Float, symbol, suffix }, span, - }) if symbol.as_str().starts_with("-") => { + }) if symbol.as_str().starts_with('-') => { let minus = BinOp(BinOpToken::Minus); let symbol = Symbol::intern(&symbol.as_str()[1..]); let float = TokenKind::lit(token::Float, symbol, suffix); diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 6d2f5ba6baf..ab3368d0a49 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1496,7 +1496,7 @@ pub fn is_range_literal(sm: &SourceMap, expr: &Expr<'_>) -> bool { let end_point = sm.end_point(*span); if let Ok(end_string) = sm.span_to_snippet(end_point) { - !(end_string.ends_with("}") || end_string.ends_with(")")) + !(end_string.ends_with('}') || end_string.ends_with(')')) } else { false } diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 70abb38278a..293815cb52d 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -107,7 +107,7 @@ impl AssertModuleSource<'tcx> { } // Split of the "special suffix" if there is one. - let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind(".") { + let (user_path, cgu_special_suffix) = if let Some(index) = user_path.rfind('.') { (&user_path[..index], Some(&user_path[index + 1..])) } else { (&user_path[..], None) diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index ba20006d73c..8548ad392d2 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -152,7 +152,7 @@ pub fn lock_file_path(session_dir: &Path) -> PathBuf { let directory_name = session_dir.file_name().unwrap().to_string_lossy(); assert_no_characters_lost(&directory_name); - let dash_indices: Vec<_> = directory_name.match_indices("-").map(|(idx, _)| idx).collect(); + let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect(); if dash_indices.len() != 3 { bug!( "Encountered incremental compilation session directory with \ @@ -342,7 +342,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Svh) { // Keep the 's-{timestamp}-{random-number}' prefix, but replace the // '-working' part with the SVH of the crate - let dash_indices: Vec<_> = old_sub_dir_name.match_indices("-").map(|(idx, _)| idx).collect(); + let dash_indices: Vec<_> = old_sub_dir_name.match_indices('-').map(|(idx, _)| idx).collect(); if dash_indices.len() != 3 { bug!( "Encountered incremental compilation session directory with \ @@ -594,7 +594,7 @@ fn extract_timestamp_from_session_dir(directory_name: &str) -> Result = directory_name.match_indices("-").map(|(idx, _)| idx).collect(); + let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect(); if dash_indices.len() != 3 { return Err(()); } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index c73f7aafb48..f29a2609af4 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -244,7 +244,7 @@ pub fn get_codegen_backend(sess: &Session) -> Box { .as_ref() .unwrap_or(&sess.target.target.options.codegen_backend); let backend = match &codegen_name[..] { - filename if filename.contains(".") => load_backend_from_dylib(filename.as_ref()), + filename if filename.contains('.') => load_backend_from_dylib(filename.as_ref()), codegen_name => get_builtin_codegen_backend(codegen_name), }; diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 405ce0307cd..9b4f03b3fb6 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -178,7 +178,7 @@ fn main() { for lib in output(&mut cmd).split_whitespace() { let name = if lib.starts_with("-l") { &lib[2..] - } else if lib.starts_with("-") { + } else if lib.starts_with('-') { &lib[1..] } else if Path::new(lib).exists() { // On MSVC llvm-config will print the full name to libraries, but diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index 8d991927d54..8cd75d4a2fd 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -612,7 +612,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } else { "'_".to_string() }; - let suggestion = if snippet.ends_with(";") { + let suggestion = if snippet.ends_with(';') { // `type X = impl Trait;` format!("{} + {};", &snippet[..snippet.len() - 1], suggestable_fr_name) } else { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a3edfb662c5..f5640f25004 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -365,7 +365,7 @@ fn do_mir_borrowck<'a, 'tcx>( // Skip over locals that begin with an underscore or have no name match mbcx.local_names[local] { Some(name) => { - if name.as_str().starts_with("_") { + if name.as_str().starts_with('_') { continue; } } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 3c37eccc184..c4588d5fb03 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -122,7 +122,7 @@ impl<'tcx> MirSource<'tcx> { /// type `T`. pub fn default_name() -> Cow<'static, str> { let name = ::std::any::type_name::(); - if let Some(tail) = name.rfind(":") { Cow::from(&name[tail + 1..]) } else { Cow::from(name) } + if let Some(tail) = name.rfind(':') { Cow::from(&name[tail + 1..]) } else { Cow::from(name) } } /// A streamlined trait that you can implement to create a pass; the diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 3ae97ed5f88..a46d4cceeb2 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -758,7 +758,7 @@ impl<'a> Parser<'a> { s.print_usize(float.trunc() as usize); s.pclose(); s.s.word("."); - s.s.word(fstr.splitn(2, ".").last().unwrap().to_string()) + s.s.word(fstr.splitn(2, '.').last().unwrap().to_string()) }); err.span_suggestion( lo.to(self.prev_span), diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index e0eef1db0f0..e2749c7bd7c 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -553,7 +553,7 @@ impl DeadVisitor<'tcx> { node_type: &str, participle: &str, ) { - if !name.as_str().starts_with("_") { + if !name.as_str().starts_with('_') { self.tcx.struct_span_lint_hir(lint::builtin::DEAD_CODE, id, span, |lint| { lint.build(&format!("{} is never {}: `{}`", node_type, participle, name)).emit() }); diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a81caea4e41..2a9e335e924 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1103,7 +1103,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { // Macro uses will remove items from this set, and the remaining // items will be reported as `unused_macros`. fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) { - if !ident.as_str().starts_with("_") { + if !ident.as_str().starts_with('_') { self.r.unused_macros.insert(node_id, span); } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index ebd3f8b832b..540877d22c2 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2663,7 +2663,7 @@ impl<'a> Resolver<'a> { "{} as {}{}", &snippet[..pos], suggested_name, - if snippet.ends_with(";") { ";" } else { "" } + if snippet.ends_with(';') { ";" } else { "" } )) } } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 3f44339bf4c..edd0ba46f75 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -101,7 +101,7 @@ impl TargetDataLayout { match &*spec_parts { ["e"] => dl.endian = Endian::Little, ["E"] => dl.endian = Endian::Big, - [p] if p.starts_with("P") => { + [p] if p.starts_with('P') => { dl.instruction_address_space = parse_address_space(&p[1..], "P")? } ["a", ref a @ ..] => dl.aggregate_align = align(a, "a")?, @@ -111,7 +111,7 @@ impl TargetDataLayout { dl.pointer_size = size(s, p)?; dl.pointer_align = align(a, p)?; } - [s, ref a @ ..] if s.starts_with("i") => { + [s, ref a @ ..] if s.starts_with('i') => { let bits = match s[1..].parse::() { Ok(bits) => bits, Err(_) => { @@ -135,7 +135,7 @@ impl TargetDataLayout { dl.i128_align = a; } } - [s, ref a @ ..] if s.starts_with("v") => { + [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_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 78c05a51e4f..22480019d68 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1777,7 +1777,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { { let types: Vec<_> = assoc_items.iter().map(|item| format!("{} = Type", item.ident)).collect(); - let code = if snippet.ends_with(">") { + let code = if snippet.ends_with('>') { // The user wrote `Trait<'a>` or similar and we don't have a type we can // suggest, but at least we can clue them to the correct syntax // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index c289176c303..3ebd6fde8b3 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { if let hir::ExprKind::Lit(_) = expr.kind { if let Ok(src) = sm.span_to_snippet(sp) { - if src.starts_with("\"") { + if src.starts_with('"') { return Some(( sp, "consider adding a leading `b`", @@ -701,7 +701,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // Remove fractional part from literal, for example `42.0f32` into `42` let src = src.trim_end_matches(&checked_ty.to_string()); - src.split(".").next().unwrap() + src.split('.').next().unwrap() } else { src.trim_end_matches(&checked_ty.to_string()) }, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4ab5d8f9ad3..409403f1973 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4996,7 +4996,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sugg = if receiver.ends_with(".clone()") && method_call_list.contains(&method_call.as_str()) { - let max_len = receiver.rfind(".").unwrap(); + let max_len = receiver.rfind('.').unwrap(); format!("{}{}", &receiver[..max_len], method_call) } else { if expr.precedence().order() < ExprPrecedence::MethodCall.order() { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index cb6e028ab86..2c5dcdde5e8 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -597,12 +597,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Ok(lstring) => { err.span_suggestion( lhs_expr.span, - if lstring.starts_with("&") { + if lstring.starts_with('&') { remove_borrow_msg } else { msg }, - if lstring.starts_with("&") { + if lstring.starts_with('&') { // let a = String::new(); // let _ = &a + "bar"; format!("{}", &lstring[1..]) @@ -630,7 +630,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_assign, ) { (Ok(l), Ok(r), false) => { - let to_string = if l.starts_with("&") { + let to_string = if l.starts_with('&') { // let a = String::new(); let b = String::new(); // let _ = &a + b; format!("{}", &l[1..]) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 61aa8e51cb0..ff70767235c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2206,7 +2206,7 @@ fn from_target_feature( item.span(), format!("`{}` is not valid for this target", feature), ); - if feature.starts_with("+") { + if feature.starts_with('+') { let valid = whitelist.contains_key(&feature[1..]); if valid { err.help("consider removing the leading `+` in the feature name"); @@ -2337,7 +2337,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER; } else if attr.check_name(sym::export_name) { if let Some(s) = attr.value_str() { - if s.as_str().contains("\0") { + if s.as_str().contains('\0') { // `#[export_name = ...]` will be converted to a null-terminated string, // so it may not contain any null characters. struct_span_err!( diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 56f7b07cfc8..ff6431640d3 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -707,7 +707,7 @@ impl LangString { x if x.starts_with("edition") => { data.edition = x[7..].parse::().ok(); } - x if allow_error_code_check && x.starts_with("E") && x.len() == 5 => { + x if allow_error_code_check && x.starts_with('E') && x.len() == 5 => { if x[1..].parse::().is_ok() { data.error_codes.push(x.to_owned()); seen_rust_tags = !seen_other_tags || seen_rust_tags; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index bda220d8806..59677b28245 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -86,7 +86,7 @@ pub type NameDoc = (String, Option); crate fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { crate::html::format::display_fn(move |f| { - if !v.ends_with("/") && !v.is_empty() { write!(f, "{}/", v) } else { write!(f, "{}", v) } + if !v.ends_with('/') && !v.is_empty() { write!(f, "{}/", v) } else { write!(f, "{}", v) } }) } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 3acfb82fe78..e9ebccb7ec0 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -534,7 +534,7 @@ fn extern_location( if let Some(url) = extern_url { let mut url = url.to_string(); - if !url.ends_with("/") { + if !url.ends_with('/') { url.push('/'); } return Remote(url); @@ -548,7 +548,7 @@ fn extern_location( .filter_map(|a| a.value_str()) .map(|url| { let mut url = url.to_string(); - if !url.ends_with("/") { + if !url.ends_with('/') { url.push('/') } Remote(url) diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index a37efc22c93..a41fdd2ff17 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -19,7 +19,7 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { let mut count = 0; for line in s.lines() { - if line.starts_with("# ") || line.starts_with("%") { + if line.starts_with("# ") || line.starts_with('%') { // trim the whitespace after the symbol metadata.push(line[1..].trim_start()); count += line.len() + 1; diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 67b382c7a84..a50dd9575de 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -2396,9 +2396,9 @@ impl Iterator for Lines { match self.buf.read_line(&mut buf) { Ok(0) => None, Ok(_n) => { - if buf.ends_with("\n") { + if buf.ends_with('\n') { buf.pop(); - if buf.ends_with("\r") { + if buf.ends_with('\r') { buf.pop(); } } From b6f05674508aa115b93e9855013b3f97a687eaee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 24 Feb 2020 15:50:40 +0100 Subject: [PATCH 0546/1250] librustc_typeck: remove loop that never actually loops --- src/librustc_typeck/astconv.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 78c05a51e4f..6b7f85bcffb 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2358,10 +2358,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { break; } } - for binding in segment.generic_args().bindings { + + // Only emit the first error to avoid overloading the user with error messages. + if let [binding, ..] = segment.generic_args().bindings { has_err = true; Self::prohibit_assoc_ty_binding(self.tcx(), binding.span); - break; } } has_err From 31b9764a14f1cd2c4caeb178ef091334fd89d2ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 27 Feb 2020 00:35:04 +0100 Subject: [PATCH 0547/1250] docs: note that find(f) is equivalent to filter(f).next() in the iterator docs. --- src/libcore/iter/traits/iterator.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 1d055676c77..6a529bfc8df 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -719,6 +719,8 @@ pub trait Iterator { /// ``` /// /// of these layers. + /// + /// Note that `iter.filter(f).next()` is equivalent to `iter.find(f)`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn filter

(self, predicate: P) -> Filter @@ -2152,6 +2154,8 @@ pub trait Iterator { /// // we can still use `iter`, as there are more elements. /// assert_eq!(iter.next(), Some(&3)); /// ``` + /// + /// Note that `iter.find(f)` is equivalent to `iter.filter(f).next()`. #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn find

(&mut self, predicate: P) -> Option From c1de0b1b70cfb58cec5d35d0cd790e51618c6d53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Thu, 27 Feb 2020 13:34:08 +0100 Subject: [PATCH 0548/1250] Remove unneeded calls to format!() --- src/librustc_driver/lib.rs | 2 +- src/librustc_expand/expand.rs | 7 +++---- src/librustc_incremental/assert_module_sources.rs | 5 +---- src/librustc_incremental/persist/dirty_clean.rs | 5 +---- src/librustc_infer/traits/coherence.rs | 6 +++--- src/librustc_infer/traits/error_reporting/mod.rs | 4 +--- src/librustc_metadata/creader.rs | 5 +---- src/librustc_mir/transform/check_consts/ops.rs | 6 ++---- src/librustc_parse/parser/generics.rs | 15 ++++++--------- src/librustc_passes/weak_lang_items.rs | 4 ++-- src/librustc_resolve/diagnostics.rs | 4 ++-- src/librustc_session/config.rs | 6 ++---- src/librustc_typeck/astconv.rs | 6 +++--- src/librustc_typeck/coherence/inherent_impls.rs | 6 +++--- src/librustc_typeck/collect.rs | 6 +++--- 15 files changed, 34 insertions(+), 53 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f68ea7e0770..1296d7ad2da 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -601,7 +601,7 @@ impl RustcDefaultCalls { }); compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs) } else { - sess.fatal(&format!("rlink must be a file")) + sess.fatal("rlink must be a file") } } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index bbea066b048..53f439a4789 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1664,10 +1664,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { } } } else { - let mut err = self.cx.struct_span_err( - it.span(), - &format!("expected path to external documentation"), - ); + let mut err = self + .cx + .struct_span_err(it.span(), "expected path to external documentation"); // Check if the user erroneously used `doc(include(...))` syntax. let literal = it.meta_item_list().and_then(|list| { diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 70abb38278a..e420613ac9a 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -81,10 +81,7 @@ impl AssertModuleSource<'tcx> { if !self.tcx.sess.opts.debugging_opts.query_dep_graph { self.tcx.sess.span_fatal( attr.span, - &format!( - "found CGU-reuse attribute but `-Zquery-dep-graph` \ - was not specified" - ), + "found CGU-reuse attribute but `-Zquery-dep-graph` was not specified", ); } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index 1fa57f1ecf2..f6e2956e5b2 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -537,10 +537,7 @@ impl FindAllAttrs<'tcx> { if !checked_attrs.contains(&attr.id) { self.tcx.sess.span_err( attr.span, - &format!( - "found unchecked \ - `#[rustc_dirty]` / `#[rustc_clean]` attribute" - ), + "found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute", ); } } diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs index 43c0fbc27e6..5e314a2ffdf 100644 --- a/src/librustc_infer/traits/coherence.rs +++ b/src/librustc_infer/traits/coherence.rs @@ -39,10 +39,10 @@ pub struct OverlapResult<'tcx> { } pub fn add_placeholder_note(err: &mut rustc_errors::DiagnosticBuilder<'_>) { - err.note(&format!( + err.note( "this behavior recently changed as a result of a bug fix; \ - see rust-lang/rust#56105 for details" - )); + see rust-lang/rust#56105 for details", + ); } /// If there are types that satisfy both impls, invokes `on_overlap` diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 2fc7c178977..43ee2cbc188 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -935,9 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Already reported in the query. ConstEvalFailure(ErrorHandled::Reported) => { - self.tcx - .sess - .delay_span_bug(span, &format!("constant in type had an ignored error")); + self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); return; } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 4c4383aa603..647224bc8d6 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -680,10 +680,7 @@ impl<'a> CrateLoader<'a> { // Sanity check the loaded crate to ensure it is indeed a profiler runtime if !data.is_profiler_runtime() { - self.sess.err(&format!( - "the crate `profiler_builtins` is not \ - a profiler runtime" - )); + self.sess.err("the crate `profiler_builtins` is not a profiler runtime"); } } } diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 3263905eadb..9ba44a4d18e 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -65,10 +65,8 @@ impl NonConstOp for Downcast { pub struct FnCallIndirect; impl NonConstOp for FnCallIndirect { fn emit_error(&self, item: &Item<'_, '_>, span: Span) { - let mut err = item - .tcx - .sess - .struct_span_err(span, &format!("function pointers are not allowed in const fn")); + let mut err = + item.tcx.sess.struct_span_err(span, "function pointers are not allowed in const fn"); err.emit(); } } diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs index 0984263bb28..ef01df2ea05 100644 --- a/src/librustc_parse/parser/generics.rs +++ b/src/librustc_parse/parser/generics.rs @@ -121,15 +121,12 @@ impl<'a> Parser<'a> { .span_label(attrs[0].span, "attributes must go before parameters") .emit(); } else { - self.struct_span_err( - attrs[0].span, - &format!("attribute without generic parameters"), - ) - .span_label( - attrs[0].span, - "attributes are only permitted when preceding parameters", - ) - .emit(); + self.struct_span_err(attrs[0].span, "attribute without generic parameters") + .span_label( + attrs[0].span, + "attributes are only permitted when preceding parameters", + ) + .emit(); } } break; diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 010712c28ba..1511742446b 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -64,9 +64,9 @@ fn verify<'tcx>(tcx: TyCtxt<'tcx>, items: &lang_items::LanguageItems) { for (name, &item) in WEAK_ITEMS_REFS.iter() { if missing.contains(&item) && !whitelisted(tcx, item) && items.require(item).is_err() { if item == lang_items::PanicImplLangItem { - tcx.sess.err(&format!("`#[panic_handler]` function required, but not found")); + tcx.sess.err("`#[panic_handler]` function required, but not found"); } else if item == lang_items::OomLangItem { - tcx.sess.err(&format!("`#[alloc_error_handler]` function required, but not found")); + tcx.sess.err("`#[alloc_error_handler]` function required, but not found"); } else { tcx.sess.err(&format!("language item required, but not found: `{}`", name)); } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 7c48ccfaddd..4c850068441 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -179,7 +179,7 @@ impl<'a> Resolver<'a> { if has_generic_params == HasGenericParams::Yes { // Try to retrieve the span of the function signature and generate a new // message with a local type or const parameter. - let sugg_msg = &format!("try using a local generic parameter instead"); + let sugg_msg = "try using a local generic parameter instead"; if let Some((sugg_span, snippet)) = sm.generate_local_type_param_snippet(span) { // Suggest the modification to the user err.span_suggestion( @@ -194,7 +194,7 @@ impl<'a> Resolver<'a> { format!("try adding a local generic parameter in this method instead"), ); } else { - err.help(&format!("try using a local generic parameter instead")); + err.help("try using a local generic parameter instead"); } } diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index a6f9a5fe3e0..8392d2b50d2 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1500,10 +1500,8 @@ fn parse_libs( { early_error( error_format, - &format!( - "the library kind 'static-nobundle' is only \ - accepted on the nightly compiler" - ), + "the library kind 'static-nobundle' is only \ + accepted on the nightly compiler", ); } let mut name_parts = name.splitn(2, ':'); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 78c05a51e4f..6eec03d2e4c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -888,10 +888,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { ), ); } - err.note(&format!( + err.note( "because of the default `Self` reference, type parameters must be \ - specified on object types" - )); + specified on object types", + ); err.emit(); } diff --git a/src/librustc_typeck/coherence/inherent_impls.rs b/src/librustc_typeck/coherence/inherent_impls.rs index d4c89b7e037..49fa45836e1 100644 --- a/src/librustc_typeck/coherence/inherent_impls.rs +++ b/src/librustc_typeck/coherence/inherent_impls.rs @@ -283,10 +283,10 @@ impl ItemLikeVisitor<'v> for InherentCollect<'tcx> { "no base type found for inherent implementation" ) .span_label(ty.span, "impl requires a base type") - .note(&format!( + .note( "either implement a trait on it or create a newtype \ - to wrap it instead" - )) + to wrap it instead", + ) .emit(); return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 70586be0d04..36cd7cf7bff 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1282,10 +1282,10 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::Generics { param.hir_id, param.span, |lint| { - lint.build(&format!( + lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions." - )) + `struct`, `enum`, `type`, or `trait` definitions.", + ) .emit(); }, ); From 5fa2c9e79900cf760e442d8a7af71ddb22f5c53b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 10:03:00 -0800 Subject: [PATCH 0549/1250] Port `MaybeStorageLive` to new dataflow framework --- .../dataflow/impls/storage_liveness.rs | 64 +++++++++---------- src/librustc_mir/transform/generator.rs | 14 ++-- 2 files changed, 37 insertions(+), 41 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 659b66823c2..fdc34f2204b 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -1,47 +1,39 @@ pub use super::*; -use crate::dataflow::generic::{Results, ResultsRefCursor}; -use crate::dataflow::BitDenotation; -use crate::dataflow::MaybeBorrowedLocals; +use crate::dataflow::generic::{self as dataflow, GenKill, Results, ResultsRefCursor}; +use crate::dataflow::BottomValue; use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; use std::cell::RefCell; #[derive(Copy, Clone)] -pub struct MaybeStorageLive<'a, 'tcx> { - body: &'a Body<'tcx>, -} +pub struct MaybeStorageLive; -impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> { - pub fn new(body: &'a Body<'tcx>) -> Self { - MaybeStorageLive { body } - } +impl dataflow::AnalysisDomain<'tcx> for MaybeStorageLive { + type Idx = Local; - pub fn body(&self) -> &Body<'tcx> { - self.body - } -} + const NAME: &'static str = "maybe_storage_live"; -impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { - type Idx = Local; - fn name() -> &'static str { - "maybe_storage_live" - } - fn bits_per_block(&self) -> usize { - self.body.local_decls.len() + fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize { + body.local_decls.len() } - fn start_block_effect(&self, on_entry: &mut BitSet) { + fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut BitSet) { // The resume argument is live on function entry (we don't care about // the `self` argument) - for arg in self.body.args_iter().skip(1) { + for arg in body.args_iter().skip(1) { on_entry.insert(arg); } } +} - fn statement_effect(&self, trans: &mut GenKillSet, loc: Location) { - let stmt = &self.body[loc.block].statements[loc.statement_index]; - +impl dataflow::GenKillAnalysis<'tcx> for MaybeStorageLive { + fn statement_effect( + &self, + trans: &mut impl GenKill, + stmt: &mir::Statement<'tcx>, + _: Location, + ) { match stmt.kind { StatementKind::StorageLive(l) => trans.gen(l), StatementKind::StorageDead(l) => trans.kill(l), @@ -49,22 +41,28 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> { } } - fn terminator_effect(&self, _trans: &mut GenKillSet, _loc: Location) { + fn terminator_effect( + &self, + _trans: &mut impl GenKill, + _: &mir::Terminator<'tcx>, + _: Location, + ) { // Terminators have no effect } - fn propagate_call_return( + fn call_return_effect( &self, - _in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - _dest_place: &mir::Place<'tcx>, + _trans: &mut impl GenKill, + _block: BasicBlock, + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], + _return_place: &mir::Place<'tcx>, ) { // Nothing to do when a call returns successfully } } -impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> { +impl BottomValue for MaybeStorageLive { /// bottom = dead const BOTTOM_VALUE: bool = false; } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 3621ca63209..de9710452ee 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -473,12 +473,10 @@ fn locals_live_across_suspend_points( // Calculate when MIR locals have live storage. This gives us an upper bound of their // lifetimes. - let storage_live_analysis = MaybeStorageLive::new(body_ref); - let storage_live_results = - do_dataflow(tcx, body_ref, def_id, &[], &dead_unwinds, storage_live_analysis, |bd, p| { - DebugFormatted::new(&bd.body().local_decls[p]) - }); - let mut storage_live_cursor = DataflowResultsCursor::new(&storage_live_results, body_ref); + let mut storage_live = MaybeStorageLive + .into_engine(tcx, body_ref, def_id) + .iterate_to_fixpoint() + .into_results_cursor(body_ref); // Find the MIR locals which do not use StorageLive/StorageDead statements. // The storage of these locals are always live. @@ -534,8 +532,8 @@ fn locals_live_across_suspend_points( liveness.outs[block].union(borrowed_locals_cursor.get()); } - storage_live_cursor.seek(loc); - let storage_liveness = storage_live_cursor.get(); + storage_live.seek_before(loc); + let storage_liveness = storage_live.get(); // Store the storage liveness for later use so we can restore the state // after a suspension point From 6d7ce880aa213b631bf67cb54734e2e3ccd91336 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 09:51:21 -0800 Subject: [PATCH 0550/1250] Add inherent `visit_with` method to `dataflow::Results` This is more ergonomic than importing `dataflow::visit_results` --- src/librustc_mir/dataflow/generic/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index c61b7bed353..26aa933f423 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -75,6 +75,24 @@ where pub fn entry_set_for_block(&self, block: BasicBlock) -> &BitSet { &self.entry_sets[block] } + + pub fn visit_with( + &self, + body: &'mir mir::Body<'tcx>, + blocks: impl IntoIterator, + vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = BitSet>, + ) { + visit_results(body, blocks, self, vis) + } + + pub fn visit_in_rpo_with( + &self, + body: &'mir mir::Body<'tcx>, + vis: &mut impl ResultsVisitor<'mir, 'tcx, FlowState = BitSet>, + ) { + let blocks = mir::traversal::reverse_postorder(body); + visit_results(body, blocks.map(|(bb, _)| bb), self, vis) + } } /// Define the domain of a dataflow problem. From ecad4341af86665a2fb94dac732362d47608c73f Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 10:31:01 -0800 Subject: [PATCH 0551/1250] Port `RequiresStorage` to new dataflow framework --- src/librustc_mir/dataflow/impls/mod.rs | 2 +- .../dataflow/impls/storage_liveness.rs | 119 ++++++++++-------- src/librustc_mir/transform/generator.rs | 76 ++++------- 3 files changed, 97 insertions(+), 100 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 59aa91ab824..87d8e9e411c 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -14,7 +14,7 @@ use crate::util::elaborate_drops::DropFlagState; use super::generic::{AnalysisDomain, GenKill, GenKillAnalysis}; use super::move_paths::{HasMoveData, InitIndex, InitKind, LookupResult, MoveData, MovePathIndex}; -use super::{BottomValue, GenKillSet}; +use super::BottomValue; use super::drop_flag_effects_for_function_entry; use super::drop_flag_effects_for_location; diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index fdc34f2204b..828321f7031 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -76,7 +76,7 @@ pub struct RequiresStorage<'mir, 'tcx> { borrowed_locals: RefCell>, } -impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { pub fn new( body: ReadOnlyBodyAndCache<'mir, 'tcx>, borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>, @@ -86,45 +86,47 @@ impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> { borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)), } } - - pub fn body(&self) -> &Body<'tcx> { - &self.body - } } -impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for RequiresStorage<'mir, 'tcx> { type Idx = Local; - fn name() -> &'static str { - "requires_storage" - } - fn bits_per_block(&self) -> usize { - self.body.local_decls.len() + + const NAME: &'static str = "requires_storage"; + + fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize { + body.local_decls.len() } - fn start_block_effect(&self, on_entry: &mut BitSet) { + fn initialize_start_block(&self, body: &mir::Body<'tcx>, on_entry: &mut BitSet) { // The resume argument is live on function entry (we don't care about // the `self` argument) - for arg in self.body.args_iter().skip(1) { + for arg in body.args_iter().skip(1) { on_entry.insert(arg); } } +} - fn before_statement_effect(&self, sets: &mut GenKillSet, loc: Location) { - let stmt = &self.body[loc.block].statements[loc.statement_index]; - +impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for RequiresStorage<'mir, 'tcx> { + fn before_statement_effect( + &self, + trans: &mut impl GenKill, + stmt: &mir::Statement<'tcx>, + loc: Location, + ) { // If a place is borrowed in a statement, it needs storage for that statement. - self.borrowed_locals.borrow().analysis().statement_effect(sets, stmt, loc); + self.borrowed_locals.borrow().analysis().statement_effect(trans, stmt, loc); - // If a place is assigned to in a statement, it needs storage for that statement. match &stmt.kind { - StatementKind::StorageDead(l) => sets.kill(*l), + StatementKind::StorageDead(l) => trans.kill(*l), + + // If a place is assigned to in a statement, it needs storage for that statement. StatementKind::Assign(box (place, _)) | StatementKind::SetDiscriminant { box place, .. } => { - sets.gen(place.local); + trans.gen(place.local); } - StatementKind::InlineAsm(box InlineAsm { outputs, .. }) => { - for place in &**outputs { - sets.gen(place.local); + StatementKind::InlineAsm(asm) => { + for place in &*asm.outputs { + trans.gen(place.local); } } @@ -138,22 +140,30 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } } - fn statement_effect(&self, sets: &mut GenKillSet, loc: Location) { + fn statement_effect( + &self, + trans: &mut impl GenKill, + _: &mir::Statement<'tcx>, + loc: Location, + ) { // If we move from a place then only stops needing storage *after* // that statement. - self.check_for_move(sets, loc); + self.check_for_move(trans, loc); } - fn before_terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { - let terminator = self.body[loc.block].terminator(); - + fn before_terminator_effect( + &self, + trans: &mut impl GenKill, + terminator: &mir::Terminator<'tcx>, + loc: Location, + ) { // If a place is borrowed in a terminator, it needs storage for that terminator. - self.borrowed_locals.borrow().analysis().terminator_effect(sets, terminator, loc); + self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc); match &terminator.kind { - TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } - | TerminatorKind::Yield { resume_arg: Place { local, .. }, .. } => { - sets.gen(*local); + TerminatorKind::Call { destination: Some((place, _)), .. } + | TerminatorKind::Yield { resume_arg: place, .. } => { + trans.gen(place.local); } // Nothing to do for these. Match exhaustively so this fails to compile when new @@ -174,14 +184,19 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { } } - fn terminator_effect(&self, sets: &mut GenKillSet, loc: Location) { - match &self.body[loc.block].terminator().kind { + fn terminator_effect( + &self, + trans: &mut impl GenKill, + terminator: &mir::Terminator<'tcx>, + loc: Location, + ) { + match &terminator.kind { // For call terminators the destination requires storage for the call // and after the call returns successfully, but not after a panic. // Since `propagate_call_unwind` doesn't exist, we have to kill the - // destination here, and then gen it again in `propagate_call_return`. - TerminatorKind::Call { destination: Some((Place { local, .. }, _)), .. } => { - sets.kill(*local); + // destination here, and then gen it again in `call_return_effect`. + TerminatorKind::Call { destination: Some((place, _)), .. } => { + trans.kill(place.local); } // Nothing to do for these. Match exhaustively so this fails to compile when new @@ -202,24 +217,25 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> { | TerminatorKind::Unreachable => {} } - self.check_for_move(sets, loc); + self.check_for_move(trans, loc); } - fn propagate_call_return( + fn call_return_effect( &self, - in_out: &mut BitSet, - _call_bb: mir::BasicBlock, - _dest_bb: mir::BasicBlock, - dest_place: &mir::Place<'tcx>, + trans: &mut impl GenKill, + _block: BasicBlock, + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], + return_place: &mir::Place<'tcx>, ) { - in_out.insert(dest_place.local); + trans.gen(return_place.local); } } impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. - fn check_for_move(&self, sets: &mut GenKillSet, loc: Location) { - let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals }; + fn check_for_move(&self, trans: &mut impl GenKill, loc: Location) { + let mut visitor = MoveVisitor { trans, borrowed_locals: &self.borrowed_locals }; visitor.visit_location(self.body, loc); } } @@ -229,18 +245,21 @@ impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> { const BOTTOM_VALUE: bool = false; } -struct MoveVisitor<'a, 'mir, 'tcx> { +struct MoveVisitor<'a, 'mir, 'tcx, T> { borrowed_locals: &'a RefCell>, - sets: &'a mut GenKillSet, + trans: &'a mut T, } -impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> { +impl<'a, 'mir, 'tcx, T> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx, T> +where + T: GenKill, +{ fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) { if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context { let mut borrowed_locals = self.borrowed_locals.borrow_mut(); borrowed_locals.seek_before(loc); if !borrowed_locals.contains(*local) { - self.sets.kill(*local); + self.trans.kill(*local); } } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index de9710452ee..b9d2a167d73 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -49,9 +49,7 @@ //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing. //! Otherwise it drops all the values in scope at the last suspension point. -use crate::dataflow::generic::{Analysis, ResultsCursor}; -use crate::dataflow::{do_dataflow, DataflowResultsCursor, DebugFormatted}; -use crate::dataflow::{DataflowResults, DataflowResultsConsumer, FlowAtLocation}; +use crate::dataflow::generic::{self as dataflow, Analysis}; use crate::dataflow::{MaybeBorrowedLocals, MaybeStorageLive, RequiresStorage}; use crate::transform::no_landing_pads::no_landing_pads; use crate::transform::simplify; @@ -467,7 +465,6 @@ fn locals_live_across_suspend_points( source: MirSource<'tcx>, movable: bool, ) -> LivenessInfo { - let dead_unwinds = BitSet::new_empty(body.basic_blocks().len()); let def_id = source.def_id(); let body_ref: &Body<'_> = &body; @@ -488,22 +485,16 @@ fn locals_live_across_suspend_points( let borrowed_locals_results = MaybeBorrowedLocals::all_borrows().into_engine(tcx, body_ref, def_id).iterate_to_fixpoint(); - let mut borrowed_locals_cursor = ResultsCursor::new(body_ref, &borrowed_locals_results); + let mut borrowed_locals_cursor = + dataflow::ResultsCursor::new(body_ref, &borrowed_locals_results); // Calculate the MIR locals that we actually need to keep storage around // for. - let requires_storage_analysis = RequiresStorage::new(body, &borrowed_locals_results); - let requires_storage_results = do_dataflow( - tcx, - body_ref, - def_id, - &[], - &dead_unwinds, - requires_storage_analysis, - |bd, p| DebugFormatted::new(&bd.body().local_decls[p]), - ); + let requires_storage_results = RequiresStorage::new(body, &borrowed_locals_results) + .into_engine(tcx, body_ref, def_id) + .iterate_to_fixpoint(); let mut requires_storage_cursor = - DataflowResultsCursor::new(&requires_storage_results, body_ref); + dataflow::ResultsCursor::new(body_ref, &requires_storage_results); // Calculate the liveness of MIR locals ignoring borrows. let mut live_locals = liveness::LiveVarSet::new_empty(body.local_decls.len()); @@ -539,7 +530,7 @@ fn locals_live_across_suspend_points( // after a suspension point storage_liveness_map.insert(block, storage_liveness.clone()); - requires_storage_cursor.seek(loc); + requires_storage_cursor.seek_before(loc); let storage_required = requires_storage_cursor.get().clone(); // Locals live are live at this point only if they are used across @@ -609,7 +600,7 @@ fn compute_storage_conflicts( body: &'mir Body<'tcx>, stored_locals: &liveness::LiveVarSet, ignored: &StorageIgnored, - requires_storage: DataflowResults<'tcx, RequiresStorage<'mir, 'tcx>>, + requires_storage: dataflow::Results<'tcx, RequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), ignored.0.domain_size()); assert_eq!(body.local_decls.len(), stored_locals.domain_size()); @@ -627,8 +618,10 @@ fn compute_storage_conflicts( stored_locals: &stored_locals, local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), }; - let mut state = FlowAtLocation::new(requires_storage); - visitor.analyze_results(&mut state); + + // FIXME: Do we need to do this in RPO? + requires_storage.visit_in_rpo_with(body, &mut visitor); + let local_conflicts = visitor.local_conflicts; // Compress the matrix using only stored locals (Local -> GeneratorSavedLocal). @@ -657,60 +650,45 @@ fn compute_storage_conflicts( storage_conflicts } -struct StorageConflictVisitor<'body, 'tcx, 's> { - body: &'body Body<'tcx>, +struct StorageConflictVisitor<'mir, 'tcx, 's> { + body: &'mir Body<'tcx>, stored_locals: &'s liveness::LiveVarSet, // FIXME(tmandry): Consider using sparse bitsets here once we have good // benchmarks for generators. local_conflicts: BitMatrix, } -impl<'body, 'tcx, 's> DataflowResultsConsumer<'body, 'tcx> - for StorageConflictVisitor<'body, 'tcx, 's> -{ - type FlowState = FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>; - - fn body(&self) -> &'body Body<'tcx> { - self.body - } - - fn visit_block_entry(&mut self, block: BasicBlock, flow_state: &Self::FlowState) { - // statement_index is only used for logging, so this is fine. - self.apply_state(flow_state, Location { block, statement_index: 0 }); - } +impl dataflow::ResultsVisitor<'mir, 'tcx> for StorageConflictVisitor<'mir, 'tcx, '_> { + type FlowState = BitSet; - fn visit_statement_entry( + fn visit_statement( &mut self, + state: &Self::FlowState, + _statement: &'mir Statement<'tcx>, loc: Location, - _stmt: &Statement<'tcx>, - flow_state: &Self::FlowState, ) { - self.apply_state(flow_state, loc); + self.apply_state(state, loc); } - fn visit_terminator_entry( + fn visit_terminator( &mut self, + state: &Self::FlowState, + _terminator: &'mir Terminator<'tcx>, loc: Location, - _term: &Terminator<'tcx>, - flow_state: &Self::FlowState, ) { - self.apply_state(flow_state, loc); + self.apply_state(state, loc); } } impl<'body, 'tcx, 's> StorageConflictVisitor<'body, 'tcx, 's> { - fn apply_state( - &mut self, - flow_state: &FlowAtLocation<'tcx, RequiresStorage<'body, 'tcx>>, - loc: Location, - ) { + fn apply_state(&mut self, flow_state: &BitSet, loc: Location) { // Ignore unreachable blocks. match self.body.basic_blocks()[loc.block].terminator().kind { TerminatorKind::Unreachable => return, _ => (), }; - let mut eligible_storage_live = flow_state.as_dense().clone(); + let mut eligible_storage_live = flow_state.clone(); eligible_storage_live.intersect(&self.stored_locals); for local in eligible_storage_live.iter() { From e1f8a22271cdca71c7ca310e935ef6446e66c585 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 18 Feb 2020 10:35:16 -0800 Subject: [PATCH 0552/1250] Rename `RequiresStorage` to `MaybeRequiresStorage` ...to be consistent with the naming of other dataflow analyses. --- .../dataflow/impls/storage_liveness.rs | 14 +++++++------- src/librustc_mir/dataflow/mod.rs | 2 +- src/librustc_mir/transform/generator.rs | 6 +++--- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index 828321f7031..fabe562e68a 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -71,24 +71,24 @@ type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorro /// Dataflow analysis that determines whether each local requires storage at a /// given location; i.e. whether its storage can go away without being observed. -pub struct RequiresStorage<'mir, 'tcx> { +pub struct MaybeRequiresStorage<'mir, 'tcx> { body: ReadOnlyBodyAndCache<'mir, 'tcx>, borrowed_locals: RefCell>, } -impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { pub fn new( body: ReadOnlyBodyAndCache<'mir, 'tcx>, borrowed_locals: &'mir Results<'tcx, MaybeBorrowedLocals>, ) -> Self { - RequiresStorage { + MaybeRequiresStorage { body, borrowed_locals: RefCell::new(ResultsRefCursor::new(*body, borrowed_locals)), } } } -impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { type Idx = Local; const NAME: &'static str = "requires_storage"; @@ -106,7 +106,7 @@ impl<'mir, 'tcx> dataflow::AnalysisDomain<'tcx> for RequiresStorage<'mir, 'tcx> } } -impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tcx> { fn before_statement_effect( &self, trans: &mut impl GenKill, @@ -232,7 +232,7 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for RequiresStorage<'mir, 'tcx> } } -impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { /// Kill locals that are fully moved and have not been borrowed. fn check_for_move(&self, trans: &mut impl GenKill, loc: Location) { let mut visitor = MoveVisitor { trans, borrowed_locals: &self.borrowed_locals }; @@ -240,7 +240,7 @@ impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> { } } -impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> { +impl<'mir, 'tcx> BottomValue for MaybeRequiresStorage<'mir, 'tcx> { /// bottom = dead const BOTTOM_VALUE: bool = false; } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index eccdac2fb99..0b45f660c3a 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -25,7 +25,7 @@ pub use self::impls::DefinitelyInitializedPlaces; pub use self::impls::EverInitializedPlaces; pub use self::impls::{MaybeBorrowedLocals, MaybeMutBorrowedLocals}; pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; -pub use self::impls::{MaybeStorageLive, RequiresStorage}; +pub use self::impls::{MaybeRequiresStorage, MaybeStorageLive}; use self::move_paths::MoveData; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index b9d2a167d73..770f93517d0 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -50,7 +50,7 @@ //! Otherwise it drops all the values in scope at the last suspension point. use crate::dataflow::generic::{self as dataflow, Analysis}; -use crate::dataflow::{MaybeBorrowedLocals, MaybeStorageLive, RequiresStorage}; +use crate::dataflow::{MaybeBorrowedLocals, MaybeRequiresStorage, MaybeStorageLive}; use crate::transform::no_landing_pads::no_landing_pads; use crate::transform::simplify; use crate::transform::{MirPass, MirSource}; @@ -490,7 +490,7 @@ fn locals_live_across_suspend_points( // Calculate the MIR locals that we actually need to keep storage around // for. - let requires_storage_results = RequiresStorage::new(body, &borrowed_locals_results) + let requires_storage_results = MaybeRequiresStorage::new(body, &borrowed_locals_results) .into_engine(tcx, body_ref, def_id) .iterate_to_fixpoint(); let mut requires_storage_cursor = @@ -600,7 +600,7 @@ fn compute_storage_conflicts( body: &'mir Body<'tcx>, stored_locals: &liveness::LiveVarSet, ignored: &StorageIgnored, - requires_storage: dataflow::Results<'tcx, RequiresStorage<'mir, 'tcx>>, + requires_storage: dataflow::Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, ) -> BitMatrix { assert_eq!(body.local_decls.len(), ignored.0.domain_size()); assert_eq!(body.local_decls.len(), stored_locals.domain_size()); From 75d256fc61afc70af8f093a14f8b7c02185396ee Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Wed, 19 Feb 2020 09:54:48 -0800 Subject: [PATCH 0553/1250] Remove now unused `GenKill` impl for old `GenKillSet` --- src/librustc_mir/dataflow/generic/mod.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index 26aa933f423..9a102c9a3d0 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -451,16 +451,5 @@ impl GenKill for BitSet { } } -// For compatibility with old framework -impl GenKill for crate::dataflow::GenKillSet { - fn gen(&mut self, elem: T) { - self.gen(elem); - } - - fn kill(&mut self, elem: T) { - self.kill(elem); - } -} - #[cfg(test)] mod tests; From 13d42f4784c2454a1890e48f50a8f672f4c0494c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 27 Feb 2020 20:09:14 +0100 Subject: [PATCH 0554/1250] error_derive_forbidden_on_non_adt: be more graceful --- src/librustc_expand/expand.rs | 7 +++-- .../issue-69341-malformed-derive-inert.rs | 10 +++++++ .../issue-69341-malformed-derive-inert.stderr | 26 +++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/malformed/issue-69341-malformed-derive-inert.rs create mode 100644 src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 8ed7bbf6e12..84fe609ef9a 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -503,13 +503,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } fn error_derive_forbidden_on_non_adt(&self, derives: &[Path], item: &Annotatable) { - let attr = - attr::find_by_name(item.attrs(), sym::derive).expect("`derive` attribute should exist"); - let span = attr.span; + let attr = attr::find_by_name(item.attrs(), sym::derive); + let span = attr.map_or(item.span(), |attr| attr.span); let mut err = self .cx .struct_span_err(span, "`derive` may only be applied to structs, enums and unions"); - if let ast::AttrStyle::Inner = attr.style { + if let Some(ast::Attribute { style: ast::AttrStyle::Inner, .. }) = attr { let trait_list = derives.iter().map(|t| pprust::path_to_string(t)).collect::>(); let suggestion = format!("#[derive({})]", trait_list.join(", ")); err.span_suggestion( diff --git a/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs b/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs new file mode 100644 index 00000000000..24692f7cf52 --- /dev/null +++ b/src/test/ui/malformed/issue-69341-malformed-derive-inert.rs @@ -0,0 +1,10 @@ +fn main() {} + +struct CLI { + #[derive(parse())] + //~^ ERROR traits in `#[derive(...)]` don't accept arguments + //~| ERROR cannot find derive macro `parse` in this scope + //~| ERROR cannot find derive macro `parse` in this scope + path: (), + //~^ ERROR `derive` may only be applied to structs, enums and unions +} diff --git a/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr b/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr new file mode 100644 index 00000000000..e8f96178d10 --- /dev/null +++ b/src/test/ui/malformed/issue-69341-malformed-derive-inert.stderr @@ -0,0 +1,26 @@ +error: traits in `#[derive(...)]` don't accept arguments + --> $DIR/issue-69341-malformed-derive-inert.rs:4:19 + | +LL | #[derive(parse())] + | ^^ help: remove the arguments + +error: `derive` may only be applied to structs, enums and unions + --> $DIR/issue-69341-malformed-derive-inert.rs:8:5 + | +LL | path: (), + | ^^^^^^^^ + +error: cannot find derive macro `parse` in this scope + --> $DIR/issue-69341-malformed-derive-inert.rs:4:14 + | +LL | #[derive(parse())] + | ^^^^^ + +error: cannot find derive macro `parse` in this scope + --> $DIR/issue-69341-malformed-derive-inert.rs:4:14 + | +LL | #[derive(parse())] + | ^^^^^ + +error: aborting due to 4 previous errors + From 6f40cdb3807b25c92d32c5f7c3180958bb62f3c8 Mon Sep 17 00:00:00 2001 From: Albin Stjerna Date: Wed, 20 Nov 2019 20:34:24 +0100 Subject: [PATCH 0555/1250] - polonius: adapt to the new fact format - update polonius-engine dependency to 0.12.0 - rustfmt the files failing tidy --- Cargo.lock | 4 +- src/librustc/Cargo.toml | 2 +- src/librustc_mir/Cargo.toml | 2 +- src/librustc_mir/borrow_check/facts.rs | 20 ++++----- src/librustc_mir/borrow_check/nll.rs | 30 +++++++++---- .../type_check/liveness/polonius.rs | 45 ++++++++++--------- .../borrow_check/type_check/liveness/trace.rs | 2 +- 7 files changed, 60 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index beda3993353..93d7c83a036 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2494,9 +2494,9 @@ checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "polonius-engine" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e478d7c38eb785c6416cbe58df12aa55d7aefa3759b6d3e044b2ed03f423cec" +checksum = "04d8ef65e3f89ecaec9ca7cb0e0911b4617352d4494018bcf934992f03f2024c" dependencies = [ "datafrog", "log", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index af2be30cc0a..0fa70b76063 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -17,7 +17,7 @@ scoped-tls = "1.0" log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc-rayon = "0.3.0" rustc-rayon-core = "0.3.0" -polonius-engine = "0.11.0" +polonius-engine = "0.12.0" rustc_apfloat = { path = "../librustc_apfloat" } rustc_attr = { path = "../librustc_attr" } rustc_feature = { path = "../librustc_feature" } diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index 3554fe54c45..4bbe05cf596 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -15,7 +15,7 @@ dot = { path = "../libgraphviz", package = "graphviz" } itertools = "0.8" log = "0.4" log_settings = "0.1.1" -polonius-engine = "0.11.0" +polonius-engine = "0.12.0" rustc = { path = "../librustc" } rustc_ast_pretty = { path = "../librustc_ast_pretty" } rustc_attr = { path = "../librustc_attr" } diff --git a/src/librustc_mir/borrow_check/facts.rs b/src/librustc_mir/borrow_check/facts.rs index 827ccb1c857..cd8139b17b4 100644 --- a/src/librustc_mir/borrow_check/facts.rs +++ b/src/librustc_mir/borrow_check/facts.rs @@ -71,16 +71,16 @@ impl AllFactsExt for AllFacts { killed, outlives, invalidates, - var_used, - var_defined, - var_drop_used, - var_uses_region, - var_drops_region, - child, - path_belongs_to_var, - initialized_at, - moved_out_at, - path_accessed_at, + var_used_at, + var_defined_at, + var_dropped_at, + use_of_var_derefs_origin, + drop_of_var_derefs_origin, + child_path, + path_is_var, + path_assigned_at_base, + path_moved_at_base, + path_accessed_at_base, known_subset, ]) } diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 2201abe4b92..ba1b322524e 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -86,15 +86,18 @@ fn populate_polonius_move_facts( body: &Body<'_>, ) { all_facts - .path_belongs_to_var + .path_is_var .extend(move_data.rev_lookup.iter_locals_enumerated().map(|(v, &m)| (m, v))); for (child, move_path) in move_data.move_paths.iter_enumerated() { - all_facts - .child - .extend(move_path.parents(&move_data.move_paths).map(|(parent, _)| (child, parent))); + if let Some(parent) = move_path.parent { + all_facts.child_path.push((child, parent)); + } } + let fn_entry_start = location_table + .start_index(Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }); + // initialized_at for init in move_data.inits.iter() { match init.location { @@ -115,28 +118,37 @@ fn populate_polonius_move_facts( // the successors, but not in the unwind block. let first_statement = Location { block: successor, statement_index: 0 }; all_facts - .initialized_at + .path_assigned_at_base .push((init.path, location_table.start_index(first_statement))); } } else { // In all other cases, the initialization just happens at the // midpoint, like any other effect. - all_facts.initialized_at.push((init.path, location_table.mid_index(location))); + all_facts + .path_assigned_at_base + .push((init.path, location_table.mid_index(location))); } } // Arguments are initialized on function entry InitLocation::Argument(local) => { assert!(body.local_kind(local) == LocalKind::Arg); - let fn_entry = Location { block: BasicBlock::from_u32(0u32), statement_index: 0 }; - all_facts.initialized_at.push((init.path, location_table.start_index(fn_entry))); + all_facts.path_assigned_at_base.push((init.path, fn_entry_start)); } } } + for (local, &path) in move_data.rev_lookup.iter_locals_enumerated() { + if body.local_kind(local) != LocalKind::Arg { + // Non-arguments start out deinitialised; we simulate this with an + // initial move: + all_facts.path_moved_at_base.push((path, fn_entry_start)); + } + } + // moved_out_at // deinitialisation is assumed to always happen! all_facts - .moved_out_at + .path_moved_at_base .extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source)))); } diff --git a/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs index 055415f2872..407e0628b6e 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/polonius.rs @@ -12,12 +12,12 @@ type VarPointRelation = Vec<(Local, LocationIndex)>; type PathPointRelation = Vec<(MovePathIndex, LocationIndex)>; struct UseFactsExtractor<'me> { - var_defined: &'me mut VarPointRelation, - var_used: &'me mut VarPointRelation, + var_defined_at: &'me mut VarPointRelation, + var_used_at: &'me mut VarPointRelation, location_table: &'me LocationTable, - var_drop_used: &'me mut Vec<(Local, Location)>, + var_dropped_at: &'me mut VarPointRelation, move_data: &'me MoveData<'me>, - path_accessed_at: &'me mut PathPointRelation, + path_accessed_at_base: &'me mut PathPointRelation, } // A Visitor to walk through the MIR and extract point-wise facts @@ -28,22 +28,22 @@ impl UseFactsExtractor<'_> { fn insert_def(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_def()"); - self.var_defined.push((local, self.location_to_index(location))); + self.var_defined_at.push((local, self.location_to_index(location))); } fn insert_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_use()"); - self.var_used.push((local, self.location_to_index(location))); + self.var_used_at.push((local, self.location_to_index(location))); } fn insert_drop_use(&mut self, local: Local, location: Location) { debug!("UseFactsExtractor::insert_drop_use()"); - self.var_drop_used.push((local, location)); + self.var_dropped_at.push((local, self.location_to_index(location))); } fn insert_path_access(&mut self, path: MovePathIndex, location: Location) { debug!("UseFactsExtractor::insert_path_access({:?}, {:?})", path, location); - self.path_accessed_at.push((path, self.location_to_index(location))); + self.path_accessed_at_base.push((path, self.location_table.start_index(location))); } fn place_to_mpi(&self, place: &Place<'_>) -> Option { @@ -88,51 +88,54 @@ pub(super) fn populate_access_facts( body: ReadOnlyBodyAndCache<'_, 'tcx>, location_table: &LocationTable, move_data: &MoveData<'_>, - drop_used: &mut Vec<(Local, Location)>, + dropped_at: &mut Vec<(Local, Location)>, ) { debug!("populate_access_facts()"); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { let mut extractor = UseFactsExtractor { - var_defined: &mut facts.var_defined, - var_used: &mut facts.var_used, - var_drop_used: drop_used, - path_accessed_at: &mut facts.path_accessed_at, + var_defined_at: &mut facts.var_defined_at, + var_used_at: &mut facts.var_used_at, + var_dropped_at: &mut facts.var_dropped_at, + path_accessed_at_base: &mut facts.path_accessed_at_base, location_table, move_data, }; extractor.visit_body(body); - facts.var_drop_used.extend( - drop_used.iter().map(|&(local, location)| (local, location_table.mid_index(location))), + facts.var_dropped_at.extend( + dropped_at.iter().map(|&(local, location)| (local, location_table.mid_index(location))), ); for (local, local_decl) in body.local_decls.iter_enumerated() { - debug!("add var_uses_regions facts - local={:?}, type={:?}", local, local_decl.ty); + debug!( + "add use_of_var_derefs_origin facts - local={:?}, type={:?}", + local, local_decl.ty + ); let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(&local_decl.ty, |region| { let region_vid = universal_regions.to_region_vid(region); - facts.var_uses_region.push((local, region_vid)); + facts.use_of_var_derefs_origin.push((local, region_vid)); }); } } } // For every potentially drop()-touched region `region` in `local`'s type -// (`kind`), emit a Polonius `var_drops_region(local, region)` fact. -pub(super) fn add_var_drops_regions( +// (`kind`), emit a Polonius `use_of_var_derefs_origin(local, origin)` fact. +pub(super) fn add_drop_of_var_derefs_origin( typeck: &mut TypeChecker<'_, 'tcx>, local: Local, kind: &GenericArg<'tcx>, ) { - debug!("add_var_drops_region(local={:?}, kind={:?}", local, kind); + debug!("add_drop_of_var_derefs_origin(local={:?}, kind={:?}", local, kind); if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() { let _prof_timer = typeck.infcx.tcx.prof.generic_activity("polonius_fact_generation"); let universal_regions = &typeck.borrowck_context.universal_regions; typeck.infcx.tcx.for_each_free_region(kind, |drop_live_region| { let region_vid = universal_regions.to_region_vid(drop_live_region); - facts.var_drops_region.push((local, region_vid)); + facts.drop_of_var_derefs_origin.push((local, region_vid)); }); } } diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index 4c8deb0ecf8..baa9d1d212e 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -484,7 +484,7 @@ impl LivenessContext<'_, '_, '_, 'tcx> { for &kind in &drop_data.dropck_result.kinds { Self::make_all_regions_live(self.elements, &mut self.typeck, kind, live_at); - polonius::add_var_drops_regions(&mut self.typeck, dropped_local, &kind); + polonius::add_drop_of_var_derefs_origin(&mut self.typeck, dropped_local, &kind); } } From cac4eeee24b8e17540dfbc28d31f39a732112118 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 27 Feb 2020 15:52:09 -0500 Subject: [PATCH 0556/1250] Ignore untracked paths when running `rustfmt` on repository. --- src/bootstrap/format.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6e5e3fe07e7..a4acb14ee4b 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -1,7 +1,7 @@ //! Runs rustfmt on the repository. use crate::Build; -use build_helper::t; +use build_helper::{output, t}; use ignore::WalkBuilder; use std::path::Path; use std::process::Command; @@ -53,6 +53,17 @@ pub fn format(build: &Build, check: bool) { for ignore in rustfmt_config.ignore { ignore_fmt.add(&format!("!{}", ignore)).expect(&ignore); } + let untracked_paths_output = output( + Command::new("git").arg("status").arg("--porcelain").arg("--untracked-files=normal"), + ); + let untracked_paths = untracked_paths_output + .lines() + .filter(|entry| entry.starts_with("??")) + .map(|entry| entry.split(" ").nth(1).expect("every git status entry should list a path")); + for untracked_path in untracked_paths { + eprintln!("skip untracked path {} during rustfmt invocations", untracked_path); + ignore_fmt.add(&format!("!{}", untracked_path)).expect(&untracked_path); + } let ignore_fmt = ignore_fmt.build().unwrap(); let rustfmt_path = build.config.initial_rustfmt.as_ref().unwrap_or_else(|| { From 7be94a8a958750cf57c0fa41ad7797a2cd1630de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 25 Feb 2020 18:10:34 +0100 Subject: [PATCH 0557/1250] don't use .into() to convert types into identical types. example: let s: String = format!("hello").into(); --- src/librustc/mir/interpret/allocation.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/mir/tcx.rs | 2 +- src/librustc/traits/mod.rs | 3 +-- src/librustc_ast_lowering/expr.rs | 7 +++---- src/librustc_codegen_ssa/mir/operand.rs | 3 +-- src/librustc_codegen_ssa/mir/rvalue.rs | 2 +- src/librustc_expand/mbe/quoted.rs | 4 ++-- src/librustc_expand/mbe/transcribe.rs | 3 +-- src/librustc_expand/proc_macro_server.rs | 10 +++------- .../infer/canonical/canonicalizer.rs | 2 +- src/librustc_infer/infer/outlives/verify.rs | 1 - src/librustc_infer/traits/select.rs | 2 +- src/librustc_interface/util.rs | 2 +- .../borrow_check/region_infer/reverse_sccs.rs | 2 +- src/librustc_mir/const_eval/mod.rs | 2 +- src/librustc_mir/interpret/intrinsics.rs | 2 +- src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/transform/mod.rs | 2 +- src/librustc_mir/util/aggregate.rs | 1 - src/librustc_mir_build/build/matches/mod.rs | 4 ++-- src/librustc_mir_build/build/mod.rs | 4 ++-- src/librustc_parse/lexer/mod.rs | 15 +++++---------- src/librustc_parse/lexer/tokentrees.rs | 2 +- src/librustc_parse/lib.rs | 2 +- src/librustc_parse/parser/mod.rs | 7 +++---- src/librustc_parse/parser/stmt.rs | 2 +- src/librustc_passes/loops.rs | 2 +- src/librustc_traits/generic_types.rs | 2 -- src/librustc_typeck/outlives/implicit_infer.rs | 2 +- src/libstd/sys/unix/process/process_common.rs | 4 +--- src/libsyntax/attr/mod.rs | 2 +- 32 files changed, 42 insertions(+), 62 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index 052603f6e5e..0d0aa8a232e 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -472,7 +472,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra> Allocation { val: ScalarMaybeUndef, ) -> InterpResult<'tcx> { let ptr_size = cx.data_layout().pointer_size; - self.write_scalar(cx, ptr.into(), val, ptr_size) + self.write_scalar(cx, ptr, val, ptr_size) } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3086f9b04df..6a937b87645 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1519,7 +1519,7 @@ impl<'tcx> TerminatorKind<'tcx> { values .iter() .map(|&u| { - ty::Const::from_scalar(tcx, Scalar::from_uint(u, size).into(), switch_ty) + ty::Const::from_scalar(tcx, Scalar::from_uint(u, size), switch_ty) .to_string() .into() }) diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index e6c7c84494c..13996a74acb 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -156,7 +156,7 @@ impl<'tcx> Rvalue<'tcx> { } Rvalue::AddressOf(mutability, ref place) => { let place_ty = place.ty(local_decls, tcx).ty; - tcx.mk_ptr(ty::TypeAndMut { ty: place_ty, mutbl: mutability.into() }) + tcx.mk_ptr(ty::TypeAndMut { ty: place_ty, mutbl: mutability }) } Rvalue::Len(..) => tcx.types.usize, Rvalue::Cast(.., ty) => ty, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index de2ec53e51e..b05bd26f048 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -820,8 +820,7 @@ impl ObjectSafetyViolation { MethodViolationCode::UndispatchableReceiver, span, ) => ( - format!("consider changing method `{}`'s `self` parameter to be `&self`", name) - .into(), + format!("consider changing method `{}`'s `self` parameter to be `&self`", name), Some(("&Self".to_string(), span)), ), ObjectSafetyViolation::AssocConst(name, _) diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs index e2dd55b4cba..d781fbde59c 100644 --- a/src/librustc_ast_lowering/expr.rs +++ b/src/librustc_ast_lowering/expr.rs @@ -831,8 +831,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .last() .cloned() .map(|id| Ok(self.lower_node_id(id))) - .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)) - .into(), + .unwrap_or(Err(hir::LoopIdError::OutsideLoopScope)), }; hir::Destination { label: destination.map(|(_, label)| label), target_id } } @@ -841,7 +840,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if self.is_in_loop_condition && opt_label.is_none() { hir::Destination { label: None, - target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition).into(), + target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition), } } else { self.lower_loop_destination(opt_label.map(|label| (id, label))) @@ -912,7 +911,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .collect(), asm: asm.asm, asm_str_style: asm.asm_str_style, - clobbers: asm.clobbers.clone().into(), + clobbers: asm.clobbers.clone(), volatile: asm.volatile, alignstack: asm.alignstack, dialect: asm.dialect, diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 07c8829e7d8..af95450935c 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -92,8 +92,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let a = Scalar::from(Pointer::new( bx.tcx().alloc_map.lock().create_memory_alloc(data), Size::from_bytes(start as u64), - )) - .into(); + )); let a_llval = bx.scalar_to_backend( a, a_scalar, diff --git a/src/librustc_codegen_ssa/mir/rvalue.rs b/src/librustc_codegen_ssa/mir/rvalue.rs index 2f83298741a..6d004606398 100644 --- a/src/librustc_codegen_ssa/mir/rvalue.rs +++ b/src/librustc_codegen_ssa/mir/rvalue.rs @@ -387,7 +387,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::AddressOf(mutability, ref place) => { let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| { - tcx.mk_ptr(ty::TypeAndMut { ty, mutbl: mutability.into() }) + tcx.mk_ptr(ty::TypeAndMut { ty, mutbl: mutability }) }; self.codegen_place_to_pointer(bx, place, mk_ptr) } diff --git a/src/librustc_expand/mbe/quoted.rs b/src/librustc_expand/mbe/quoted.rs index 9ae8ead1a72..809bbe47a6e 100644 --- a/src/librustc_expand/mbe/quoted.rs +++ b/src/librustc_expand/mbe/quoted.rs @@ -112,7 +112,7 @@ fn parse_tree( sess.span_diagnostic.span_err(span.entire(), &msg); } // Parse the contents of the sequence itself - let sequence = parse(tts.into(), expect_matchers, sess); + let sequence = parse(tts, expect_matchers, sess); // Get the Kleene operator and optional separator let (separator, kleene) = parse_sep_and_kleene_op(trees, span.entire(), sess); // Count the number of captured "names" (i.e., named metavars) @@ -159,7 +159,7 @@ fn parse_tree( // descend into the delimited set and further parse it. tokenstream::TokenTree::Delimited(span, delim, tts) => TokenTree::Delimited( span, - Lrc::new(Delimited { delim, tts: parse(tts.into(), expect_matchers, sess) }), + Lrc::new(Delimited { delim, tts: parse(tts, expect_matchers, sess) }), ), } } diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 104a5233c9d..9e6a2c4f8f5 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -155,8 +155,7 @@ pub(super) fn transcribe( } // Step back into the parent Delimited. - let tree = - TokenTree::Delimited(span, forest.delim, TokenStream::new(result).into()); + let tree = TokenTree::Delimited(span, forest.delim, TokenStream::new(result)); result = result_stack.pop().unwrap(); result.push(tree.into()); } diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index a7397e576b1..afaba6bf315 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -60,7 +60,7 @@ impl FromInternal<(TreeAndJoint, &'_ ParseSess, &'_ mut Vec)> let Token { kind, span } = match tree { tokenstream::TokenTree::Delimited(span, delim, tts) => { let delimiter = Delimiter::from_internal(delim); - return TokenTree::Group(Group { delimiter, stream: tts.into(), span }); + return TokenTree::Group(Group { delimiter, stream: tts, span }); } tokenstream::TokenTree::Token(token) => token, }; @@ -196,12 +196,8 @@ impl ToInternal for TokenTree { let (ch, joint, span) = match self { TokenTree::Punct(Punct { ch, joint, span }) => (ch, joint, span), TokenTree::Group(Group { delimiter, stream, span }) => { - return tokenstream::TokenTree::Delimited( - span, - delimiter.to_internal(), - stream.into(), - ) - .into(); + return tokenstream::TokenTree::Delimited(span, delimiter.to_internal(), stream) + .into(); } TokenTree::Ident(self::Ident { sym, is_raw, span }) => { return tokenstream::TokenTree::token(Ident(sym, is_raw), span).into(); diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index ecd7281351d..26f855b177e 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -669,7 +669,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> { } else { let var = self.canonical_var(info, const_var.into()); self.tcx().mk_const(ty::Const { - val: ty::ConstKind::Bound(self.binder_index, var.into()), + val: ty::ConstKind::Bound(self.binder_index, var), ty: self.fold_ty(const_var.ty), }) } diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index be6f868430d..08f73d2c9d2 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -140,7 +140,6 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // Extend with bounds that we can find from the trait. let trait_bounds = self .projection_declared_bounds_from_trait(projection_ty) - .into_iter() .map(|r| VerifyBound::OutlivedBy(r)); // see the extensive comment in projection_must_outlive diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index 371268b5ee4..4eac89138f1 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -3202,7 +3202,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation.predicate.def_id(), obligation.recursion_depth + 1, a_last.expect_ty(), - &[b_last.into()], + &[b_last], )); } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index c73f7aafb48..781b33bd94c 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -639,7 +639,7 @@ impl<'a, 'b> ReplaceBodyWithLoop<'a, 'b> { ast::GenericArg::Type(ty) => Some(ty), _ => None, }); - any_involves_impl_trait(types.into_iter()) + any_involves_impl_trait(types) || data.constraints.iter().any(|c| match c.kind { ast::AssocTyConstraintKind::Bound { .. } => true, ast::AssocTyConstraintKind::Equality { ref ty } => { diff --git a/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs index 4b8357bda02..ff19ac5f21a 100644 --- a/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs +++ b/src/librustc_mir/borrow_check/region_infer/reverse_sccs.rs @@ -56,7 +56,7 @@ impl RegionInferenceContext<'_> { let mut scc_regions = FxHashMap::default(); let mut start = 0; for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) { - let group_size = group.into_iter().count(); + let group_size = group.count(); scc_regions.insert(scc, start..start + group_size); start += group_size; } diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs index 04e2558a308..cb658397625 100644 --- a/src/librustc_mir/const_eval/mod.rs +++ b/src/librustc_mir/const_eval/mod.rs @@ -52,7 +52,7 @@ pub(crate) fn const_caller_location<'tcx>( let loc_place = ecx.alloc_caller_location(file, line, col); intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap(); - ConstValue::Scalar(loc_place.ptr.into()) + ConstValue::Scalar(loc_place.ptr) } // this function uses `unwrap` copiously, because an already validated constant diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 04f0f92d67f..cd06cf01bfa 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -67,7 +67,7 @@ crate fn eval_nullary_intrinsic<'tcx>( }; ConstValue::from_machine_usize(n, &tcx) } - sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty).into()), + sym::type_id => ConstValue::from_u64(tcx.type_id_hash(tp_ty)), other => bug!("`{}` is not a zero arg intrinsic", other), }) } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 37dcab512b9..a02a6898c1d 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -293,7 +293,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { let (&untuple_arg, args) = args.split_last().unwrap(); trace!("eval_fn_call: Will pass last argument by untupling"); Cow::from(args.iter().map(|&a| Ok(a)) - .chain((0..untuple_arg.layout.fields.count()).into_iter() + .chain((0..untuple_arg.layout.fields.count()) .map(|i| self.operand_field(untuple_arg, i as u64)) ) .collect::>>>()?) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 3c37eccc184..c9038ccf37b 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -209,7 +209,7 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> ConstQualifs { // We return the qualifs in the return place for every MIR body, even though it is only used // when deciding to promote a reference to a `const` for now. - validator.qualifs_in_return_place().into() + validator.qualifs_in_return_place() } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { diff --git a/src/librustc_mir/util/aggregate.rs b/src/librustc_mir/util/aggregate.rs index be515ef5713..927c8f6dfb2 100644 --- a/src/librustc_mir/util/aggregate.rs +++ b/src/librustc_mir/util/aggregate.rs @@ -49,7 +49,6 @@ pub fn expand_aggregate<'tcx>( }; operands - .into_iter() .enumerate() .map(move |(i, (op, ty))| { let lhs_field = if let AggregateKind::Array(_) = kind { diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index 79951255243..d9091f92b03 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -1942,8 +1942,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let tcx = self.hir.tcx(); let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope }; let binding_mode = match mode { - BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()), - BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability.into()), + BindingMode::ByValue => ty::BindingMode::BindByValue(mutability), + BindingMode::ByRef(_) => ty::BindingMode::BindByReference(mutability), }; debug!("declare_binding: user_ty={:?}", user_ty); let local = LocalDecl::<'tcx> { diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 8b7d0637c03..830877f713e 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -882,7 +882,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { span: tcx_hir.span(var_id), }, place: Place { - local: closure_env_arg.into(), + local: closure_env_arg, projection: tcx.intern_place_elems(&projs), }, }); @@ -927,7 +927,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.local_decls[local].local_info = if let Some(kind) = self_binding { LocalInfo::User(ClearCrossCrate::Set(BindingForm::ImplicitSelf(*kind))) } else { - let binding_mode = ty::BindingMode::BindByValue(mutability.into()); + let binding_mode = ty::BindingMode::BindByValue(mutability); LocalInfo::User(ClearCrossCrate::Set(BindingForm::Var( VarBindingForm { binding_mode, diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index e60f1138ddc..66280638a2d 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -327,8 +327,7 @@ impl<'a> StringReader<'a> { match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { - self.fatal_span_(start, suffix_start, "unterminated character literal".into()) - .raise() + self.fatal_span_(start, suffix_start, "unterminated character literal").raise() } let content_start = start + BytePos(1); let content_end = suffix_start - BytePos(1); @@ -338,12 +337,8 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { - self.fatal_span_( - start + BytePos(1), - suffix_start, - "unterminated byte constant".into(), - ) - .raise() + self.fatal_span_(start + BytePos(1), suffix_start, "unterminated byte constant") + .raise() } let content_start = start + BytePos(2); let content_end = suffix_start - BytePos(1); @@ -353,7 +348,7 @@ impl<'a> StringReader<'a> { } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { - self.fatal_span_(start, suffix_start, "unterminated double quote string".into()) + self.fatal_span_(start, suffix_start, "unterminated double quote string") .raise() } let content_start = start + BytePos(1); @@ -367,7 +362,7 @@ impl<'a> StringReader<'a> { self.fatal_span_( start + BytePos(1), suffix_start, - "unterminated double quote byte string".into(), + "unterminated double quote byte string", ) .raise() } diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index c28b59a7908..4f0276225fb 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -212,7 +212,7 @@ impl<'a> TokenTreesReader<'a> { _ => {} } - Ok(TokenTree::Delimited(delim_span, delim, tts.into()).into()) + Ok(TokenTree::Delimited(delim_span, delim, tts).into()) } token::CloseDelim(delim) => { // An unexpected closing delimiter (i.e., there is no diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index bd0b189d4fd..4cf9e4c3059 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -420,7 +420,7 @@ fn prepend_attrs( builder.push(tokenstream::TokenTree::Delimited( delim_span, token::DelimToken::Bracket, - brackets.build().into(), + brackets.build(), )); } builder.push(tokens.clone()); diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 75d4b3750f1..7b8642b0151 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -263,8 +263,7 @@ impl TokenCursor { ] .iter() .cloned() - .collect::() - .into(), + .collect::(), ); self.stack.push(mem::replace( @@ -389,7 +388,7 @@ impl<'a> Parser<'a> { root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { - frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, &tokens.into()), + frame: TokenCursorFrame::new(DelimSpan::dummy(), token::NoDelim, &tokens), stack: Vec::new(), }, desugar_doc_comments, @@ -1006,7 +1005,7 @@ impl<'a> Parser<'a> { ); self.set_token(Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close)); self.bump(); - TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream.into()) + TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream) } token::CloseDelim(_) | token::Eof => unreachable!(), _ => { diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index d2a6f0b7fcf..257292ae072 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -169,7 +169,7 @@ impl<'a> Parser<'a> { } fn parse_local_mk(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, Stmt> { - let local = self.parse_local(attrs.into())?; + let local = self.parse_local(attrs)?; Ok(self.mk_stmt(lo.to(self.prev_span), StmtKind::Local(local))) } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 69d6b38005c..2719057fb53 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -77,7 +77,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { return; } - let loop_id = match label.target_id.into() { + let loop_id = match label.target_id { Ok(loop_id) => loop_id, Err(hir::LoopIdError::OutsideLoopScope) => hir::DUMMY_HIR_ID, Err(hir::LoopIdError::UnlabeledCfInWhileCondition) => { diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs index e1a9ec56f8b..44a2c5464cd 100644 --- a/src/librustc_traits/generic_types.rs +++ b/src/librustc_traits/generic_types.rs @@ -24,7 +24,6 @@ crate fn fn_ptr( ) -> Ty<'tcx> { let inputs_and_output = tcx.mk_type_list( (0..arity_and_output) - .into_iter() .map(|i| ty::BoundVar::from(i)) // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig` .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into()))), @@ -37,7 +36,6 @@ crate fn fn_ptr( crate fn type_list(tcx: TyCtxt<'tcx>, arity: usize) -> SubstsRef<'tcx> { tcx.mk_substs( (0..arity) - .into_iter() .map(|i| ty::BoundVar::from(i)) .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into()))) .map(|ty| GenericArg::from(ty)), diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index 1645f01a4b1..fcbeb5b210d 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -312,6 +312,6 @@ pub fn check_explicit_predicates<'tcx>( let predicate = outlives_predicate.subst(tcx, substs); debug!("predicate = {:?}", &predicate); - insert_outlives_predicate(tcx, predicate.0.into(), predicate.1, span, required_predicates); + insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates); } } diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index e66d6fdc56a..83f052c898b 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -287,9 +287,7 @@ impl CStringArray { fn construct_envp(env: BTreeMap, saw_nul: &mut bool) -> CStringArray { let mut result = CStringArray::with_capacity(env.len()); - for (k, v) in env { - let mut k: OsString = k.into(); - + for (mut k, v) in env { // Reserve additional space for '=' and null terminator k.reserve_exact(v.len() + 2); k.push("="); diff --git a/src/libsyntax/attr/mod.rs b/src/libsyntax/attr/mod.rs index cd485e71378..bc5c86b02b3 100644 --- a/src/libsyntax/attr/mod.rs +++ b/src/libsyntax/attr/mod.rs @@ -529,7 +529,7 @@ impl MetaItemKind { TokenTree::Delimited( DelimSpan::from_single(span), token::Paren, - TokenStream::new(tokens).into(), + TokenStream::new(tokens), ) .into(), ] From 4f6661a18d2c35e6d4bfa8533ddaab10cd522b35 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 4 Feb 2020 22:19:05 +0100 Subject: [PATCH 0558/1250] Fix and test implementation of BTreeMap's first_entry, last_entry, pop_first, pop_last --- src/liballoc/collections/btree/map.rs | 24 ++++++++++++++---------- src/liballoc/tests/btree/map.rs | 5 +++++ src/liballoc/tests/btree/set.rs | 27 ++++++++++++++++----------- 3 files changed, 35 insertions(+), 21 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8eabc177304..c1778f2065d 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -675,13 +675,15 @@ impl BTreeMap { T: Ord, K: Borrow, { - match self.length { - 0 => None, - _ => Some(OccupiedEntry { - handle: self.root.as_mut().first_kv(), + let front = self.root.as_mut().first_leaf_edge(); + if let Ok(kv) = front.right_kv() { + Some(OccupiedEntry { + handle: kv.forget_node_type(), length: &mut self.length, _marker: PhantomData, - }), + }) + } else { + None } } @@ -736,13 +738,15 @@ impl BTreeMap { T: Ord, K: Borrow, { - match self.length { - 0 => None, - _ => Some(OccupiedEntry { - handle: self.root.as_mut().last_kv(), + let back = self.root.as_mut().last_leaf_edge(); + if let Ok(kv) = back.left_kv() { + Some(OccupiedEntry { + handle: kv.forget_node_type(), length: &mut self.length, _marker: PhantomData, - }), + }) + } else { + None } } diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index 0d009507fc7..0a26d7bf427 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -23,6 +23,11 @@ fn test_basic_large() { assert_eq!(map.len(), i + 1); } + assert_eq!(map.first_key_value(), Some((&0, &0))); + assert_eq!(map.last_key_value(), Some((&(size - 1), &(10 * (size - 1))))); + assert_eq!(map.first_entry().unwrap().key(), &0); + assert_eq!(map.last_entry().unwrap().key(), &(size - 1)); + for i in 0..size { assert_eq!(map.get(&i).unwrap(), &(i * 10)); } diff --git a/src/liballoc/tests/btree/set.rs b/src/liballoc/tests/btree/set.rs index 265ef758cc5..1a2b62d026b 100644 --- a/src/liballoc/tests/btree/set.rs +++ b/src/liballoc/tests/btree/set.rs @@ -487,21 +487,26 @@ fn test_first_last() { a.insert(2); assert_eq!(a.first(), Some(&1)); assert_eq!(a.last(), Some(&2)); - a.insert(3); + for i in 3..=12 { + a.insert(i); + } assert_eq!(a.first(), Some(&1)); - assert_eq!(a.last(), Some(&3)); - - assert_eq!(a.len(), 3); + assert_eq!(a.last(), Some(&12)); assert_eq!(a.pop_first(), Some(1)); - assert_eq!(a.len(), 2); - assert_eq!(a.pop_last(), Some(3)); - assert_eq!(a.len(), 1); + assert_eq!(a.pop_last(), Some(12)); assert_eq!(a.pop_first(), Some(2)); - assert_eq!(a.len(), 0); - assert_eq!(a.pop_last(), None); - assert_eq!(a.len(), 0); + assert_eq!(a.pop_last(), Some(11)); + assert_eq!(a.pop_first(), Some(3)); + assert_eq!(a.pop_last(), Some(10)); + assert_eq!(a.pop_first(), Some(4)); + assert_eq!(a.pop_first(), Some(5)); + assert_eq!(a.pop_first(), Some(6)); + assert_eq!(a.pop_first(), Some(7)); + assert_eq!(a.pop_first(), Some(8)); + assert_eq!(a.clone().pop_last(), Some(9)); + assert_eq!(a.pop_first(), Some(9)); assert_eq!(a.pop_first(), None); - assert_eq!(a.len(), 0); + assert_eq!(a.pop_last(), None); } fn rand_data(len: usize) -> Vec { From e6c85960d164c5f1e30ae9d18002c3e9d435fc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 27 Feb 2020 15:59:08 -0800 Subject: [PATCH 0559/1250] Revert "Backport only: avoid ICE on bad placeholder type" This reverts commit 1cb555a1dc809a8d310354678ef9c43f01e41ad4. --- src/librustc_typeck/collect.rs | 2 +- src/test/ui/did_you_mean/bad-assoc-ty.rs | 1 - src/test/ui/did_you_mean/bad-assoc-ty.stderr | 26 +- src/test/ui/self/self-infer.rs | 2 - src/test/ui/self/self-infer.stderr | 16 +- .../ui/typeck/typeck_type_placeholder_item.rs | 34 -- .../typeck_type_placeholder_item.stderr | 316 +++--------------- 7 files changed, 68 insertions(+), 329 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1fade1b5ca6..6c4e9ecee1c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -320,7 +320,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - placeholder_type_error(self.tcx(), span, &[], vec![span], false); + self.tcx().sess.delay_span_bug(span, "bad placeholder type"); self.tcx().types.err } diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index f02931eeb6f..fccfb7911ce 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -17,7 +17,6 @@ type D = (u8, u8)::AssocTy; type E = _::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures type F = &'static (u8)::AssocTy; //~^ ERROR missing angle brackets in associated item path diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index d5b2abf2f8b..64e49934d87 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -29,25 +29,25 @@ LL | type E = _::AssocTy; | ^^^^^^^^^^ help: try: `<_>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:22:19 + --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:28:10 + --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:45:10 + --> $DIR/bad-assoc-ty.rs:44:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:38:19 + --> $DIR/bad-assoc-ty.rs:37:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` @@ -87,32 +87,26 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | type E = _::AssocTy; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/bad-assoc-ty.rs:17:10 - | -LL | type E = _::AssocTy; - | ^ not allowed in type signatures - error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:22:19 + --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:28:10 + --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:34:10 + --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:38:19 + --> $DIR/bad-assoc-ty.rs:37:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` @@ -123,12 +117,12 @@ LL | type J = ty!(u8); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:45:10 + --> $DIR/bad-assoc-ty.rs:44:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 20 previous errors +error: aborting due to 19 previous errors Some errors have detailed explanations: E0121, E0223. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs index 77c80521236..0956f2a5691 100644 --- a/src/test/ui/self/self-infer.rs +++ b/src/test/ui/self/self-infer.rs @@ -2,9 +2,7 @@ struct S; impl S { fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig - //~^ ERROR the type placeholder `_` is not allowed within types on item sig fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig - //~^ ERROR the type placeholder `_` is not allowed within types on item sig } fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index d6bf8b44d60..1475b212b56 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -1,9 +1,3 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:4:16 - | -LL | fn f(self: _) {} - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/self-infer.rs:4:16 | @@ -16,13 +10,7 @@ LL | fn f(self: T) {} | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:6:17 - | -LL | fn g(self: &_) {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:6:17 + --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} | ^ not allowed in type signatures @@ -32,6 +20,6 @@ help: use type parameters instead LL | fn g(self: &T) {} | ^^^ ^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index eb6cc832fb4..86c7c52b271 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -19,24 +19,19 @@ static TEST5: (_, _) = (1, 2); fn test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_b(_: _, _: T) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_c(_: _, _: (T, K, L, A, B)) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Test9; @@ -46,7 +41,6 @@ impl Test9 { fn test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn test11(x: &usize) -> &_ { @@ -65,16 +59,12 @@ impl Clone for Test9 { fn clone_from(&mut self, other: _) { *self = Test9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct Test10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } pub fn main() { @@ -102,16 +92,13 @@ pub fn main() { fn fn_test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures struct FnTest9; @@ -121,7 +108,6 @@ pub fn main() { fn fn_test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } impl Clone for FnTest9 { @@ -130,16 +116,12 @@ pub fn main() { fn clone_from(&mut self, other: _) { *self = FnTest9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct FnTest10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn fn_test11(_: _) -> (_, _) { panic!() } @@ -156,40 +138,28 @@ pub fn main() { trait T { fn method_test1(&self, x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test2(&self, x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test3(&self) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test1(x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test2(x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test3() -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct BadStruct<_>(_); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -198,22 +168,18 @@ struct BadStruct1<_, _>(_); //~| ERROR expected identifier, found reserved identifier `_` //~| ERROR the name `_` is already used //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct BadStruct2<_, T>(_, T); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index a8fdd66ee37..95e8f94c6f3 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:179:18 + --> $DIR/typeck_type_placeholder_item.rs:153:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:183:16 + --> $DIR/typeck_type_placeholder_item.rs:156:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:196:19 + --> $DIR/typeck_type_placeholder_item.rs:166:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:196:22 + --> $DIR/typeck_type_placeholder_item.rs:166:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:202:19 + --> $DIR/typeck_type_placeholder_item.rs:171:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:196:22 + --> $DIR/typeck_type_placeholder_item.rs:166:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -79,12 +79,6 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:20:13 - | -LL | fn test6(_: _) { } - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:20:13 | @@ -97,13 +91,7 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:24:18 - | -LL | fn test6_b(_: _, _: T) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:24:18 + --> $DIR/typeck_type_placeholder_item.rs:23:18 | LL | fn test6_b(_: _, _: T) { } | ^ not allowed in type signatures @@ -114,13 +102,7 @@ LL | fn test6_b(_: K, _: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:28:30 - | -LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:28:30 + --> $DIR/typeck_type_placeholder_item.rs:26:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } | ^ not allowed in type signatures @@ -131,13 +113,7 @@ LL | fn test6_c(_: C, _: (T, K, L, A, B)) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:13 - | -LL | fn test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:13 + --> $DIR/typeck_type_placeholder_item.rs:29:13 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -148,19 +124,13 @@ LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 + --> $DIR/typeck_type_placeholder_item.rs:32:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 - | -LL | fn test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 + --> $DIR/typeck_type_placeholder_item.rs:32:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -171,61 +141,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:72:8 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:9 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:12 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:137:12 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:140:13 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:140:16 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:21 - | -LL | struct BadStruct<_>(_); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:25 - | -LL | struct BadStruct1<_, _>(_); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:202:25 - | -LL | struct BadStruct2<_, T>(_, T); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:52:26 + --> $DIR/typeck_type_placeholder_item.rs:46:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -234,7 +150,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:52 + --> $DIR/typeck_type_placeholder_item.rs:51:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -243,11 +159,11 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:72:8 + --> $DIR/typeck_type_placeholder_item.rs:65:8 | LL | a: _, | ^ not allowed in type signatures -... +LL | LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -258,18 +174,17 @@ help: use type parameters instead LL | struct Test10 { LL | a: T, LL | -LL | LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:81:12 + --> $DIR/typeck_type_placeholder_item.rs:71:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:83:15 + --> $DIR/typeck_type_placeholder_item.rs:73:15 | LL | static B: _ = 42; | ^ @@ -278,13 +193,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:85:15 + --> $DIR/typeck_type_placeholder_item.rs:75:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:88:21 + --> $DIR/typeck_type_placeholder_item.rs:78:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -293,7 +208,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:91:23 + --> $DIR/typeck_type_placeholder_item.rs:81:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -303,7 +218,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:94:22 + --> $DIR/typeck_type_placeholder_item.rs:84:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -312,7 +227,7 @@ LL | static FN_TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:97:22 + --> $DIR/typeck_type_placeholder_item.rs:87:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -321,19 +236,13 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:100:22 + --> $DIR/typeck_type_placeholder_item.rs:90:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:103:20 - | -LL | fn fn_test6(_: _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:103:20 + --> $DIR/typeck_type_placeholder_item.rs:93:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -344,13 +253,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:107:20 - | -LL | fn fn_test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:107:20 + --> $DIR/typeck_type_placeholder_item.rs:96:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -361,19 +264,13 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 - | -LL | fn fn_test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 + --> $DIR/typeck_type_placeholder_item.rs:99:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 + --> $DIR/typeck_type_placeholder_item.rs:99:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -384,11 +281,11 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:137:12 + --> $DIR/typeck_type_placeholder_item.rs:122:12 | LL | a: _, | ^ not allowed in type signatures -... +LL | LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -399,18 +296,17 @@ help: use type parameters instead LL | struct FnTest10 { LL | a: T, LL | -LL | LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:145:18 + --> $DIR/typeck_type_placeholder_item.rs:127:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:145:28 + --> $DIR/typeck_type_placeholder_item.rs:127:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -418,7 +314,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:149:30 + --> $DIR/typeck_type_placeholder_item.rs:131:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -428,7 +324,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:152:33 + --> $DIR/typeck_type_placeholder_item.rs:134:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -437,7 +333,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:21 + --> $DIR/typeck_type_placeholder_item.rs:153:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -448,19 +344,7 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:32 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:15 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:15 + --> $DIR/typeck_type_placeholder_item.rs:158:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -473,13 +357,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:190:34 + --> $DIR/typeck_type_placeholder_item.rs:161:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:25 + --> $DIR/typeck_type_placeholder_item.rs:166:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -490,7 +374,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:202:25 + --> $DIR/typeck_type_placeholder_item.rs:171:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -501,25 +385,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 + --> $DIR/typeck_type_placeholder_item.rs:175:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 - | -LL | type X = Box<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:27 - | -LL | fn test10(&self, _x : _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:27 + --> $DIR/typeck_type_placeholder_item.rs:42:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -530,13 +402,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:157:31 - | -LL | fn method_test1(&self, x: _); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:157:31 + --> $DIR/typeck_type_placeholder_item.rs:139:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -547,19 +413,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:37 - | -LL | fn method_test2(&self, x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:31 - | -LL | fn method_test2(&self, x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:31 + --> $DIR/typeck_type_placeholder_item.rs:141:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -572,13 +426,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:31 - | -LL | fn method_test3(&self) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:31 + --> $DIR/typeck_type_placeholder_item.rs:143:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -589,13 +437,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:167:26 - | -LL | fn assoc_fn_test1(x: _); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:167:26 + --> $DIR/typeck_type_placeholder_item.rs:145:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -606,19 +448,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:32 - | -LL | fn assoc_fn_test2(x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:26 - | -LL | fn assoc_fn_test2(x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:26 + --> $DIR/typeck_type_placeholder_item.rs:147:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -631,13 +461,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:28 - | -LL | fn assoc_fn_test3() -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:28 + --> $DIR/typeck_type_placeholder_item.rs:149:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -648,13 +472,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:66:37 - | -LL | fn clone_from(&mut self, other: _) { *self = Test9; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:66:37 + --> $DIR/typeck_type_placeholder_item.rs:60:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -665,13 +483,7 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:34 - | -LL | fn fn_test10(&self, _x : _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:34 + --> $DIR/typeck_type_placeholder_item.rs:109:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -682,13 +494,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:41 - | -LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:41 + --> $DIR/typeck_type_placeholder_item.rs:117:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -699,25 +505,13 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:190:34 - | -LL | fn impl_trait() -> impl BadTrait<_> { - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:214:21 - | -LL | type Y = impl Trait<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:214:21 + --> $DIR/typeck_type_placeholder_item.rs:181:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:44:24 + --> $DIR/typeck_type_placeholder_item.rs:39:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -726,7 +520,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:63:24 + --> $DIR/typeck_type_placeholder_item.rs:57:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -735,7 +529,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:31 + --> $DIR/typeck_type_placeholder_item.rs:106:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -744,7 +538,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:128:28 + --> $DIR/typeck_type_placeholder_item.rs:114:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -752,7 +546,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 92 previous errors +error: aborting due to 58 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From a7b727dab3aff466fc88c3ce0916817dc2d093bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Feb 2020 13:34:00 -0800 Subject: [PATCH 0560/1250] Account for bounds when denying `_` in type parameters --- src/librustc_typeck/astconv.rs | 22 +++++++- src/test/ui/did_you_mean/bad-assoc-ty.rs | 4 ++ src/test/ui/did_you_mean/bad-assoc-ty.stderr | 10 +++- .../ui/typeck/typeck_type_placeholder_item.rs | 5 ++ .../typeck_type_placeholder_item.stderr | 50 +++++++++++++++---- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 49f38d86d91..d1a6163df2d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -514,7 +514,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Option>, arg_count_correct: bool, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), - provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, + mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( Option<&[subst::GenericArg<'tcx>]>, &GenericParamDef, @@ -751,6 +751,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let mut missing_type_params = vec![]; + let mut inferred_params = vec![]; let substs = Self::create_substs_for_generic_args( tcx, def_id, @@ -773,7 +774,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(<, Some(param)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.ast_ty_to_ty(&ty).into() + if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) { + inferred_params.push(ty.span); + tcx.types.err.into() + } else { + self.ast_ty_to_ty(&ty).into() + } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into() @@ -832,6 +838,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }, ); + if !inferred_params.is_empty() { + // We always collect the spans for placeholder types when evaluating `fn`s, but we + // only want to emit an error complaining about them if infer types (`_`) are not + // allowed. `allow_ty_infer` gates this behavior. + crate::collect::placeholder_type_error( + tcx, + inferred_params[0], + &[], + inferred_params, + false, + ); + } self.complain_about_missing_type_params( missing_type_params, diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index fccfb7911ce..00845a17b11 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -45,4 +45,8 @@ type I = ty!()::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR ambiguous associated type +trait K {} +fn foo>(x: X) {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 64e49934d87..6d5f3d9f143 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -122,7 +122,15 @@ error[E0223]: ambiguous associated type LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 19 previous errors +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:49:13 + | +LL | fn foo>(x: X) {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 20 previous errors Some errors have detailed explanations: E0121, E0223. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 86c7c52b271..8ee46343d2d 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -157,9 +157,12 @@ trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -174,12 +177,14 @@ struct BadStruct2<_, T>(_, T); type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 95e8f94c6f3..18317d2b974 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -11,25 +11,25 @@ LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:19 + --> $DIR/typeck_type_placeholder_item.rs:169:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:174:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -343,6 +343,18 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:158:32 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:158:15 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:158:15 | @@ -357,13 +369,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:161:34 + --> $DIR/typeck_type_placeholder_item.rs:163:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:166:25 + --> $DIR/typeck_type_placeholder_item.rs:169:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -374,7 +386,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 + --> $DIR/typeck_type_placeholder_item.rs:174:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -385,7 +397,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:14 + --> $DIR/typeck_type_placeholder_item.rs:178:14 + | +LL | type X = Box<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:178:14 | LL | type X = Box<_>; | ^ not allowed in type signatures @@ -505,7 +523,19 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:181:21 + --> $DIR/typeck_type_placeholder_item.rs:163:34 + | +LL | fn impl_trait() -> impl BadTrait<_> { + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:21 + | +LL | type Y = impl Trait<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures @@ -546,7 +576,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 58 previous errors +error: aborting due to 63 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From c6cfcf999a53e5656f412c64f5e97e7a4840e072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 12:07:50 -0800 Subject: [PATCH 0561/1250] Account for associated items when denying `_` --- src/librustc_typeck/collect.rs | 34 +++- .../ui/typeck/typeck_type_placeholder_item.rs | 25 ++- .../typeck_type_placeholder_item.stderr | 184 ++++++++++++------ 3 files changed, 170 insertions(+), 73 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6c4e9ecee1c..f257fc5442c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -715,13 +715,21 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { tcx.generics_of(def_id); match trait_item.kind { - hir::TraitItemKind::Const(..) - | hir::TraitItemKind::Type(_, Some(_)) - | hir::TraitItemKind::Method(..) => { + hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); - if let hir::TraitItemKind::Method(..) = trait_item.kind { - tcx.fn_sig(def_id); - } + tcx.fn_sig(def_id); + } + + hir::TraitItemKind::Const(.., Some(_)) => { + tcx.type_of(def_id); + } + + hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => { + tcx.type_of(def_id); + // Account for `const C: _;` and `type T = _;`. + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_trait_item(trait_item); + placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false); } hir::TraitItemKind::Type(_, None) => {} @@ -735,8 +743,18 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); - if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).kind { - tcx.fn_sig(def_id); + let impl_item = tcx.hir().expect_impl_item(impl_item_id); + match impl_item.kind { + hir::ImplItemKind::Method(..) => { + tcx.fn_sig(def_id); + } + hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => { + // Account for `type T = _;` + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_impl_item(impl_item); + placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false); + } + hir::ImplItemKind::Const(..) => {} } } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 8ee46343d2d..6cd2b8c75b6 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -1,4 +1,5 @@ -#![feature(type_alias_impl_trait)] // Needed for single test `type Y = impl Trait<_>` +// Needed for `type Y = impl Trait<_>` and `type B = _;` +#![feature(type_alias_impl_trait, associated_type_defaults)] // This test checks that it is not possible to enable global type // inference by using the `_` type placeholder. @@ -188,3 +189,25 @@ type Y = impl Trait<_>; fn foo() -> Y { Struct } + +trait Qux { + type A; + type B = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const C: _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const D: _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + // type E: _; // FIXME: make the parser propagate the existence of `B` +} +impl Qux for Struct { + type A = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + type B = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const C: _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR associated constant in `impl` without body + const D: _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 18317d2b974..f2d02f70f4a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,43 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:153:18 + --> $DIR/typeck_type_placeholder_item.rs:154:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:156:16 + --> $DIR/typeck_type_placeholder_item.rs:157:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:169:19 + --> $DIR/typeck_type_placeholder_item.rs:170:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:169:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:174:19 + --> $DIR/typeck_type_placeholder_item.rs:175:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier +error: associated constant in `impl` without body + --> $DIR/typeck_type_placeholder_item.rs:208:5 + | +LL | const C: _; + | ^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:169:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -37,7 +45,7 @@ LL | struct BadStruct1<_, _>(_); | first use of `_` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:5:14 + --> $DIR/typeck_type_placeholder_item.rs:6:14 | LL | fn test() -> _ { 5 } | ^ @@ -46,7 +54,7 @@ LL | fn test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:8:16 + --> $DIR/typeck_type_placeholder_item.rs:9:16 | LL | fn test2() -> (_, _) { (5, 5) } | -^--^- @@ -56,7 +64,7 @@ LL | fn test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:11:15 + --> $DIR/typeck_type_placeholder_item.rs:12:15 | LL | static TEST3: _ = "test"; | ^ @@ -65,7 +73,7 @@ LL | static TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:14:15 + --> $DIR/typeck_type_placeholder_item.rs:15:15 | LL | static TEST4: _ = 145; | ^ @@ -74,13 +82,13 @@ LL | static TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:17:15 + --> $DIR/typeck_type_placeholder_item.rs:18:15 | LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:20:13 + --> $DIR/typeck_type_placeholder_item.rs:21:13 | LL | fn test6(_: _) { } | ^ not allowed in type signatures @@ -91,7 +99,7 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:23:18 + --> $DIR/typeck_type_placeholder_item.rs:24:18 | LL | fn test6_b(_: _, _: T) { } | ^ not allowed in type signatures @@ -102,7 +110,7 @@ LL | fn test6_b(_: K, _: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:26:30 + --> $DIR/typeck_type_placeholder_item.rs:27:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } | ^ not allowed in type signatures @@ -113,7 +121,7 @@ LL | fn test6_c(_: C, _: (T, K, L, A, B)) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:29:13 + --> $DIR/typeck_type_placeholder_item.rs:30:13 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -124,13 +132,13 @@ LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:33:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:33:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -141,7 +149,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:46:26 + --> $DIR/typeck_type_placeholder_item.rs:47:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -150,7 +158,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:51:52 + --> $DIR/typeck_type_placeholder_item.rs:52:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -159,7 +167,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:65:8 + --> $DIR/typeck_type_placeholder_item.rs:66:8 | LL | a: _, | ^ not allowed in type signatures @@ -178,13 +186,13 @@ LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:71:12 + --> $DIR/typeck_type_placeholder_item.rs:72:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:73:15 + --> $DIR/typeck_type_placeholder_item.rs:74:15 | LL | static B: _ = 42; | ^ @@ -193,13 +201,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:15 + --> $DIR/typeck_type_placeholder_item.rs:76:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:78:21 + --> $DIR/typeck_type_placeholder_item.rs:79:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -208,7 +216,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:81:23 + --> $DIR/typeck_type_placeholder_item.rs:82:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -218,7 +226,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:84:22 + --> $DIR/typeck_type_placeholder_item.rs:85:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -227,7 +235,7 @@ LL | static FN_TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:87:22 + --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -236,13 +244,13 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:90:22 + --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:93:20 + --> $DIR/typeck_type_placeholder_item.rs:94:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -253,7 +261,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:96:20 + --> $DIR/typeck_type_placeholder_item.rs:97:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -264,13 +272,13 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -281,7 +289,7 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:12 + --> $DIR/typeck_type_placeholder_item.rs:123:12 | LL | a: _, | ^ not allowed in type signatures @@ -300,13 +308,13 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:127:18 + --> $DIR/typeck_type_placeholder_item.rs:128:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:127:28 + --> $DIR/typeck_type_placeholder_item.rs:128:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -314,7 +322,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:30 + --> $DIR/typeck_type_placeholder_item.rs:132:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -324,7 +332,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:134:33 + --> $DIR/typeck_type_placeholder_item.rs:135:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -333,7 +341,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:153:21 + --> $DIR/typeck_type_placeholder_item.rs:154:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -344,19 +352,19 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:32 + --> $DIR/typeck_type_placeholder_item.rs:159:32 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:15 + --> $DIR/typeck_type_placeholder_item.rs:159:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:15 + --> $DIR/typeck_type_placeholder_item.rs:159:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -369,13 +377,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:34 + --> $DIR/typeck_type_placeholder_item.rs:164:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:169:25 + --> $DIR/typeck_type_placeholder_item.rs:170:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -386,7 +394,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:25 + --> $DIR/typeck_type_placeholder_item.rs:175:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -397,19 +405,19 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:178:14 + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:178:14 + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:42:27 + --> $DIR/typeck_type_placeholder_item.rs:43:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -420,7 +428,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:139:31 + --> $DIR/typeck_type_placeholder_item.rs:140:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -431,7 +439,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:141:31 + --> $DIR/typeck_type_placeholder_item.rs:142:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -444,7 +452,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:143:31 + --> $DIR/typeck_type_placeholder_item.rs:144:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -455,7 +463,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:145:26 + --> $DIR/typeck_type_placeholder_item.rs:146:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -466,7 +474,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:147:26 + --> $DIR/typeck_type_placeholder_item.rs:148:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -479,7 +487,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:149:28 + --> $DIR/typeck_type_placeholder_item.rs:150:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -490,7 +498,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:60:37 + --> $DIR/typeck_type_placeholder_item.rs:61:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -501,7 +509,7 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:109:34 + --> $DIR/typeck_type_placeholder_item.rs:110:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -512,7 +520,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:117:41 + --> $DIR/typeck_type_placeholder_item.rs:118:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -523,25 +531,46 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:34 + --> $DIR/typeck_type_placeholder_item.rs:164:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:21 + --> $DIR/typeck_type_placeholder_item.rs:186:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:21 + --> $DIR/typeck_type_placeholder_item.rs:186:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:39:24 + --> $DIR/typeck_type_placeholder_item.rs:195:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:197:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:199:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace `_` with the correct type: `i32` + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:40:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -550,7 +579,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:24 + --> $DIR/typeck_type_placeholder_item.rs:58:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -559,7 +588,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:106:31 + --> $DIR/typeck_type_placeholder_item.rs:107:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -568,7 +597,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:114:28 + --> $DIR/typeck_type_placeholder_item.rs:115:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -576,7 +605,34 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 63 previous errors +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:204:14 + | +LL | type A = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:206:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:208:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:211:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace `_` with the correct type: `i32` + +error: aborting due to 71 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From 9f7b58f3c94708f344237f826b4f96a659b5fc82 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 4 Feb 2020 15:00:51 +0100 Subject: [PATCH 0562/1250] Make implementation of navigation simpler, safer and faster --- src/liballoc/collections/btree/map.rs | 11 +- src/liballoc/collections/btree/navigate.rs | 245 ++++++++++----------- src/liballoc/collections/btree/node.rs | 42 ++-- 3 files changed, 148 insertions(+), 150 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index c1778f2065d..e62855f2fb3 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1473,16 +1473,13 @@ impl Drop for IntoIter { fn drop(&mut self) { self.for_each(drop); unsafe { - let leaf_node = ptr::read(&self.front).into_node(); - if leaf_node.is_shared_root() { + let mut node = ptr::read(&self.front).into_node().forget_type(); + if node.is_shared_root() { return; } - if let Some(first_parent) = leaf_node.deallocate_and_ascend() { - let mut cur_internal_node = first_parent.into_node(); - while let Some(parent) = cur_internal_node.deallocate_and_ascend() { - cur_internal_node = parent.into_node() - } + while let Some(parent) = node.deallocate_and_ascend() { + node = parent.into_node().forget_type(); } } } diff --git a/src/liballoc/collections/btree/navigate.rs b/src/liballoc/collections/btree/navigate.rs index 65321897231..5e8dcf247ae 100644 --- a/src/liballoc/collections/btree/navigate.rs +++ b/src/liballoc/collections/btree/navigate.rs @@ -3,120 +3,69 @@ use core::ptr; use super::node::{marker, ForceResult::*, Handle, NodeRef}; use super::unwrap_unchecked; -macro_rules! def_next { - { unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => { - /// Given a leaf edge handle into an immutable tree, returns a handle to the next - /// leaf edge and references to the key and value between these edges. - /// Unsafe because the caller must ensure that the given leaf edge has a successor. - unsafe fn $name <'a, K: 'a, V: 'a>( - leaf_edge: Handle, K, V, marker::Leaf>, marker::Edge>, - ) -> (Handle, K, V, marker::Leaf>, marker::Edge>, &'a K, &'a V) { - let mut cur_handle = match leaf_edge.$next_kv() { - Ok(leaf_kv) => { - let (k, v) = leaf_kv.into_kv(); - let next_leaf_edge = leaf_kv.$next_edge(); - return (next_leaf_edge, k, v); - } - Err(last_edge) => { - let next_level = last_edge.into_node().ascend().ok(); - unwrap_unchecked(next_level) - } - }; - - loop { - cur_handle = match cur_handle.$next_kv() { - Ok(internal_kv) => { - let (k, v) = internal_kv.into_kv(); - let next_internal_edge = internal_kv.$next_edge(); - let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge(); - return (next_leaf_edge, k, v); - } - Err(last_edge) => { - let next_level = last_edge.into_node().ascend().ok(); - unwrap_unchecked(next_level) - } - } +impl Handle, marker::Edge> { + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the right side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the last one in the tree, returns [`Result::Err`] with the root node. + pub fn next_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.right_kv() { + Ok(internal_kv) => return Ok(internal_kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root.forget_type()), + }, } } - }; -} - -macro_rules! def_next_mut { - { unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => { - /// Given a leaf edge handle into a mutable tree, returns handles to the next - /// leaf edge and to the KV between these edges. - /// Unsafe for two reasons: - /// - the caller must ensure that the given leaf edge has a successor; - /// - both returned handles represent mutable references into the same tree - /// that can easily invalidate each other, even on immutable use. - unsafe fn $name <'a, K: 'a, V: 'a>( - leaf_edge: Handle, K, V, marker::Leaf>, marker::Edge>, - ) -> (Handle, K, V, marker::Leaf>, marker::Edge>, - Handle, K, V, marker::LeafOrInternal>, marker::KV>) { - let mut cur_handle = match leaf_edge.$next_kv() { - Ok(leaf_kv) => { - let next_leaf_edge = ptr::read(&leaf_kv).$next_edge(); - return (next_leaf_edge, leaf_kv.forget_node_type()); - } - Err(last_edge) => { - let next_level = last_edge.into_node().ascend().ok(); - unwrap_unchecked(next_level) - } - }; + } - loop { - cur_handle = match cur_handle.$next_kv() { - Ok(internal_kv) => { - let next_internal_edge = ptr::read(&internal_kv).$next_edge(); - let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge(); - return (next_leaf_edge, internal_kv.forget_node_type()); - } - Err(last_edge) => { - let next_level = last_edge.into_node().ascend().ok(); - unwrap_unchecked(next_level) - } - } + /// Given a leaf edge handle, returns [`Result::Ok`] with a handle to the neighboring KV + /// on the left side, which is either in the same leaf node or in an ancestor node. + /// If the leaf edge is the first one in the tree, returns [`Result::Err`] with the root node. + pub fn next_back_kv( + self, + ) -> Result< + Handle, marker::KV>, + NodeRef, + > { + let mut edge = self.forget_node_type(); + loop { + edge = match edge.left_kv() { + Ok(internal_kv) => return Ok(internal_kv), + Err(last_edge) => match last_edge.into_node().ascend() { + Ok(parent_edge) => parent_edge.forget_node_type(), + Err(root) => return Err(root.forget_type()), + }, } } - }; + } } -macro_rules! def_next_dealloc { - { unsafe fn $name:ident : $next_kv:ident $next_edge:ident $initial_leaf_edge:ident } => { - /// Given a leaf edge handle into an owned tree, returns a handle to the next - /// leaf edge and the key and value between these edges, while deallocating - /// any node left behind. +macro_rules! def_next_kv_uncheched_dealloc { + { unsafe fn $name:ident : $adjacent_kv:ident } => { + /// Given a leaf edge handle into an owned tree, returns a handle to the next KV, + /// while deallocating any node left behind. /// Unsafe for two reasons: - /// - the caller must ensure that the given leaf edge has a successor; - /// - the node pointed at by the given handle, and its ancestors, may be deallocated, + /// - The caller must ensure that the leaf edge is not the last one in the tree. + /// - The node pointed at by the given handle, and its ancestors, may be deallocated, /// while the reference to those nodes in the surviving ancestors is left dangling; - /// thus using the returned handle is dangerous. + /// thus using the returned handle to navigate further is dangerous. unsafe fn $name ( leaf_edge: Handle, marker::Edge>, - ) -> (Handle, marker::Edge>, K, V) { - let mut cur_handle = match leaf_edge.$next_kv() { - Ok(leaf_kv) => { - let k = ptr::read(leaf_kv.reborrow().into_kv().0); - let v = ptr::read(leaf_kv.reborrow().into_kv().1); - let next_leaf_edge = leaf_kv.$next_edge(); - return (next_leaf_edge, k, v); - } - Err(last_edge) => { - unwrap_unchecked(last_edge.into_node().deallocate_and_ascend()) - } - }; - + ) -> Handle, marker::KV> { + let mut edge = leaf_edge.forget_node_type(); loop { - cur_handle = match cur_handle.$next_kv() { - Ok(internal_kv) => { - let k = ptr::read(internal_kv.reborrow().into_kv().0); - let v = ptr::read(internal_kv.reborrow().into_kv().1); - let next_internal_edge = internal_kv.$next_edge(); - let next_leaf_edge = next_internal_edge.descend().$initial_leaf_edge(); - return (next_leaf_edge, k, v); - } + edge = match edge.$adjacent_kv() { + Ok(internal_kv) => return internal_kv, Err(last_edge) => { - unwrap_unchecked(last_edge.into_node().deallocate_and_ascend()) + let parent_edge = last_edge.into_node().deallocate_and_ascend(); + unwrap_unchecked(parent_edge).forget_node_type() } } } @@ -124,30 +73,42 @@ macro_rules! def_next_dealloc { }; } -def_next! {unsafe fn next_unchecked: right_kv right_edge first_leaf_edge} -def_next! {unsafe fn next_back_unchecked: left_kv left_edge last_leaf_edge} -def_next_mut! {unsafe fn next_unchecked_mut: right_kv right_edge first_leaf_edge} -def_next_mut! {unsafe fn next_back_unchecked_mut: left_kv left_edge last_leaf_edge} -def_next_dealloc! {unsafe fn next_unchecked_deallocating: right_kv right_edge first_leaf_edge} -def_next_dealloc! {unsafe fn next_back_unchecked_deallocating: left_kv left_edge last_leaf_edge} +def_next_kv_uncheched_dealloc! {unsafe fn next_kv_unchecked_dealloc: right_kv} +def_next_kv_uncheched_dealloc! {unsafe fn next_back_kv_unchecked_dealloc: left_kv} + +/// This replaces the value behind the `v` unique reference by calling the +/// relevant function. +/// +/// Safety: The change closure must not panic. +#[inline] +unsafe fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { + let value = ptr::read(v); + let (new_value, ret) = change(value); + ptr::write(v, new_value); + ret +} impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge> { /// Moves the leaf edge handle to the next leaf edge and returns references to the /// key and value in between. /// Unsafe because the caller must ensure that the leaf edge is not the last one in the tree. pub unsafe fn next_unchecked(&mut self) -> (&'a K, &'a V) { - let (next_edge, k, v) = next_unchecked(*self); - *self = next_edge; - (k, v) + replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unwrap_unchecked(kv.ok()); + (kv.next_leaf_edge(), kv.into_kv()) + }) } /// Moves the leaf edge handle to the previous leaf edge and returns references to the /// key and value in between. /// Unsafe because the caller must ensure that the leaf edge is not the first one in the tree. pub unsafe fn next_back_unchecked(&mut self) -> (&'a K, &'a V) { - let (next_edge, k, v) = next_back_unchecked(*self); - *self = next_edge; - (k, v) + replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unwrap_unchecked(kv.ok()); + (kv.next_back_leaf_edge(), kv.into_kv()) + }) } } @@ -158,8 +119,11 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge /// - The caller must ensure that the leaf edge is not the last one in the tree. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - let (next_edge, kv) = next_unchecked_mut(ptr::read(self)); - *self = next_edge; + let kv = replace(self, |leaf_edge| { + let kv = leaf_edge.next_kv(); + let kv = unwrap_unchecked(kv.ok()); + (ptr::read(&kv).next_leaf_edge(), kv) + }); // Doing the descend (and perhaps another move) invalidates the references // returned by `into_kv_mut`, so we have to do this last. kv.into_kv_mut() @@ -171,8 +135,11 @@ impl<'a, K, V> Handle, K, V, marker::Leaf>, marker::Edge /// - The caller must ensure that the leaf edge is not the first one in the tree. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_back_unchecked(&mut self) -> (&'a mut K, &'a mut V) { - let (next_edge, kv) = next_back_unchecked_mut(ptr::read(self)); - *self = next_edge; + let kv = replace(self, |leaf_edge| { + let kv = leaf_edge.next_back_kv(); + let kv = unwrap_unchecked(kv.ok()); + (ptr::read(&kv).next_back_leaf_edge(), kv) + }); // Doing the descend (and perhaps another move) invalidates the references // returned by `into_kv_mut`, so we have to do this last. kv.into_kv_mut() @@ -192,9 +159,12 @@ impl Handle, marker::Edge> { /// if the two preconditions above hold. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_unchecked(&mut self) -> (K, V) { - let (next_edge, k, v) = next_unchecked_deallocating(ptr::read(self)); - *self = next_edge; - (k, v) + replace(self, |leaf_edge| { + let kv = next_kv_unchecked_dealloc(leaf_edge); + let k = ptr::read(kv.reborrow().into_kv().0); + let v = ptr::read(kv.reborrow().into_kv().1); + (kv.next_leaf_edge(), (k, v)) + }) } /// Moves the leaf edge handle to the previous leaf edge and returns the key @@ -209,9 +179,12 @@ impl Handle, marker::Edge> { /// if the two preconditions above hold. /// - Using the updated handle may well invalidate the returned references. pub unsafe fn next_back_unchecked(&mut self) -> (K, V) { - let (next_edge, k, v) = next_back_unchecked_deallocating(ptr::read(self)); - *self = next_edge; - (k, v) + replace(self, |leaf_edge| { + let kv = next_back_kv_unchecked_dealloc(leaf_edge); + let k = ptr::read(kv.reborrow().into_kv().0); + let v = ptr::read(kv.reborrow().into_kv().1); + (kv.next_back_leaf_edge(), (k, v)) + }) } } @@ -242,3 +215,29 @@ impl NodeRef { } } } + +impl Handle, marker::KV> { + /// Returns the leaf edge closest to a KV for forward navigation. + pub fn next_leaf_edge(self) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.right_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.right_edge(); + next_internal_edge.descend().first_leaf_edge() + } + } + } + + /// Returns the leaf edge closest to a KV for backward navigation. + pub fn next_back_leaf_edge( + self, + ) -> Handle, marker::Edge> { + match self.force() { + Leaf(leaf_kv) => leaf_kv.left_edge(), + Internal(internal_kv) => { + let next_internal_edge = internal_kv.left_edge(); + next_internal_edge.descend().last_leaf_edge() + } + } + } +} diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index e4123c9a20b..62b96ab9ef9 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -451,7 +451,7 @@ impl NodeRef { } } -impl NodeRef { +impl NodeRef { /// Similar to `ascend`, gets a reference to a node's parent node, but also /// deallocate the current node in the process. This is unsafe because the /// current node will still be accessible despite being deallocated. @@ -459,23 +459,17 @@ impl NodeRef { self, ) -> Option, marker::Edge>> { assert!(!self.is_shared_root()); + let height = self.height; let node = self.node; let ret = self.ascend().ok(); - Global.dealloc(node.cast(), Layout::new::>()); - ret - } -} - -impl NodeRef { - /// Similar to `ascend`, gets a reference to a node's parent node, but also - /// deallocate the current node in the process. This is unsafe because the - /// current node will still be accessible despite being deallocated. - pub unsafe fn deallocate_and_ascend( - self, - ) -> Option, marker::Edge>> { - let node = self.node; - let ret = self.ascend().ok(); - Global.dealloc(node.cast(), Layout::new::>()); + Global.dealloc( + node.cast(), + if height > 0 { + Layout::new::>() + } else { + Layout::new::>() + }, + ); ret } } @@ -1418,15 +1412,23 @@ unsafe fn move_edges( dest.correct_childrens_parent_links(dest_offset, dest_offset + count); } -impl Handle, marker::KV> { +impl Handle, marker::Edge> { pub fn forget_node_type( self, - ) -> Handle, marker::KV> { - unsafe { Handle::new_kv(self.node.forget_type(), self.idx) } + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } + } +} + +impl Handle, marker::Edge> { + pub fn forget_node_type( + self, + ) -> Handle, marker::Edge> { + unsafe { Handle::new_edge(self.node.forget_type(), self.idx) } } } -impl Handle, marker::KV> { +impl Handle, marker::KV> { pub fn forget_node_type( self, ) -> Handle, marker::KV> { From 4e0bea326e7f3f26ddae920e599597b309530e00 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 28 Feb 2020 13:28:09 +0900 Subject: [PATCH 0563/1250] Stabilize `boxed_slice_try_from` --- src/liballoc/boxed.rs | 2 +- src/liballoc/rc.rs | 2 +- src/liballoc/sync.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3ac4bd82a3a..81b0e9817d2 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -825,7 +825,7 @@ impl From> for Box<[u8]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Box<[T; N]> where [T; N]: LengthAtMost32, diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9dc5447397f..6ee128f4fa1 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1453,7 +1453,7 @@ impl From> for Rc<[T]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Rc<[T; N]> where [T; N]: LengthAtMost32, diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index fd285242d5b..9bd708c0f59 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -2002,7 +2002,7 @@ impl From> for Arc<[T]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Arc<[T; N]> where [T; N]: LengthAtMost32, From 85b585daaf735deda96c6e087e2a3f203c64d52d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 28 Feb 2020 07:58:37 +0100 Subject: [PATCH 0564/1250] late resolve, visit_fn: bail early if there's no body. --- src/librustc_resolve/late.rs | 5 +++-- .../ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs | 6 ++++++ .../resolve/issue-69401-trait-fn-no-body-ty-local.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs create mode 100644 src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index c924fef4dc9..48a2f829d19 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -456,8 +456,9 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) { let rib_kind = match fn_kind { - FnKind::Fn(FnCtxt::Foreign, ..) => return visit::walk_fn(self, fn_kind, sp), - FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind, + // Bail if there's no body. + FnKind::Fn(.., None) => return visit::walk_fn(self, fn_kind, sp), + FnKind::Fn(FnCtxt::Free, ..) | FnKind::Fn(FnCtxt::Foreign, ..) => FnItemRibKind, FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind, }; let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp)); diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs new file mode 100644 index 00000000000..4397baea4a9 --- /dev/null +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -0,0 +1,6 @@ +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: b); + //~^ ERROR cannot find type `b` in this scope +} diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr new file mode 100644 index 00000000000..109409d2731 --- /dev/null +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `b` in this scope + --> $DIR/issue-69401-trait-fn-no-body-ty-local.rs:4:53 + | +LL | fn fn_with_type_named_same_as_local_in_param(b: b); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From f9644c16f3156025d83d3dc1262ac35d9ae89588 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 09:21:25 +0100 Subject: [PATCH 0565/1250] add comment to check_data --- src/librustc/mir/interpret/value.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2c146b5d7b4..0e14089eebc 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -170,6 +170,10 @@ impl From for Scalar { } impl Scalar<()> { + /// Make sure the `data` fits in `size`. + /// This is guaranteed by all constructors here, but since the enum variants are public, + /// it could still be violated (even though no code outside this file should + /// construct `Scalar`s). #[inline(always)] fn check_data(data: u128, size: u8) { debug_assert_eq!( From e9ab099d6f30328b03ec2d5515bd11e4852d1eca Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 09:27:21 +0100 Subject: [PATCH 0566/1250] get rid of to_ptr --- src/librustc/mir/interpret/value.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 0e14089eebc..44a6fc5fb84 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -406,22 +406,14 @@ impl<'tcx, Tag> Scalar { self.to_bits(target_size).expect("expected Raw bits but got a Pointer") } - /// Do not call this method! Use either `assert_ptr` or `force_ptr`. - /// This method is intentionally private, do not make it public. #[inline] - fn to_ptr(self) -> InterpResult<'tcx, Pointer> { + pub fn assert_ptr(self) -> Pointer { match self { - Scalar::Raw { data: 0, .. } => throw_unsup!(InvalidNullPointerUsage), - Scalar::Raw { .. } => throw_unsup!(ReadBytesAsPointer), - Scalar::Ptr(p) => Ok(p), + Scalar::Ptr(p) => p, + Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits") } } - #[inline(always)] - pub fn assert_ptr(self) -> Pointer { - self.to_ptr().expect("expected a Pointer but got Raw bits") - } - /// Do not call this method! Dispatch based on the type instead. #[inline] pub fn is_bits(self) -> bool { From 1fec68277a16e39389085fba462a05cd71797423 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 09:15:04 +0100 Subject: [PATCH 0567/1250] remove check_raw after reducing it to one use only --- src/librustc/mir/interpret/value.rs | 11 ++------ src/librustc_mir_build/hair/pattern/_match.rs | 28 +++++++++---------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 44a6fc5fb84..2eb5f7ca878 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -382,19 +382,14 @@ impl<'tcx, Tag> Scalar { } } - #[inline(always)] - pub fn check_raw(data: u128, size: u8, target_size: Size) { - assert_eq!(target_size.bytes(), size as u64); - assert_ne!(size, 0, "you should never look at the bits of a ZST"); - Scalar::check_data(data, size); - } - /// Do not call this method! Use either `assert_bits` or `force_bits`. #[inline] pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { match self { Scalar::Raw { data, size } => { - Self::check_raw(data, size, target_size); + assert_eq!(target_size.bytes(), size as u64); + assert_ne!(size, 0, "you should never look at the bits of a ZST"); + Scalar::check_data(data, size); Ok(data) } Scalar::Ptr(_) => throw_unsup!(ReadPointerAsBytes), diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 85f03629b64..a4a122a737f 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1396,21 +1396,19 @@ impl<'tcx> IntRange<'tcx> { ) -> Option> { if let Some((target_size, bias)) = Self::integral_size_and_signed_bias(tcx, value.ty) { let ty = value.ty; - let val = if let ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data, size })) = - value.val - { - // For this specific pattern we can skip a lot of effort and go - // straight to the result, after doing a bit of checking. (We - // could remove this branch and just use the next branch, which - // is more general but much slower.) - Scalar::<()>::check_raw(data, size, target_size); - data - } else if let Some(val) = value.try_eval_bits(tcx, param_env, ty) { - // This is a more general form of the previous branch. - val - } else { - return None; - }; + let val = (|| { + if let ty::ConstKind::Value(ConstValue::Scalar(scalar)) = value.val { + // For this specific pattern we can skip a lot of effort and go + // straight to the result, after doing a bit of checking. (We + // could remove this branch and just fall through, which + // is more general but much slower.) + if let Ok(bits) = scalar.to_bits_or_ptr(target_size, &tcx) { + return Some(bits); + } + } + // This is a more general form of the previous case. + value.try_eval_bits(tcx, param_env, ty) + })()?; let val = val ^ bias; Some(IntRange { range: val..=val, ty, span }) } else { From 299a0d559f574f1ca1092a3783f00adba68be290 Mon Sep 17 00:00:00 2001 From: Pulkit Goyal <7895pulkit@gmail.com> Date: Wed, 26 Feb 2020 14:00:35 +0530 Subject: [PATCH 0568/1250] docs: add mention of async blocks in move keyword docs Fixes #69298 --- src/libstd/keyword_docs.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/libstd/keyword_docs.rs b/src/libstd/keyword_docs.rs index 58f4e76cd30..3c69c1160d5 100644 --- a/src/libstd/keyword_docs.rs +++ b/src/libstd/keyword_docs.rs @@ -895,6 +895,15 @@ mod mod_keyword {} /// // x is no longer available /// ``` /// +/// `move` is also valid before an async block. +/// +/// ```rust +/// let capture = "hello"; +/// let block = async move { +/// println!("rust says {} from async block", capture); +/// }; +/// ``` +/// /// For more information on the `move` keyword, see the [closure]'s section /// of the Rust book or the [threads] section /// From 1b0bb35ca3cd8e80c9255eefb1e35381ec9aa73a Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 28 Feb 2020 12:22:28 +0100 Subject: [PATCH 0569/1250] Unrevert "Remove `checked_add` in `Layout::repeat`" --- src/libcore/alloc.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index a04e75bc7ce..71f7f971eab 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -241,13 +241,11 @@ impl Layout { #[unstable(feature = "alloc_layout_extra", issue = "55724")] #[inline] pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> { - // Warning, removing the checked_add here led to segfaults in #67174. Further - // analysis in #69225 seems to indicate that this is an LTO-related - // miscompilation, so #67174 might be able to be reapplied in the future. - let padded_size = self - .size() - .checked_add(self.padding_needed_for(self.align())) - .ok_or(LayoutErr { private: () })?; + // This cannot overflow. Quoting from the invariant of Layout: + // > `size`, when rounded up to the nearest multiple of `align`, + // > must not overflow (i.e., the rounded value must be less than + // > `usize::MAX`) + let padded_size = self.size() + self.padding_needed_for(self.align()); let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?; unsafe { From 0c5d497603129d3bf25e83e3e387bb39202b34ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 28 Feb 2020 13:19:30 +0100 Subject: [PATCH 0570/1250] use to_vec() instead of .iter().cloned().collect() to convert slices to vecs. --- src/librustc_builtin_macros/deriving/generic/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 00ed05608b5..7f7ee6e0fed 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -588,14 +588,14 @@ impl<'a> TraitDef<'a> { span: self.span, bound_generic_params: wb.bound_generic_params.clone(), bounded_ty: wb.bounded_ty.clone(), - bounds: wb.bounds.iter().cloned().collect(), + bounds: wb.bounds.to_vec(), }) } ast::WherePredicate::RegionPredicate(ref rb) => { ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { span: self.span, lifetime: rb.lifetime, - bounds: rb.bounds.iter().cloned().collect(), + bounds: rb.bounds.to_vec(), }) } ast::WherePredicate::EqPredicate(ref we) => { From ff9341a9e3c23494cbd51fabafd1275097d41203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 28 Feb 2020 13:36:45 +0100 Subject: [PATCH 0571/1250] remove redundant clones, references to operands, explicit boolean comparisons and filter(x).next() calls. --- src/librustc_infer/traits/wf.rs | 12 ++-- src/librustc_mir/dataflow/mod.rs | 6 +- src/librustc_parse/parser/stmt.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 70 +++++++++++------------- src/librustdoc/test.rs | 2 +- 5 files changed, 39 insertions(+), 53 deletions(-) diff --git a/src/librustc_infer/traits/wf.rs b/src/librustc_infer/traits/wf.rs index 993eb41b9b1..980a3f04781 100644 --- a/src/librustc_infer/traits/wf.rs +++ b/src/librustc_infer/traits/wf.rs @@ -232,10 +232,8 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { // found type `()` if let Some(hir::ItemKind::Impl { items, .. }) = item.map(|i| &i.kind) { let trait_assoc_item = tcx.associated_item(proj.projection_def_id()); - if let Some(impl_item) = items - .iter() - .filter(|item| item.ident == trait_assoc_item.ident) - .next() + if let Some(impl_item) = + items.iter().find(|item| item.ident == trait_assoc_item.ident) { cause.span = impl_item.span; cause.code = traits::AssocTypeBound(Box::new(AssocTypeBoundData { @@ -285,13 +283,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { { if let Some((impl_item, trait_assoc_item)) = trait_assoc_items .iter() - .filter(|i| i.def_id == *item_def_id) - .next() + .find(|i| i.def_id == *item_def_id) .and_then(|trait_assoc_item| { items .iter() - .filter(|i| i.ident == trait_assoc_item.ident) - .next() + .find(|i| i.ident == trait_assoc_item.ident) .map(|impl_item| (impl_item, trait_assoc_item)) }) { diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index eccdac2fb99..a0d93d6d19a 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -689,11 +689,7 @@ pub trait BottomValue { /// 3. Override `join` to do the opposite from what it's doing now. #[inline] fn join(&self, inout_set: &mut BitSet, in_set: &BitSet) -> bool { - if Self::BOTTOM_VALUE == false { - inout_set.union(in_set) - } else { - inout_set.intersect(in_set) - } + if !Self::BOTTOM_VALUE { inout_set.union(in_set) } else { inout_set.intersect(in_set) } } } diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 257292ae072..9073e131f70 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -89,7 +89,7 @@ impl<'a> Parser<'a> { fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs.clone(), false, true, |_| true)?; + let item = self.parse_item_common(attrs, false, true, |_| true)?; self.directory.ownership = old; Ok(item) } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 957574cced7..e2aa853e78c 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -968,18 +968,14 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for missing in &self.missing_named_lifetime_spots { match missing { MissingLifetimeSpot::Generics(generics) => { - let (span, sugg) = if let Some(param) = generics - .params - .iter() - .filter(|p| match p.kind { + let (span, sugg) = if let Some(param) = + generics.params.iter().find(|p| match p.kind { hir::GenericParamKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. } => false, _ => true, - }) - .next() - { + }) { (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)) } else { (generics.span, format!("<{}>", lifetime_ref)) @@ -1053,25 +1049,24 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { Applicability::MaybeIncorrect, ); }; - let suggest_new = - |err: &mut DiagnosticBuilder<'_>, sugg: &str| { - err.span_label(span, "expected named lifetime parameter"); + let suggest_new = |err: &mut DiagnosticBuilder<'_>, sugg: &str| { + err.span_label(span, "expected named lifetime parameter"); - for missing in self.missing_named_lifetime_spots.iter().rev() { - let mut introduce_suggestion = vec![]; - let msg; - let should_break; - introduce_suggestion.push(match missing { + for missing in self.missing_named_lifetime_spots.iter().rev() { + let mut introduce_suggestion = vec![]; + let msg; + let should_break; + introduce_suggestion.push(match missing { MissingLifetimeSpot::Generics(generics) => { msg = "consider introducing a named lifetime parameter".to_string(); should_break = true; - if let Some(param) = generics.params.iter().filter(|p| match p.kind { + if let Some(param) = generics.params.iter().find(|p| match p.kind { hir::GenericParamKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. } => false, _ => true, - }).next() { + }) { (param.span.shrink_to_lo(), "'a, ".to_string()) } else { (generics.span, "<'a>".to_string()) @@ -1090,30 +1085,29 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { (*span, span_type.suggestion("'a")) } }); - for param in params { - if let Ok(snippet) = - self.tcx.sess.source_map().span_to_snippet(param.span) - { - if snippet.starts_with("&") && !snippet.starts_with("&'") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[1..]))); - } else if snippet.starts_with("&'_ ") { - introduce_suggestion - .push((param.span, format!("&'a {}", &snippet[4..]))); - } + for param in params { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) + { + if snippet.starts_with("&") && !snippet.starts_with("&'") { + introduce_suggestion + .push((param.span, format!("&'a {}", &snippet[1..]))); + } else if snippet.starts_with("&'_ ") { + introduce_suggestion + .push((param.span, format!("&'a {}", &snippet[4..]))); } } - introduce_suggestion.push((span, sugg.to_string())); - err.multipart_suggestion( - &msg, - introduce_suggestion, - Applicability::MaybeIncorrect, - ); - if should_break { - break; - } } - }; + introduce_suggestion.push((span, sugg.to_string())); + err.multipart_suggestion( + &msg, + introduce_suggestion, + Applicability::MaybeIncorrect, + ); + if should_break { + break; + } + } + }; match ( lifetime_names.len(), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 5dd7bd82755..4d51b63b740 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -398,7 +398,7 @@ pub fn make_test( use rustc_span::source_map::FilePathMapping; let filename = FileName::anon_source_code(s); - let source = crates + &everything_else; + let source = crates + everything_else; // Any errors in parsing should also appear when the doctest is compiled for real, so just // send all the errors that libsyntax emits directly into a `Sink` instead of stderr. From 3713ed67fd46b113948ed98170325a7225bdf331 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Fri, 28 Feb 2020 14:15:06 +0100 Subject: [PATCH 0572/1250] Improve MinGW detection when cross compiling --- src/bootstrap/dist.rs | 9 ++++++++- src/librustc_target/spec/i686_pc_windows_gnu.rs | 1 + src/librustc_target/spec/x86_64_pc_windows_gnu.rs | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 8003d8906e8..d2f2bc56bdc 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -234,7 +234,14 @@ fn make_win_dist( } } - let target_tools = ["gcc.exe", "ld.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let compiler = if target_triple == "i686-pc-windows-gnu" { + "i686-w64-mingw32-gcc.exe" + } else if target_triple == "x86_64-pc-windows-gnu" { + "x86_64-w64-mingw32-gcc.exe" + } else { + "gcc.exe" + }; + let target_tools = [&compiler, "ld.exe", "dlltool.exe", "libwinpthread-1.dll"]; let mut rustc_dlls = vec!["libwinpthread-1.dll"]; if target_triple.starts_with("i686-") { rustc_dlls.push("libgcc_s_dw2-1.dll"); diff --git a/src/librustc_target/spec/i686_pc_windows_gnu.rs b/src/librustc_target/spec/i686_pc_windows_gnu.rs index 35fbf875731..2091902d7ce 100644 --- a/src/librustc_target/spec/i686_pc_windows_gnu.rs +++ b/src/librustc_target/spec/i686_pc_windows_gnu.rs @@ -5,6 +5,7 @@ pub fn target() -> TargetResult { base.cpu = "pentium4".to_string(); base.max_atomic_width = Some(64); base.eliminate_frame_pointer = false; // Required for backtraces + base.linker = Some("i686-w64-mingw32-gcc".to_string()); // Mark all dynamic libraries and executables as compatible with the larger 4GiB address // space available to x86 Windows binaries on x86_64. diff --git a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs index 8f523a3b6c6..3d3acc682de 100644 --- a/src/librustc_target/spec/x86_64_pc_windows_gnu.rs +++ b/src/librustc_target/spec/x86_64_pc_windows_gnu.rs @@ -5,6 +5,7 @@ pub fn target() -> TargetResult { base.cpu = "x86-64".to_string(); base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string()); base.max_atomic_width = Some(64); + base.linker = Some("x86_64-w64-mingw32-gcc".to_string()); Ok(Target { llvm_target: "x86_64-pc-windows-gnu".to_string(), From 9523c89f18ca62c992e580fc33fe1bf092696d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 28 Feb 2020 14:20:33 +0100 Subject: [PATCH 0573/1250] use is_empty() instead of len() == x to determine if structs are empty. --- src/libcore/slice/mod.rs | 4 ++-- src/librustc/arena.rs | 2 +- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/ich/hcx.rs | 2 +- src/librustc/ich/impls_syntax.rs | 2 +- src/librustc/mir/interpret/error.rs | 2 +- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/context.rs | 16 ++++++++-------- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_ast_lowering/path.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 2 +- src/librustc_builtin_macros/concat.rs | 2 +- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/llvm_util.rs | 2 +- src/librustc_codegen_ssa/back/link.rs | 4 ++-- src/librustc_codegen_ssa/back/write.rs | 12 ++++++------ src/librustc_data_structures/profiling.rs | 2 +- src/librustc_errors/emitter.rs | 2 +- src/librustc_errors/snippet.rs | 2 +- .../infer/canonical/query_response.rs | 2 +- .../infer/region_constraints/mod.rs | 2 +- src/librustc_infer/traits/error_reporting/mod.rs | 2 +- src/librustc_infer/traits/select.rs | 2 +- src/librustc_lint/levels.rs | 2 +- src/librustc_metadata/dependency_format.rs | 2 +- src/librustc_mir/interpret/eval_context.rs | 6 +++--- .../transform/uninhabited_enum_branching.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_mir/util/patch.rs | 2 +- src/librustc_mir_build/build/matches/mod.rs | 2 +- src/librustc_mir_build/build/matches/test.rs | 2 +- src/librustc_parse/lexer/tokentrees.rs | 2 +- src/librustc_parse/lib.rs | 2 +- src/librustc_parse/parser/path.rs | 2 +- src/librustc_resolve/check_unused.rs | 2 +- src/librustc_resolve/imports.rs | 2 +- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 12 ++++-------- src/librustc_session/config.rs | 2 +- src/librustc_span/lib.rs | 2 +- src/librustc_traits/dropck_outlives.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/op.rs | 2 +- src/librustc_typeck/check/pat.rs | 6 +++--- src/librustc_typeck/collect.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/render.rs | 6 +++--- src/librustdoc/theme.rs | 2 +- src/libstd/backtrace.rs | 2 +- src/libtest/formatters/json.rs | 2 +- 54 files changed, 78 insertions(+), 82 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 7c65f595790..9a4561f2869 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3823,7 +3823,7 @@ where // The last index of self.v is already checked and found to match // by the last iteration, so we start searching a new match // one index to the left. - let remainder = if self.v.len() == 0 { &[] } else { &self.v[..(self.v.len() - 1)] }; + let remainder = if self.v.is_empty() { &[] } else { &self.v[..(self.v.len() - 1)] }; let idx = remainder.iter().rposition(|x| (self.pred)(x)).map(|idx| idx + 1).unwrap_or(0); if idx == 0 { self.finished = true; @@ -4033,7 +4033,7 @@ where return None; } - let idx_opt = if self.v.len() == 0 { + let idx_opt = if self.v.is_empty() { None } else { // work around borrowck limitations diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index ca55d410ceb..16920947c80 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -250,7 +250,7 @@ impl<'tcx> Arena<'tcx> { #[inline] pub fn alloc_slice(&self, value: &[T]) -> &mut [T] { - if value.len() == 0 { + if value.is_empty() { return &mut []; } self.dropless.alloc_slice(value) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 531a45b120c..33902fe913a 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -809,7 +809,7 @@ impl DepGraph { dep_node ); - if unlikely!(diagnostics.len() > 0) { + if unlikely!(!diagnostics.is_empty()) { self.emit_diagnostics(tcx, data, dep_node_index, prev_dep_node_index, diagnostics); } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 1a9c5d1f13f..2cb8388aca6 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -19,7 +19,7 @@ use smallvec::SmallVec; use std::cmp::Ord; fn compute_ignored_attr_names() -> FxHashSet { - debug_assert!(ich::IGNORED_ATTRIBUTES.len() > 0); + debug_assert!(!ich::IGNORED_ATTRIBUTES.is_empty()); ich::IGNORED_ATTRIBUTES.iter().map(|&s| s).collect() } diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index d1815d5e320..889c8f3aca0 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -14,7 +14,7 @@ impl<'ctx> rustc_target::HashStableContext for StableHashingContext<'ctx> {} impl<'a> HashStable> for [ast::Attribute] { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - if self.len() == 0 { + if self.is_empty() { self.len().hash_stable(hcx, hasher); return; } diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index a23ff6bd66d..28e197b2a7f 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -171,7 +171,7 @@ impl<'tcx> ConstEvalErr<'tcx> { // Skip the last, which is just the environment of the constant. The stacktrace // is sometimes empty because we create "fake" eval contexts in CTFE to do work // on constant values. - if self.stacktrace.len() > 0 { + if !self.stacktrace.is_empty() { for frame_info in &self.stacktrace[..self.stacktrace.len() - 1] { err.span_label(frame_info.call_site, frame_info.to_string()); } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 6a937b87645..a415c72d0ba 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -2219,7 +2219,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }); let region = if print_region { let mut region = region.to_string(); - if region.len() > 0 { + if !region.is_empty() { region.push(' '); } region diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 823cbf0966d..befae4195f3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2473,7 +2473,7 @@ impl<'tcx> TyCtxt<'tcx> { // FIXME consider asking the input slice to be sorted to avoid // re-interning permutations, in which case that would be asserted // here. - if preds.len() == 0 { + if preds.is_empty() { // The macro-generated method below asserts we don't intern an empty slice. List::empty() } else { @@ -2482,31 +2482,31 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx List> { - if ts.len() == 0 { List::empty() } else { self._intern_type_list(ts) } + if ts.is_empty() { List::empty() } else { self._intern_type_list(ts) } } pub fn intern_substs(self, ts: &[GenericArg<'tcx>]) -> &'tcx List> { - if ts.len() == 0 { List::empty() } else { self._intern_substs(ts) } + if ts.is_empty() { List::empty() } else { self._intern_substs(ts) } } pub fn intern_projs(self, ps: &[ProjectionKind]) -> &'tcx List { - if ps.len() == 0 { List::empty() } else { self._intern_projs(ps) } + if ps.is_empty() { List::empty() } else { self._intern_projs(ps) } } pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List> { - if ts.len() == 0 { List::empty() } else { self._intern_place_elems(ts) } + if ts.is_empty() { List::empty() } else { self._intern_place_elems(ts) } } pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'tcx> { - if ts.len() == 0 { List::empty() } else { self._intern_canonical_var_infos(ts) } + if ts.is_empty() { List::empty() } else { self._intern_canonical_var_infos(ts) } } pub fn intern_clauses(self, ts: &[Clause<'tcx>]) -> Clauses<'tcx> { - if ts.len() == 0 { List::empty() } else { self._intern_clauses(ts) } + if ts.is_empty() { List::empty() } else { self._intern_clauses(ts) } } pub fn intern_goals(self, ts: &[Goal<'tcx>]) -> Goals<'tcx> { - if ts.len() == 0 { List::empty() } else { self._intern_goals(ts) } + if ts.is_empty() { List::empty() } else { self._intern_goals(ts) } } pub fn mk_fn_sig( diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 66888cdb552..f65822aba4c 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -314,7 +314,7 @@ impl<'tcx> Instance<'tcx> { ) -> Option> { 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 + let is_vtable_shim = !fn_sig.inputs().skip_binder().is_empty() && fn_sig.input(0).skip_binder().is_param(0) && tcx.generics_of(def_id).has_self; if is_vtable_shim { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e8bf2eb9a12..cb98ff4c9e5 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -798,7 +798,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // (Typechecking will reject discriminant-sizing attrs.) let v = present_first.unwrap(); - let kind = if def.is_enum() || variants[v].len() == 0 { + let kind = if def.is_enum() || variants[v].is_empty() { StructKind::AlwaysSized } else { let param_env = tcx.param_env(def.did); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dae9f945ce0..4c7046781c1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -698,7 +698,7 @@ impl List { fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { assert!(!mem::needs_drop::()); assert!(mem::size_of::() != 0); - assert!(slice.len() != 0); + assert!(!slice.is_empty()); // Align up the size of the len (usize) field let align = mem::align_of::(); diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index b45a06e1c1d..248874dbe46 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -229,7 +229,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { err.span_label(data.span, "only `Fn` traits may use parentheses"); if let Ok(snippet) = self.sess.source_map().span_to_snippet(data.span) { // Do not suggest going from `Trait()` to `Trait<>` - if data.inputs.len() > 0 { + if !data.inputs.is_empty() { if let Some(split) = snippet.find('(') { let trait_name = &snippet[0..split]; let args = &snippet[split + 1..snippet.len() - 1]; diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index 3431c1b8e9d..76e1e7c175b 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -791,7 +791,7 @@ impl<'a> PrintState<'a> for State<'a> { s.print_generic_arg(generic_arg) }); - let mut comma = data.args.len() != 0; + let mut comma = !data.args.is_empty(); for constraint in data.constraints.iter() { if comma { diff --git a/src/librustc_builtin_macros/concat.rs b/src/librustc_builtin_macros/concat.rs index ed65611da61..1f1c8b8d21e 100644 --- a/src/librustc_builtin_macros/concat.rs +++ b/src/librustc_builtin_macros/concat.rs @@ -49,7 +49,7 @@ pub fn expand_concat( } } } - if missing_literal.len() > 0 { + if !missing_literal.is_empty() { 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(); diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index a9298abe2d7..5343ab0fbbe 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -1096,7 +1096,7 @@ pub fn expand_preparsed_format_args( cx.str_pieces.push(s); } - if cx.invalid_refs.len() >= 1 { + if !cx.invalid_refs.is_empty() { cx.report_invalid_references(numbered_position_args); } diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index d7297ed4176..8c3fdcb8ecd 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -237,7 +237,7 @@ fn fat_lto( let module: ModuleCodegen = match costliest_module { Some((_cost, i)) => in_memory.remove(i), None => { - assert!(serialized_modules.len() > 0, "must have at least one serialized module"); + assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); let (buffer, name) = serialized_modules.remove(0); info!("no in-memory regular modules to choose from, parsing {:?}", name); ModuleCodegen { diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 6d3498f8b80..0081a75a4da 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -61,7 +61,7 @@ unsafe fn configure_llvm(sess: &Session) { let sess_args = cg_opts.chain(tg_opts); let user_specified_args: FxHashSet<_> = - sess_args.clone().map(|s| llvm_arg_to_arg_name(s)).filter(|s| s.len() > 0).collect(); + sess_args.clone().map(|s| llvm_arg_to_arg_name(s)).filter(|s| !s.is_empty()).collect(); { // This adds the given argument to LLVM. Unless `force` is true diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 78aacc56ea4..90601521b19 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1524,12 +1524,12 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( for &(cnum, _) in deps.iter().rev() { if let Some(missing) = info.missing_lang_items.get(&cnum) { end_with.extend(missing.iter().cloned()); - if end_with.len() > 0 && group_end.is_none() { + if !end_with.is_empty() && group_end.is_none() { group_end = Some(cnum); } } end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum)); - if end_with.len() == 0 && group_end.is_some() { + if end_with.is_empty() && group_end.is_some() { group_start = Some(cnum); break; } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 92f795acc54..bc20ed6f6c5 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1244,10 +1244,10 @@ fn start_executing_work( while !codegen_done || running > 0 || (!codegen_aborted - && (work_items.len() > 0 - || needs_fat_lto.len() > 0 - || needs_thin_lto.len() > 0 - || lto_import_only_modules.len() > 0 + && (!work_items.is_empty() + || !needs_fat_lto.is_empty() + || !needs_thin_lto.is_empty() + || !lto_import_only_modules.is_empty() || main_thread_worker_state != MainThreadWorkerState::Idle)) { // While there are still CGUs to be codegened, the coordinator has @@ -1289,7 +1289,7 @@ fn start_executing_work( // Perform the serial work here of figuring out what we're // going to LTO and then push a bunch of work items onto our // queue to do LTO - if work_items.len() == 0 + if work_items.is_empty() && running == 0 && main_thread_worker_state == MainThreadWorkerState::Idle { @@ -1354,7 +1354,7 @@ fn start_executing_work( // Spin up what work we can, only doing this while we've got available // parallelism slots and work left to spawn. - while !codegen_aborted && work_items.len() > 0 && running < tokens.len() { + while !codegen_aborted && !work_items.is_empty() && running < tokens.len() { let (item, _) = work_items.pop().unwrap(); maybe_start_llvm_timer(prof, cgcx.config(item.module_kind()), &mut llvm_start_time); diff --git a/src/librustc_data_structures/profiling.rs b/src/librustc_data_structures/profiling.rs index f2c80510f22..a70314c35c0 100644 --- a/src/librustc_data_structures/profiling.rs +++ b/src/librustc_data_structures/profiling.rs @@ -425,7 +425,7 @@ impl SelfProfiler { } // Warn about any unknown event names - if unknown_events.len() > 0 { + if !unknown_events.is_empty() { unknown_events.sort(); unknown_events.dedup(); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index f3653da4be6..2d7ff191c77 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -231,7 +231,7 @@ pub trait Emitter { ].contains(&sugg.style) { let substitution = &sugg.substitutions[0].parts[0].snippet.trim(); - let msg = if substitution.len() == 0 || sugg.style.hide_inline() { + let msg = if substitution.is_empty() || sugg.style.hide_inline() { // This substitution is only removal OR we explicitly don't want to show the // code inline (`hide_inline`). Therefore, we don't show the substitution. format!("help: {}", sugg.msg) diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs index a39e19f0bf7..0660590a725 100644 --- a/src/librustc_errors/snippet.rs +++ b/src/librustc_errors/snippet.rs @@ -152,7 +152,7 @@ impl Annotation { // | // // Note that this would be the complete output users would see. - label.len() > 0 + !label.is_empty() } else { false } diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index f4196e57605..f77faf3d4ab 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -421,7 +421,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { for _ in num_universes_in_query..num_universes_in_response { universe_map.push(self.create_next_universe()); } - assert!(universe_map.len() >= 1); // always have the root universe + assert!(!universe_map.is_empty()); // always have the root universe assert_eq!(universe_map[ty::UniverseIndex::ROOT.as_usize()], ty::UniverseIndex::ROOT); // Every canonical query result includes values for each of diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index af4e199f288..3f9fa6459b3 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -587,7 +587,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { // skip no-op cases known to be satisfied if let VerifyBound::AllBounds(ref bs) = verify.bound { - if bs.len() == 0 { + if bs.is_empty() { return; } } diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 9bfa2196950..80b5e8ca69d 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -440,7 +440,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// going to help). pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { let cycle = self.resolve_vars_if_possible(&cycle.to_owned()); - assert!(cycle.len() > 0); + assert!(!cycle.is_empty()); debug!("report_overflow_error_cycle: cycle={:?}", cycle); diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index c6878fad2a4..925665763cb 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2157,7 +2157,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { debug!("builtin_bound: nested={:?}", nested); candidates .vec - .push(BuiltinCandidate { has_nested: nested.skip_binder().len() > 0 }); + .push(BuiltinCandidate { has_nested: !nested.skip_binder().is_empty() }); } BuiltinImplConditions::None => {} BuiltinImplConditions::Ambiguous => { diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index da449ed42fd..8e1947e52ca 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -375,7 +375,7 @@ impl<'s> LintLevelsBuilder<'s> { } let prev = self.cur; - if specs.len() > 0 { + if !specs.is_empty() { self.cur = self.sets.list.len() as u32; self.sets.list.push(LintSet::Node { specs: specs, parent: prev }); } diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 375f372005f..9e71839dbfd 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -339,7 +339,7 @@ fn activate_injected_dep( // there's only going to be one allocator in the output. fn verify_ok(tcx: TyCtxt<'_>, list: &[Linkage]) { let sess = &tcx.sess; - if list.len() == 0 { + if list.is_empty() { return; } let mut panic_runtime = None; diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index cce4b90e224..7a3f09ac80b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -264,7 +264,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { #[inline(always)] pub fn cur_frame(&self) -> usize { - assert!(self.stack.len() > 0); + assert!(!self.stack.is_empty()); self.stack.len() - 1 } @@ -505,7 +505,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { return_place: Option>, return_to_block: StackPopCleanup, ) -> InterpResult<'tcx> { - if self.stack.len() > 0 { + if !self.stack.is_empty() { info!("PAUSING({}) {}", self.cur_frame(), self.frame().instance); } ::log_settings::settings().indentation += 1; @@ -698,7 +698,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } - if self.stack.len() > 0 { + if !self.stack.is_empty() { info!( "CONTINUING({}) {} (unwinding = {})", self.cur_frame(), diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index 0bf0ff2852d..8f2f2094b1e 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -28,7 +28,7 @@ fn get_switched_on_type<'tcx>( // Only bother checking blocks which terminate by switching on a local. if let Some(local) = get_discriminant_local(&terminator.kind) { - let stmt_before_term = (block_data.statements.len() > 0) + let stmt_before_term = (!block_data.statements.is_empty()) .then(|| &block_data.statements[block_data.statements.len() - 1].kind); if let Some(StatementKind::Assign(box (l, Rvalue::Discriminant(place)))) = stmt_before_term diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index fab64e37cbc..83483aeb6a4 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -369,7 +369,7 @@ where fn open_drop_for_adt(&mut self, adt: &'tcx ty::AdtDef, substs: SubstsRef<'tcx>) -> BasicBlock { debug!("open_drop_for_adt({:?}, {:?}, {:?})", self, adt, substs); - if adt.variants.len() == 0 { + if adt.variants.is_empty() { return self.elaborator.patch().new_block(BasicBlockData { statements: vec![], terminator: Some(Terminator { diff --git a/src/librustc_mir/util/patch.rs b/src/librustc_mir/util/patch.rs index 68aa82f902f..473692a43f3 100644 --- a/src/librustc_mir/util/patch.rs +++ b/src/librustc_mir/util/patch.rs @@ -37,7 +37,7 @@ impl<'tcx> MirPatch<'tcx> { let mut resume_stmt_block = None; for (bb, block) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::Resume = block.terminator().kind { - if block.statements.len() > 0 { + if !block.statements.is_empty() { assert!(resume_stmt_block.is_none()); resume_stmt_block = Some(bb); } else { diff --git a/src/librustc_mir_build/build/matches/mod.rs b/src/librustc_mir_build/build/matches/mod.rs index d9091f92b03..bb61e56a2c5 100644 --- a/src/librustc_mir_build/build/matches/mod.rs +++ b/src/librustc_mir_build/build/matches/mod.rs @@ -1438,7 +1438,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let target_blocks: Vec<_> = target_candidates .into_iter() .map(|mut candidates| { - if candidates.len() != 0 { + if !candidates.is_empty() { let candidate_start = this.cfg.start_new_block(); this.match_candidates( span, diff --git a/src/librustc_mir_build/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs index 1acfa7dddbe..9f450f8fc7b 100644 --- a/src/librustc_mir_build/build/matches/test.rs +++ b/src/librustc_mir_build/build/matches/test.rs @@ -222,7 +222,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::SwitchInt { switch_ty, ref options, indices: _ } => { let target_blocks = make_target_blocks(self); let terminator = if switch_ty.kind == ty::Bool { - assert!(options.len() > 0 && options.len() <= 2); + assert!(!options.is_empty() && options.len() <= 2); if let [first_bb, second_bb] = *target_blocks { let (true_bb, false_bb) = match options[0] { 1 => (first_bb, second_bb), diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index a412dabf144..e87dde8863c 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -141,7 +141,7 @@ impl<'a> TokenTreesReader<'a> { self.last_delim_empty_block_spans.insert(delim, empty_block_span); } - if self.open_braces.len() == 0 { + if self.open_braces.is_empty() { // Clear up these spans to avoid suggesting them as we've found // properly matched delimiters so far for an entire block. self.matching_delim_spans.clear(); diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 4cf9e4c3059..c60330864de 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -371,7 +371,7 @@ fn prepend_attrs( span: rustc_span::Span, ) -> Option { let tokens = tokens?; - if attrs.len() == 0 { + if attrs.is_empty() { return Some(tokens.clone()); } let mut builder = tokenstream::TokenStreamBuilder::new(); diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 18e57c6a5d4..550cf48601f 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -470,7 +470,7 @@ impl<'a> Parser<'a> { // FIXME: we would like to report this in ast_validation instead, but we currently do not // preserve ordering of generic parameters with respect to associated type binding, so we // lose that information after parsing. - if misplaced_assoc_ty_constraints.len() > 0 { + if !misplaced_assoc_ty_constraints.is_empty() { let mut err = self.struct_span_err( args_lo.to(self.prev_span), "associated type bindings must be declared after generic parameters", diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index e8e3b685794..74154cb3df4 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -158,7 +158,7 @@ fn calc_unused_spans( } } ast::UseTreeKind::Nested(ref nested) => { - if nested.len() == 0 { + if nested.is_empty() { return UnusedSpanResult::FlatUnused(use_tree.span, full_span); } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 55ce51e0ff0..3926849e7ca 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1478,7 +1478,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } }); - if reexports.len() > 0 { + if !reexports.is_empty() { if let Some(def_id) = module.def_id() { self.r.export_map.insert(def_id, reexports); } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index c924fef4dc9..6b0fc5bda41 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1016,7 +1016,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_items .iter() .filter_map(|item| match &item.kind { - AssocItemKind::TyAlias(_, _, bounds, _) if bounds.len() == 0 => { + AssocItemKind::TyAlias(_, _, bounds, _) if bounds.is_empty() => { Some(item.ident) } _ => None, diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 957574cced7..f1f42f491aa 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -354,7 +354,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { let mut has_self_arg = None; if let PathSource::Expr(parent) = source { match &parent?.kind { - ExprKind::Call(_, args) if args.len() > 0 => { + ExprKind::Call(_, args) if !args.is_empty() => { let mut expr_kind = &args[0].kind; loop { match expr_kind { @@ -968,18 +968,14 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for missing in &self.missing_named_lifetime_spots { match missing { MissingLifetimeSpot::Generics(generics) => { - let (span, sugg) = if let Some(param) = generics - .params - .iter() - .filter(|p| match p.kind { + let (span, sugg) = if let Some(param) = + generics.params.iter().find(|p| match p.kind { hir::GenericParamKind::Type { synthetic: Some(hir::SyntheticTyParamKind::ImplTrait), .. } => false, _ => true, - }) - .next() - { + }) { (param.span.shrink_to_lo(), format!("{}, ", lifetime_ref)) } else { (generics.span, format!("<{}>", lifetime_ref)) diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index a6f9a5fe3e0..8c7ea63d405 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -1129,7 +1129,7 @@ pub fn parse_error_format( // Conservatively require that the `--json` argument is coupled with // `--error-format=json`. This means that `--json` is specified we // should actually be emitting JSON blobs. - _ if matches.opt_strs("json").len() > 0 => { + _ if !matches.opt_strs("json").is_empty() => { early_error( ErrorOutputType::default(), "using `--json` requires also using `--error-format=json`", diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index f9f3a900311..a361267b59e 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -1205,7 +1205,7 @@ impl SourceFile { /// number. If the source_file is empty or the position is located before the /// first line, `None` is returned. pub fn lookup_line(&self, pos: BytePos) -> Option { - if self.lines.len() == 0 { + if self.lines.is_empty() { return None; } diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index e14295de061..2f854c045e5 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -92,7 +92,7 @@ fn dropck_outlives<'tcx>( // information and will just decrease the speed at which we can emit these errors // (since we'll be printing for just that much longer for the often enormous types // that result here). - if result.overflows.len() >= 1 { + if !result.overflows.is_empty() { break; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 710f02cdedb..5819a9f2df7 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1743,7 +1743,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { potential_assoc_types: Vec, trait_bounds: &[hir::PolyTraitRef<'_>], ) { - if !associated_types.values().any(|v| v.len() > 0) { + if !associated_types.values().any(|v| !v.is_empty()) { return; } let tcx = self.tcx(); diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index cb6e028ab86..1c72b49fbbe 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -529,7 +529,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .lookup_op_method(fn_sig.output(), &[other_ty], Op::Binary(op, is_assign)) .is_ok() { - let (variable_snippet, applicability) = if fn_sig.inputs().len() > 0 { + let (variable_snippet, applicability) = if !fn_sig.inputs().is_empty() { ( format!("{}( /* arguments */ )", source_map.span_to_snippet(span).unwrap()), Applicability::HasPlaceholders, diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 2c7cbed6a2d..c8eef9dfd04 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -339,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); } - if pat_adjustments.len() > 0 { + if !pat_adjustments.is_empty() { debug!("default binding mode is now {:?}", def_bm); self.inh.tables.borrow_mut().pat_adjustments_mut().insert(pat.hir_id, pat_adjustments); } @@ -987,7 +987,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .filter(|ident| !used_fields.contains_key(&ident)) .collect::>(); - if inexistent_fields.len() > 0 && !variant.recovered { + if !inexistent_fields.is_empty() && !variant.recovered { self.error_inexistent_fields( kind_name, &inexistent_fields, @@ -1018,7 +1018,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if etc { tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit(); } - } else if !etc && unmentioned_fields.len() > 0 { + } else if !etc && !unmentioned_fields.is_empty() { self.error_unmentioned_fields(span, &unmentioned_fields, variant); } no_field_errors diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1fade1b5ca6..5e0f80b3357 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2481,7 +2481,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { // purpose functions as they wouldn't have the right target features // enabled. For that reason we also forbid #[inline(always)] as it can't be // respected. - if codegen_fn_attrs.target_features.len() > 0 { + if !codegen_fn_attrs.target_features.is_empty() { if codegen_fn_attrs.inline == InlineAttr::Always { if let Some(span) = inline_span { tcx.sess.span_err( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 50c780e9ecb..8be6bf8f0d3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -398,7 +398,7 @@ impl Clean for hir::GenericParam<'_> { fn clean(&self, _: &DocContext<'_>) -> Lifetime { match self.kind { hir::GenericParamKind::Lifetime { .. } => { - if self.bounds.len() > 0 { + if !self.bounds.is_empty() { let mut bounds = self.bounds.iter().map(|bound| match bound { hir::GenericBound::Outlives(lt) => lt, _ => panic!(), @@ -607,7 +607,7 @@ impl Clean for hir::GenericParam<'_> { fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef { let (name, kind) = match self.kind { hir::GenericParamKind::Lifetime { .. } => { - let name = if self.bounds.len() > 0 { + let name = if !self.bounds.is_empty() { let mut bounds = self.bounds.iter().map(|bound| match bound { hir::GenericBound::Outlives(lt) => lt, _ => panic!(), diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 4f58116e4fe..ee685c90a62 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -201,7 +201,7 @@ impl Item { classes.push("deprecated"); } - if classes.len() != 0 { Some(classes.join(" ")) } else { None } + if !classes.is_empty() { Some(classes.join(" ")) } else { None } }) } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index bda220d8806..e1ac962f200 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2783,7 +2783,7 @@ fn assoc_type( fn render_stability_since_raw(w: &mut Buffer, ver: Option<&str>, containing_ver: Option<&str>) { if let Some(v) = ver { - if containing_ver != ver && v.len() > 0 { + if containing_ver != ver && !v.is_empty() { write!(w, "{0}", v) } } @@ -3143,7 +3143,7 @@ fn render_attribute(attr: &ast::MetaItem) -> Option { .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi))) .collect(); - if display.len() > 0 { Some(format!("{}({})", path, display.join(", "))) } else { None } + if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None } } else { None } @@ -3178,7 +3178,7 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { attrs.push_str(&format!("#[{}]\n", s)); } } - if attrs.len() > 0 { + if !attrs.is_empty() { write!( w, "{}", diff --git a/src/librustdoc/theme.rs b/src/librustdoc/theme.rs index 620f9f56a6a..a8a571e7c54 100644 --- a/src/librustdoc/theme.rs +++ b/src/librustdoc/theme.rs @@ -191,7 +191,7 @@ fn build_rule(v: &[u8], positions: &[usize]) -> String { .replace("{", "") .replace("}", "") .split(' ') - .filter(|s| s.len() > 0) + .filter(|s| !s.is_empty()) .collect::>() .join(" "), ) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index a1c9aa75d77..97db0ff3791 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -304,7 +304,7 @@ impl Backtrace { // If no frames came out assume that this is an unsupported platform // since `backtrace` doesn't provide a way of learning this right now, // and this should be a good enough approximation. - let inner = if frames.len() == 0 { + let inner = if frames.is_empty() { Inner::Unsupported } else { Inner::Captured(Mutex::new(Capture { diff --git a/src/libtest/formatters/json.rs b/src/libtest/formatters/json.rs index 863cad9f9d7..9ebc991d638 100644 --- a/src/libtest/formatters/json.rs +++ b/src/libtest/formatters/json.rs @@ -80,7 +80,7 @@ impl OutputFormatter for JsonFormatter { state: &ConsoleTestState, ) -> io::Result<()> { let display_stdout = state.options.display_output || *result != TestResult::TrOk; - let stdout = if display_stdout && stdout.len() > 0 { + let stdout = if display_stdout && !stdout.is_empty() { Some(String::from_utf8_lossy(stdout)) } else { None From bae5f3976b21f33d9d15ed7da04d3fb9b1878bdc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 Feb 2020 14:50:27 +0100 Subject: [PATCH 0574/1250] Add E0747 error code --- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_parse/lexer/mod.rs | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 91a7b6c8958..89359bb1bfd 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -418,6 +418,7 @@ E0744: include_str!("./error_codes/E0744.md"), E0745: include_str!("./error_codes/E0745.md"), E0746: include_str!("./error_codes/E0746.md"), E0747: include_str!("./error_codes/E0747.md"), +E0748: include_str!("./error_codes/E0748.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index 66280638a2d..face0e67992 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -1,5 +1,5 @@ use rustc_data_structures::sync::Lrc; -use rustc_errors::{DiagnosticBuilder, FatalError}; +use rustc_errors::{error_code, DiagnosticBuilder, FatalError}; use rustc_lexer::unescape; use rustc_lexer::Base; use rustc_session::parse::ParseSess; @@ -495,7 +495,11 @@ impl<'a> StringReader<'a> { } fn report_unterminated_raw_string(&self, start: BytePos, n_hashes: usize) -> ! { - let mut err = self.struct_span_fatal(start, start, "unterminated raw string"); + let mut err = self.sess.span_diagnostic.struct_span_fatal_with_code( + self.mk_sp(start, start), + "unterminated raw string", + error_code!(E0748), + ); err.span_label(self.mk_sp(start, start), "unterminated raw string"); if n_hashes > 0 { From f439de36afa8e70d99557a0563341a9211a14096 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 Feb 2020 14:50:40 +0100 Subject: [PATCH 0575/1250] Add explanation for E0747 --- src/librustc_error_codes/error_codes/E0748.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/librustc_error_codes/error_codes/E0748.md diff --git a/src/librustc_error_codes/error_codes/E0748.md b/src/librustc_error_codes/error_codes/E0748.md new file mode 100644 index 00000000000..7743c722eee --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0748.md @@ -0,0 +1,14 @@ +A raw string isn't correctly terminated because the trailing `#` count doesn't +match its leading `#` count. + +Erroneous code example: + +```compile_fail,E0748 +let dolphins = r##"Dolphins!"#; // error! +``` +To terminate a raw string, you have to have the same number of `#` at the end +than at the beginning. Example: +``` +let dolphins = r#"Dolphins!"#; // one `#` at the beginning, one at the end so + // all good! +``` From 8ce9460b7a132fa4075325d2ae4c4b4ecd09ffd0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 18 Feb 2020 14:50:48 +0100 Subject: [PATCH 0576/1250] Update UI tests --- src/test/ui/parser/raw-byte-string-eof.stderr | 3 ++- src/test/ui/parser/raw-str-unterminated.stderr | 3 ++- src/test/ui/parser/raw/raw_string.stderr | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/ui/parser/raw-byte-string-eof.stderr b/src/test/ui/parser/raw-byte-string-eof.stderr index 65fa89f2a81..d5f22e2a1a8 100644 --- a/src/test/ui/parser/raw-byte-string-eof.stderr +++ b/src/test/ui/parser/raw-byte-string-eof.stderr @@ -1,4 +1,4 @@ -error: unterminated raw string +error[E0748]: unterminated raw string --> $DIR/raw-byte-string-eof.rs:2:5 | LL | br##"a"#; @@ -8,3 +8,4 @@ LL | br##"a"#; error: aborting due to previous error +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/parser/raw-str-unterminated.stderr b/src/test/ui/parser/raw-str-unterminated.stderr index 67792eb91e5..077f763f154 100644 --- a/src/test/ui/parser/raw-str-unterminated.stderr +++ b/src/test/ui/parser/raw-str-unterminated.stderr @@ -1,4 +1,4 @@ -error: unterminated raw string +error[E0748]: unterminated raw string --> $DIR/raw-str-unterminated.rs:2:5 | LL | r#" string literal goes on @@ -8,3 +8,4 @@ LL | r#" string literal goes on error: aborting due to previous error +For more information about this error, try `rustc --explain E0748`. diff --git a/src/test/ui/parser/raw/raw_string.stderr b/src/test/ui/parser/raw/raw_string.stderr index 5572511881d..0f1d7e4651d 100644 --- a/src/test/ui/parser/raw/raw_string.stderr +++ b/src/test/ui/parser/raw/raw_string.stderr @@ -1,4 +1,4 @@ -error: unterminated raw string +error[E0748]: unterminated raw string --> $DIR/raw_string.rs:2:13 | LL | let x = r##"lol"#; @@ -8,3 +8,4 @@ LL | let x = r##"lol"#; error: aborting due to previous error +For more information about this error, try `rustc --explain E0748`. From e2738285ea7374bc6423ea6de095ad0e8990975d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Feb 2020 11:12:01 +0100 Subject: [PATCH 0577/1250] Wording improvement --- src/librustc_error_codes/error_codes/E0748.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0748.md b/src/librustc_error_codes/error_codes/E0748.md index 7743c722eee..69f1c026125 100644 --- a/src/librustc_error_codes/error_codes/E0748.md +++ b/src/librustc_error_codes/error_codes/E0748.md @@ -6,9 +6,11 @@ Erroneous code example: ```compile_fail,E0748 let dolphins = r##"Dolphins!"#; // error! ``` + To terminate a raw string, you have to have the same number of `#` at the end -than at the beginning. Example: +as at the beginning. Example: + ``` -let dolphins = r#"Dolphins!"#; // one `#` at the beginning, one at the end so +let dolphins = r#"Dolphins!"#; // One `#` at the beginning, one at the end so // all good! ``` From 63c77f1bd0beee9c3ee75cc41c507e31d3a72a5d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 11:04:12 +0100 Subject: [PATCH 0578/1250] remove ScalarMaybeUndef::to_bits and make Scalar::to_bits private --- src/librustc/mir/interpret/value.rs | 13 ++--- src/librustc/ty/sty.rs | 2 +- src/librustc_mir/interpret/intrinsics.rs | 2 +- src/librustc_mir/interpret/operand.rs | 63 +++++++++++------------- src/librustc_mir/interpret/validity.rs | 15 +++--- src/librustc_mir/transform/const_prop.rs | 4 +- 6 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2eb5f7ca878..c931fcf71e3 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -382,9 +382,10 @@ impl<'tcx, Tag> Scalar { } } - /// Do not call this method! Use either `assert_bits` or `force_bits`. + /// This method is intentionally private! + /// It is just a helper for other methods in this file. #[inline] - pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { + fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { match self { Scalar::Raw { data, size } => { assert_eq!(target_size.bytes(), size as u64); @@ -405,7 +406,7 @@ impl<'tcx, Tag> Scalar { pub fn assert_ptr(self) -> Pointer { match self { Scalar::Ptr(p) => p, - Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits") + Scalar::Raw { .. } => bug!("expected a Pointer but got Raw bits"), } } @@ -586,12 +587,6 @@ impl<'tcx, Tag> ScalarMaybeUndef { } } - /// Do not call this method! Use either `assert_bits` or `force_bits`. - #[inline(always)] - pub fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { - self.not_undef()?.to_bits(target_size) - } - #[inline(always)] pub fn to_bool(self) -> InterpResult<'tcx, bool> { self.not_undef()?.to_bool() diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index c3698f402a9..241781bb93d 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -2576,7 +2576,7 @@ impl<'tcx> ConstKind<'tcx> { #[inline] pub fn try_to_bits(&self, size: ty::layout::Size) -> Option { - self.try_to_scalar()?.to_bits(size).ok() + if let ConstKind::Value(val) = self { val.try_to_bits(size) } else { None } } } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index cd06cf01bfa..d63abdc3562 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -384,7 +384,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. // First, check x % y != 0 (or if that computation overflows). let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?; - if overflow || res.to_bits(a.layout.size)? != 0 { + if overflow || res.assert_bits(a.layout.size) != 0 { // Then, check if `b` is -1, which is the "min_value / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); let b_scalar = b.to_scalar().unwrap(); diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 14b8a341e26..20efe7dfc03 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -96,40 +96,40 @@ pub struct ImmTy<'tcx, Tag = ()> { impl std::fmt::Display for ImmTy<'tcx, Tag> { fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match &self.imm { - Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => match s.to_bits(self.layout.size) { - Ok(s) => { - match self.layout.ty.kind { - ty::Int(_) => { - return write!( - fmt, - "{}", - super::sign_extend(s, self.layout.size) as i128, - ); - } - ty::Uint(_) => return write!(fmt, "{}", s), - ty::Bool if s == 0 => return fmt.write_str("false"), - ty::Bool if s == 1 => return fmt.write_str("true"), - ty::Char => { - if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) { - return write!(fmt, "{}", c); - } + // We cannot use `to_bits_or_ptr` as we do not have a `tcx`. + // So we use `is_bits` and circumvent a bunch of sanity checking -- but + // this is anyway only for printing. + Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) if s.is_ptr() => { + fmt.write_str("{pointer}") + } + Immediate::Scalar(ScalarMaybeUndef::Scalar(s)) => { + let s = s.assert_bits(self.layout.size); + match self.layout.ty.kind { + ty::Int(_) => { + return write!(fmt, "{}", super::sign_extend(s, self.layout.size) as i128,); + } + ty::Uint(_) => return write!(fmt, "{}", s), + ty::Bool if s == 0 => return fmt.write_str("false"), + ty::Bool if s == 1 => return fmt.write_str("true"), + ty::Char => { + if let Some(c) = u32::try_from(s).ok().and_then(std::char::from_u32) { + return write!(fmt, "{}", c); } - ty::Float(ast::FloatTy::F32) => { - if let Ok(u) = u32::try_from(s) { - return write!(fmt, "{}", f32::from_bits(u)); - } + } + ty::Float(ast::FloatTy::F32) => { + if let Ok(u) = u32::try_from(s) { + return write!(fmt, "{}", f32::from_bits(u)); } - ty::Float(ast::FloatTy::F64) => { - if let Ok(u) = u64::try_from(s) { - return write!(fmt, "{}", f64::from_bits(u)); - } + } + ty::Float(ast::FloatTy::F64) => { + if let Ok(u) = u64::try_from(s) { + return write!(fmt, "{}", f64::from_bits(u)); } - _ => {} } - write!(fmt, "{:x}", s) + _ => {} } - Err(_) => fmt.write_str("{pointer}"), - }, + write!(fmt, "{:x}", s) + } Immediate::Scalar(ScalarMaybeUndef::Undef) => fmt.write_str("{undef}"), Immediate::ScalarPair(..) => fmt.write_str("{wide pointer or tuple}"), } @@ -205,11 +205,6 @@ impl<'tcx, Tag: Copy> ImmTy<'tcx, Tag> { pub fn from_int(i: impl Into, 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) - } } // Use the existing layout if given (but sanity check in debug mode), diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index aa2b3040a71..48c0e7930e9 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -361,16 +361,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> ty::Float(_) | ty::Int(_) | ty::Uint(_) => { // NOTE: Keep this in sync with the array optimization for int/float // types below! - let size = value.layout.size; let value = value.to_scalar_or_undef(); if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous - try_validation!( - value.to_bits(size), - value, - self.path, - "initialized plain (non-pointer) bytes" - ); + let is_bits = value.not_undef().map_or(false, |v| v.is_bits()); + if !is_bits { + throw_validation_failure!( + value, + self.path, + "initialized plain (non-pointer) bytes" + ) + } } else { // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9e05133132e..fe736321df7 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -557,7 +557,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let left_ty = left.ty(&self.local_decls, self.tcx); let left_size_bits = self.ecx.layout_of(left_ty).ok()?.size.bits(); let right_size = r.layout.size; - let r_bits = r.to_scalar().and_then(|r| r.to_bits(right_size)); + let r_bits = r.to_scalar().ok(); + // This is basically `force_bits`. + let r_bits = r_bits.and_then(|r| r.to_bits_or_ptr(right_size, &self.tcx).ok()); if r_bits.map_or(false, |b| b >= left_size_bits as u128) { self.report_assert_as_lint( lint::builtin::ARITHMETIC_OVERFLOW, From 0e157380ae2a7af0c457aea1c8be22161899ea1d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 14:08:48 +0100 Subject: [PATCH 0579/1250] move ZST assertion up, for better errors --- src/librustc/mir/interpret/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index c931fcf71e3..2be60d35af3 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -368,10 +368,10 @@ impl<'tcx, Tag> Scalar { target_size: Size, cx: &impl HasDataLayout, ) -> Result> { + assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Raw { data, size } => { assert_eq!(target_size.bytes(), size as u64); - assert_ne!(size, 0, "you should never look at the bits of a ZST"); Scalar::check_data(data, size); Ok(data) } @@ -386,10 +386,10 @@ impl<'tcx, Tag> Scalar { /// It is just a helper for other methods in this file. #[inline] fn to_bits(self, target_size: Size) -> InterpResult<'tcx, u128> { + assert_ne!(target_size.bytes(), 0, "you should never look at the bits of a ZST"); match self { Scalar::Raw { data, size } => { assert_eq!(target_size.bytes(), size as u64); - assert_ne!(size, 0, "you should never look at the bits of a ZST"); Scalar::check_data(data, size); Ok(data) } From 1622b6ef7372c40381914facf8794d851fcd9eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 28 Feb 2020 18:09:29 +0100 Subject: [PATCH 0580/1250] simplify condition in start_executing_work() --- src/librustc_codegen_ssa/back/write.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index bc20ed6f6c5..2cdbb204696 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1244,11 +1244,11 @@ fn start_executing_work( while !codegen_done || running > 0 || (!codegen_aborted - && (!work_items.is_empty() - || !needs_fat_lto.is_empty() - || !needs_thin_lto.is_empty() - || !lto_import_only_modules.is_empty() - || main_thread_worker_state != MainThreadWorkerState::Idle)) + && !(work_items.is_empty() + && needs_fat_lto.is_empty() + && needs_thin_lto.is_empty() + && lto_import_only_modules.is_empty() + && main_thread_worker_state == MainThreadWorkerState::Idle)) { // While there are still CGUs to be codegened, the coordinator has // to decide how to utilize the compiler processes implicit Token: From f037d5ca1bf42108520a1fd3b07c5cec46bc94da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 23:22:19 -0800 Subject: [PATCH 0581/1250] Add more context to E0599 errors Point at the intermediary unfullfilled trait bounds. --- .../infer/error_reporting/note.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 43 ++++++++++++++---- src/librustc_typeck/check/method/suggest.rs | 45 +++++++++++++++++-- .../ui/consts/too_generic_eval_ice.stderr | 4 +- .../derives/derive-assoc-type-not-impl.stderr | 11 ++++- src/test/ui/issues/issue-21596.stderr | 3 +- src/test/ui/issues/issue-31173.rs | 4 ++ src/test/ui/issues/issue-31173.stderr | 19 +++++--- src/test/ui/issues/issue-35677.stderr | 4 +- .../option-as_deref.stderr | 2 +- .../option-as_deref_mut.stderr | 2 +- .../result-as_deref.stderr | 2 +- .../result-as_deref_err.stderr | 2 +- .../result-as_deref_mut.stderr | 2 +- .../result-as_deref_mut_err.stderr | 2 +- .../ui/methods/method-call-err-msg.stderr | 8 +++- src/test/ui/mismatched_types/issue-36053-2.rs | 4 ++ .../ui/mismatched_types/issue-36053-2.stderr | 18 +++++--- .../method-help-unsatisfied-bound.stderr | 5 ++- ...pecialization-trait-not-implemented.stderr | 7 ++- .../suggestions/mut-borrow-needed-by-trait.rs | 4 ++ .../mut-borrow-needed-by-trait.stderr | 16 ++++--- src/test/ui/union/union-derive-clone.stderr | 11 ++++- src/test/ui/unique-object-noncopyable.rs | 4 ++ src/test/ui/unique-object-noncopyable.stderr | 17 ++++++- src/test/ui/unique-pinned-nocopy.rs | 4 ++ src/test/ui/unique-pinned-nocopy.stderr | 13 +++++- 27 files changed, 203 insertions(+), 56 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 7a7cfdecbaf..5c0caa48d0e 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -645,8 +645,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0491, - "in type `{}`, reference has a longer lifetime \ - than the data it references", + "in type `{}`, reference has a longer lifetime than the data it references", self.ty_to_string(ty) ); note_and_explain_region( diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index ea90aef4868..0d6f8e9b7e6 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1404,15 +1404,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // `potentially_unsatisfied_predicates`. return ProbeResult::NoMatch; } else { - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); + self.probe(|_| { + match self.select_trait_candidate(trait_ref) { + Ok(Some(traits::VtableImpl(traits::VtableImplData { + nested, + .. + }))) if !nested.is_empty() => { + for obligation in nested { + // Determine exactly which obligation wasn't met, so + // that we can give more context in the error. + if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; + if let Some(poly_trait_ref) = + obligation.predicate.to_opt_poly_trait_ref() + { + let trait_ref = poly_trait_ref.clone(); + let trait_ref = trait_ref.skip_binder(); + possibly_unsatisfied_predicates + .push(*trait_ref); + } + } + } + } + _ => {} + } + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let trait_ref = self.resolve_vars_if_possible(&trait_ref); + possibly_unsatisfied_predicates.push(trait_ref); + }); } } vec![] diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index ea83b40a1cb..bd87626b438 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -394,6 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.diagnostic().struct_dummy() }; + // FIXME: Unify with unmet bound label. if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { let def_sp = tcx.sess.source_map().def_span(full_sp); @@ -535,16 +536,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !unsatisfied_predicates.is_empty() { + let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path())) + .map(|p| { + let self_ty = p.self_ty(); + match &self_ty.kind { + ty::Adt(def, _) => bound_spans.push(( + self.tcx.sess.source_map().def_span(self.tcx.def_span(def.did)), + format!( + "this type doesn't satisfy the bound `{}`", + p.print_only_trait_path() + ), + )), + ty::Dynamic(preds, _) => { + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push(( + self.tcx + .sess + .source_map() + .def_span(self.tcx.def_span(tr.def_id)), + format!( + "this trait doesn't satisfy the bound `{}`", + p.print_only_trait_path() + ), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + } + _ => {} + }; + format!("`{}: {}`", p.self_ty(), p.print_only_trait_path()) + }) .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 + bound_spans.sort(); + bound_spans.dedup(); // #35677 + for (span, msg) in bound_spans.into_iter() { + err.span_label(span, &msg); + } let bound_list = bound_list.join("\n"); err.note(&format!( - "the method `{}` exists but the following trait bounds \ - were not satisfied:\n{}", + "the method `{}` exists but the following trait bounds were not \ + satisfied:\n{}", item_name, bound_list )); } diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index fd68cb9c6cf..8836de0023c 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -8,8 +8,8 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^ associated item not found in `Foo` | = note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied: - `A : std::marker::Sized` - `B : std::marker::Sized` + `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 diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 2083a1d6522..2746d8b7a14 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,13 +2,20 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ method `clone` not found for this + | ------------------ + | | + | method `clone` not found for this + | this type doesn't satisfy the bound `std::clone::Clone` +... +LL | struct NotClone; + | ---------------- this type doesn't satisfy the bound `std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `Bar : std::clone::Clone` + `Bar: std::clone::Clone` + `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index efde16167b7..d98302552ca 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,8 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8 : std::string::ToString` + `*const u8: std::fmt::Display` + `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs index 26195318380..25be266c528 100644 --- a/src/test/ui/issues/issue-31173.rs +++ b/src/test/ui/issues/issue-31173.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl use std::vec::IntoIter; pub fn get_tok(it: &mut IntoIter) { diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index a614b96ac14..77cb7fb0426 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,5 +1,5 @@ -error[E0271]: type mismatch resolving `, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_` - --> $DIR/issue-31173.rs:10:10 +error[E0271]: type mismatch resolving `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item == &_` + --> $DIR/issue-31173.rs:14:10 | LL | .cloned() | ^^^^^^ expected `u8`, found reference @@ -7,15 +7,20 @@ LL | .cloned() = note: expected type `u8` found reference `&_` -error[E0599]: no method named `collect` found for struct `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope - --> $DIR/issue-31173.rs:14:10 +error[E0599]: no method named `collect` found for struct `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` in the current scope + --> $DIR/issue-31173.rs:18:10 | LL | .collect(); - | ^^^^^^^ method not found in `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` + | ^^^^^^^ method not found in `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` + | + ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL + | +LL | pub struct Cloned { + | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator` + `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index a998f95d306..978221e502f 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -5,8 +5,8 @@ LL | this.is_subset(other) | ^^^^^^^^^ method not found in `&std::collections::HashSet` | = note: the method `is_subset` exists but the following trait bounds were not satisfied: - `T : std::cmp::Eq` - `T : std::hash::Hash` + `T: std::cmp::Eq` + `T: std::hash::Hash` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index f91f6e891ed..c6d9a8415dd 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,7 +5,7 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 583236345ca..ae51052a22c 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index fae11fe62b1..3f7904a8521 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,7 +5,7 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index 1d98361c461..eb591b419ea 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,7 +5,7 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 2c6231fb3b5..115518dcf67 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 950a050ea9f..49f4a16d8ae 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index ab1ef5b9d5a..0c48e93347d 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -35,13 +35,17 @@ error[E0599]: no method named `take` found for struct `Foo` in the current scope --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; - | --------------- method `take` not found for this + | --------------- + | | + | method `take` not found for this + | this type doesn't satisfy the bound `std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `&mut Foo : std::iter::Iterator` + `&mut Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0..36211b4ce70 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl // Regression test for #36053. ICE was caused due to obligations // being added to a special, dedicated fulfillment cx during // a probe. diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index f8d677b99d6..2b8b2d82ec2 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -1,15 +1,21 @@ -error[E0599]: no method named `count` found for struct `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope - --> $DIR/issue-36053-2.rs:7:55 +error[E0599]: no method named `count` found for struct `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` in the current scope + --> $DIR/issue-36053-2.rs:11:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` + | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | + ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL + | +LL | pub struct Filter { + | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator` + `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments - --> $DIR/issue-36053-2.rs:7:32 + --> $DIR/issue-36053-2.rs:11:32 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index bbfb0005056..a7681f9af5b 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -1,11 +1,14 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope --> $DIR/method-help-unsatisfied-bound.rs:5:7 | +LL | struct Foo; + | ----------- this type doesn't satisfy the bound `std::fmt::Debug` +... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` | = note: the method `unwrap` exists but the following trait bounds were not satisfied: - `Foo : std::fmt::Debug` + `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 19809778a5e..2d0caf1dd87 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,13 +2,16 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | struct MyStruct; - | ---------------- method `foo_one` not found for this + | ---------------- + | | + | method `foo_one` not found for this + | this type doesn't satisfy the bound `Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | = note: the method `foo_one` exists but the following trait bounds were not satisfied: - `MyStruct : Foo` + `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `foo_one`, perhaps you need to implement it: candidate #1: `Foo` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index f8b86377187..49a37498fd9 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl use std::env::args; use std::fs::File; use std::io::{stdout, Write, BufWriter}; diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 8dc041ace36..5de7295f4f4 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + --> $DIR/mut-borrow-needed-by-trait.rs:21:29 | LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -8,7 +8,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -17,7 +17,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -26,13 +26,19 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:22:5 + --> $DIR/mut-borrow-needed-by-trait.rs:26:5 | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` + | + ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL + | +LL | pub struct BufWriter { + | ------------------------------ this type doesn't satisfy the bound `std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `std::io::BufWriter<&dyn std::io::Write> : std::io::Write` + `&dyn std::io::Write: std::io::Write` + `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 12b5321331a..289b680a46e 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,13 +11,20 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- method `clone` not found for this + | ----------- + | | + | method `clone` not found for this + | this type doesn't satisfy the bound `std::clone::Clone` +... +LL | struct CloneNoCopy; + | ------------------- this type doesn't satisfy the bound `std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `U5 : std::clone::Clone` + `CloneNoCopy: std::marker::Copy` + `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index dd38a7190aa..bedaf27c2dd 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #![feature(box_syntax)] trait Foo { diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 92cda6482c0..192558f6b09 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,11 +1,24 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-object-noncopyable.rs:24:16 + --> $DIR/unique-object-noncopyable.rs:28:16 | +LL | trait Foo { + | --------- + | | + | this trait doesn't satisfy the bound `std::clone::Clone` + | this trait doesn't satisfy the bound `std::marker::Sized` +... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `std::boxed::Box : std::clone::Clone` + `dyn Foo: std::clone::Clone` + `dyn Foo: std::marker::Sized` + `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 4c30450c704..091b8a43862 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #[derive(Debug)] struct R { b: bool, diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index e5c3eaccbd3..7c1bef07218 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,11 +1,20 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-pinned-nocopy.rs:12:16 + --> $DIR/unique-pinned-nocopy.rs:16:16 | +LL | struct R { + | -------- this type doesn't satisfy the bound `std::clone::Clone` +... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `std::boxed::Box : std::clone::Clone` + `R: std::clone::Clone` + `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 5e8707f39d781df9cc40e81cd1ccdffcfbe5af1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 23:59:21 -0800 Subject: [PATCH 0582/1250] Reduce vebosity of E0599 --- src/librustc_typeck/check/method/probe.rs | 21 ++++++++++--------- src/librustc_typeck/check/method/suggest.rs | 3 +-- .../derives/derive-assoc-type-not-impl.stderr | 6 +----- src/test/ui/issues/issue-21596.stderr | 1 - src/test/ui/issues/issue-31173.stderr | 1 - .../ui/methods/method-call-err-msg.stderr | 1 - .../ui/mismatched_types/issue-36053-2.stderr | 1 - .../suggestions/mut-borrow-needed-by-trait.rs | 4 ---- .../mut-borrow-needed-by-trait.stderr | 14 ++++--------- src/test/ui/union/union-derive-clone.stderr | 6 +----- src/test/ui/unique-object-noncopyable.rs | 4 ---- src/test/ui/unique-object-noncopyable.stderr | 8 +------ src/test/ui/unique-pinned-nocopy.rs | 4 ---- src/test/ui/unique-pinned-nocopy.stderr | 8 +------ 14 files changed, 20 insertions(+), 62 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 0d6f8e9b7e6..1bf173e3b13 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1426,17 +1426,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - _ => {} + _ => { + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let trait_ref = self.resolve_vars_if_possible(&trait_ref); + possibly_unsatisfied_predicates.push(trait_ref); + } } - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); }); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index bd87626b438..c6c404c5c78 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -394,7 +394,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.diagnostic().struct_dummy() }; - // FIXME: Unify with unmet bound label. if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { let def_sp = tcx.sess.source_map().def_span(full_sp); @@ -576,7 +575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); - bound_spans.dedup(); // #35677 + bound_spans.dedup(); for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 2746d8b7a14..0b55b3f2ec9 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,10 +2,7 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ - | | - | method `clone` not found for this - | this type doesn't satisfy the bound `std::clone::Clone` + | ------------------ method `clone` not found for this ... LL | struct NotClone; | ---------------- this type doesn't satisfy the bound `std::clone::Clone` @@ -14,7 +11,6 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `Bar: std::clone::Clone` `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index d98302552ca..10b634b4603 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -8,7 +8,6 @@ LL | println!("{}", z.to_string()); = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: `*const u8: std::fmt::Display` - `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 77cb7fb0426..28b3b872220 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -19,7 +19,6 @@ LL | pub struct Cloned { | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 0c48e93347d..2b683f8aa2a 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,6 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `&mut Foo: std::iter::Iterator` `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 2b8b2d82ec2..98d71b460db 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -10,7 +10,6 @@ LL | pub struct Filter { | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index 49a37498fd9..f8b86377187 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl use std::env::args; use std::fs::File; use std::io::{stdout, Write, BufWriter}; diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 5de7295f4f4..3a9fddc474a 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:29 + --> $DIR/mut-borrow-needed-by-trait.rs:17:29 | LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -8,7 +8,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -17,7 +17,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -26,19 +26,13 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:26:5 + --> $DIR/mut-borrow-needed-by-trait.rs:22:5 | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` - | - ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL - | -LL | pub struct BufWriter { - | ------------------------------ this type doesn't satisfy the bound `std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: `&dyn std::io::Write: std::io::Write` - `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 289b680a46e..c8537afd3bd 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,10 +11,7 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- - | | - | method `clone` not found for this - | this type doesn't satisfy the bound `std::clone::Clone` + | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; | ------------------- this type doesn't satisfy the bound `std::marker::Copy` @@ -24,7 +21,6 @@ LL | let w = u.clone(); | = note: the method `clone` exists but the following trait bounds were not satisfied: `CloneNoCopy: std::marker::Copy` - `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index bedaf27c2dd..dd38a7190aa 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl #![feature(box_syntax)] trait Foo { diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 192558f6b09..1ada663129f 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-object-noncopyable.rs:28:16 + --> $DIR/unique-object-noncopyable.rs:24:16 | LL | trait Foo { | --------- @@ -9,16 +9,10 @@ LL | trait Foo { ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` - | - ::: $SRC_DIR/liballoc/boxed.rs:LL:COL - | -LL | pub struct Box(Unique); - | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `dyn Foo: std::clone::Clone` `dyn Foo: std::marker::Sized` - `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 091b8a43862..4c30450c704 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl #[derive(Debug)] struct R { b: bool, diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 7c1bef07218..2557ea8acb8 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,20 +1,14 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-pinned-nocopy.rs:16:16 + --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { | -------- this type doesn't satisfy the bound `std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` - | - ::: $SRC_DIR/liballoc/boxed.rs:LL:COL - | -LL | pub struct Box(Unique); - | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `R: std::clone::Clone` - `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 8993b99ae28a1f8e3c11231a17e645feee66ea2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 01:35:18 -0800 Subject: [PATCH 0583/1250] On single local candidate, use span label --- src/librustc_typeck/check/method/suggest.rs | 33 +++++++++++++------ .../associated-const-no-item.stderr | 5 +-- src/test/ui/auto-ref-slice-plus-ref.stderr | 20 ++++++----- ...e-21659-show-relevant-trait-impls-3.stderr | 5 +-- .../no-method-suggested-traits.stderr | 30 ++++++++++------- src/test/ui/issues/issue-5153.stderr | 5 +-- src/test/ui/issues/issue-57362-1.stderr | 5 +-- src/test/ui/issues/issue-57362-2.stderr | 5 +-- src/test/ui/never_type/issue-2149.stderr | 5 +-- src/test/ui/object-pointer-types.stderr | 10 +++--- ...at-arbitrary-self-type-trait-method.stderr | 6 ++-- ...pecialization-trait-not-implemented.stderr | 5 +-- src/test/ui/traits/trait-item-privacy.stderr | 15 +++++---- .../trivial-bounds/trivial-bounds-leak.stderr | 5 +-- 14 files changed, 95 insertions(+), 59 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index c6c404c5c78..3fa5d4baa76 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -846,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let message = |action| { format!( "the following {traits_define} an item `{name}`, perhaps you need to {action} \ - {one_of_them}:", + {one_of_them}:", traits_define = if candidates.len() == 1 { "trait defines" } else { "traits define" }, action = action, @@ -944,19 +944,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !suggested { - let mut msg = message(if let Some(param) = param_type { + let action = if let Some(param) = param_type { format!("restrict type parameter `{}` with", param) } else { "implement".to_string() - }); - for (i, trait_info) in candidates.iter().enumerate() { - msg.push_str(&format!( - "\ncandidate #{}: `{}`", - i + 1, - self.tcx.def_path_str(trait_info.def_id), - )); + }; + let mut use_note = true; + if let [trait_info] = &candidates[..] { + if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { + err.span_label( + self.tcx.sess.source_map().def_span(span), + &format!("this trait defines an item `{}`", item_name), + ); + use_note = false + } + } + if use_note { + let mut msg = message(action); + for (i, trait_info) in candidates.iter().enumerate() { + msg.push_str(&format!( + "\ncandidate #{}: `{}`", + i + 1, + self.tcx.def_path_str(trait_info.def_id), + )); + } + err.note(&msg[..]); } - err.note(&msg[..]); } } } diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index d96cf67b875..e6765bc3dd6 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,12 +1,13 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope --> $DIR/associated-const-no-item.rs:5:23 | +LL | trait Foo { + | --------- this trait defines an item `ID` +... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `ID`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index a0739a7a90b..3e14dc80122 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -3,40 +3,44 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege | LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` +... +LL | trait MyIter { + | ------------ this trait defines an item `test_mut` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test_mut`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:8:7 | LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:10:11 | LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:11:12 | LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 57417975474..32a677a7d7f 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | +LL | trait Foo { + | ------------ this trait defines an item `foo` +... LL | struct Bar; | ----------- method `foo` not found for this ... @@ -8,8 +11,6 @@ LL | f1.foo(1usize); | ^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index da25617e187..8025c12047f 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -122,62 +122,68 @@ LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); error[E0599]: no method named `method2` found for type `u64` in the current scope --> $DIR/no-method-suggested-traits.rs:45:10 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope --> $DIR/no-method-suggested-traits.rs:47:44 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:50:37 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:52:71 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:54:40 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:56:74 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method3` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:59:9 diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 4680c8b131c..730da21ddf5 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -1,12 +1,13 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope --> $DIR/issue-5153.rs:10:27 | +LL | trait Foo { + | --------- this trait defines an item `foo` +... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index ad596db13cc..3a5189b132d 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,13 +1,14 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | +LL | trait Trait { + | ----------- this trait defines an item `f` +... LL | a.f(); | ^ method not found in `fn(&u8)` | = note: `a` is a function, perhaps you wish to call it = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `f`, perhaps you need to implement it: - candidate #1: `Trait` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 3528084f6ce..e2d80b3b4df 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,12 +1,13 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | +LL | trait X { + | ------- this trait defines an item `make_g` +... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `make_g`, perhaps you need to implement it: - candidate #1: `X` error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 9645244751d..4fadf49bd6d 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -9,12 +9,13 @@ LL | for elt in self { r = r + f(*elt); } error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope --> $DIR/issue-2149.rs:13:12 | +LL | trait VecMonad { + | ----------------- this trait defines an item `bind` +... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `bind`, perhaps you need to implement it: - candidate #1: `VecMonad` error: aborting due to 2 previous errors diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 855894b4495..5ca326bca31 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -1,22 +1,24 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:11:7 | +LL | trait Foo { + | --------- this trait defines an item `owned` +... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `owned`, perhaps you need to implement it: - candidate #1: `Foo` error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:17:7 | +LL | trait Foo { + | --------- this trait defines an item `owned` +... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `owned`, perhaps you need to implement it: - candidate #1: `Foo` error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope --> $DIR/object-pointer-types.rs:23:7 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 28a7b68a682..8ed2b8b5c95 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -2,7 +2,9 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 | LL | trait B { fn foo(self: Box); } - | --- the method is available for `std::boxed::Box` here + | ------- --- the method is available for `std::boxed::Box` here + | | + | this trait defines an item `foo` LL | struct A; | --------- method `foo` not found for this ... @@ -10,8 +12,6 @@ LL | A.foo() | ^^^ method not found in `A` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `B` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 2d0caf1dd87..ccbb2aae05d 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope --> $DIR/specialization-trait-not-implemented.rs:22:29 | +LL | trait Foo { + | --------- this trait defines an item `foo_one` +... LL | struct MyStruct; | ---------------- | | @@ -13,8 +16,6 @@ LL | println!("{}", MyStruct.foo_one()); = note: the method `foo_one` exists but the following trait bounds were not satisfied: `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo_one`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 072328ab50c..5b7f0a8ce5f 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -4,12 +4,13 @@ error[E0599]: no method named `a` found for struct `S` in the current scope LL | struct S; | --------- method `a` not found for this ... +LL | trait A { + | ------- this trait defines an item `a` +... LL | S.a(); | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `a`, perhaps you need to implement it: - candidate #1: `method::A` error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:68:7 @@ -45,12 +46,13 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t LL | struct S; | --------- function or associated item `a` not found for this ... +LL | trait A { + | ------- this trait defines an item `a` +... LL | S::a(&S); | ^ function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `a`, perhaps you need to implement it: - candidate #1: `method::A` error[E0599]: no function or associated item named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:80:8 @@ -79,12 +81,13 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s LL | struct S; | --------- associated item `A` not found for this ... +LL | trait A { + | ------- this trait defines an item `A` +... LL | S::A; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `A`, perhaps you need to implement it: - candidate #1: `assoc_const::A` error[E0599]: no associated item named `B` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:98:8 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index acf309ac608..7ed24591e66 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -11,12 +11,13 @@ LL | fn cant_return_str() -> str { error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | +LL | pub trait Foo { + | ------------- this trait defines an item `test` +... LL | 3i32.test(); | ^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `Foo` error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 From ad4777dbca1d4d1b052db01b1191862c9fbbad64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 02:13:30 -0800 Subject: [PATCH 0584/1250] Deduplicate information in E0599 --- src/librustc_typeck/check/method/suggest.rs | 54 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 4 +- src/test/ui/issues/issue-31173.stderr | 5 +- .../ui/methods/method-call-err-msg.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 3 +- .../method-help-unsatisfied-bound.stderr | 5 +- ...pecialization-trait-not-implemented.stderr | 4 +- src/test/ui/union/union-derive-clone.stderr | 4 +- src/test/ui/unique-object-noncopyable.stderr | 7 +-- src/test/ui/unique-pinned-nocopy.stderr | 4 +- 10 files changed, 46 insertions(+), 48 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 3fa5d4baa76..8eb42f01984 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,16 +538,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .map(|p| { + .filter_map(|p| { let self_ty = p.self_ty(); match &self_ty.kind { - ty::Adt(def, _) => bound_spans.push(( - self.tcx.sess.source_map().def_span(self.tcx.def_span(def.did)), - format!( - "this type doesn't satisfy the bound `{}`", - p.print_only_trait_path() - ), - )), + ty::Adt(def, _) => { + bound_spans.push(( + self.tcx + .sess + .source_map() + .def_span(self.tcx.def_span(def.did)), + format!( + "the method `{}` exists but this type doesn't satisfy \ + the bound `{}: {}`", + item_name, + p.self_ty(), + p.print_only_trait_path() + ), + )); + None + } ty::Dynamic(preds, _) => { for pred in *preds.skip_binder() { match pred { @@ -558,7 +567,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .source_map() .def_span(self.tcx.def_span(tr.def_id)), format!( - "this trait doesn't satisfy the bound `{}`", + "the method `{}` exists but this trait \ + doesn't satisfy the bound `{}: {}`", + item_name, + p.self_ty(), p.print_only_trait_path() ), )), @@ -566,10 +578,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::ExistentialPredicate::AutoTrait(_) => {} } } + None } - _ => {} - }; - format!("`{}: {}`", p.self_ty(), p.print_only_trait_path()) + _ => Some(format!( + "`{}: {}`", + p.self_ty(), + p.print_only_trait_path() + )), + } }) .collect::>(); bound_list.sort(); @@ -579,12 +595,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } - let bound_list = bound_list.join("\n"); - err.note(&format!( - "the method `{}` exists but the following trait bounds were not \ - satisfied:\n{}", - item_name, bound_list - )); + if !bound_list.is_empty() { + let bound_list = bound_list.join("\n"); + err.note(&format!( + "the method `{}` exists but the following trait bounds were not \ + satisfied:\n{}", + item_name, bound_list + )); + } } if actual.is_numeric() && actual.is_fresh() { diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 0b55b3f2ec9..fd74d992299 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,13 +5,11 @@ LL | struct Bar { | ------------------ method `clone` not found for this ... LL | struct NotClone; - | ---------------- this type doesn't satisfy the bound `std::clone::Clone` + | ---------------- the method `clone` exists but this type doesn't satisfy the bound `NotClone: std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 28b3b872220..4a5940f610e 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,10 +16,7 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` - | - = note: the method `collect` exists but the following trait bounds were not satisfied: - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- the method `collect` exists but this type doesn't satisfy the bound `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 2b683f8aa2a..aa38e4da018 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -38,13 +38,11 @@ LL | pub struct Foo; | --------------- | | | method `take` not found for this - | this type doesn't satisfy the bound `std::iter::Iterator` + | the method `take` exists but this type doesn't satisfy the bound `Foo: std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | - = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 98d71b460db..dc0bd310de8 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -7,11 +7,10 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` + | ----------------------- the method `count` exists but this type doesn't satisfy the bound `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index a7681f9af5b..e95141b393a 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,13 +2,10 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; - | ----------- this type doesn't satisfy the bound `std::fmt::Debug` + | ----------- the method `unwrap` exists but this type doesn't satisfy the bound `Foo: std::fmt::Debug` ... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` - | - = note: the method `unwrap` exists but the following trait bounds were not satisfied: - `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index ccbb2aae05d..2738bac8cc8 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,13 +8,11 @@ LL | struct MyStruct; | ---------------- | | | method `foo_one` not found for this - | this type doesn't satisfy the bound `Foo` + | the method `foo_one` exists but this type doesn't satisfy the bound `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | - = note: the method `foo_one` exists but the following trait bounds were not satisfied: - `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index c8537afd3bd..c0d99c56cc0 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -14,13 +14,11 @@ LL | union U5 { | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; - | ------------------- this type doesn't satisfy the bound `std::marker::Copy` + | ------------------- the method `clone` exists but this type doesn't satisfy the bound `CloneNoCopy: std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 1ada663129f..b786a3d6d86 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -4,15 +4,12 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box LL | trait Foo { | --------- | | - | this trait doesn't satisfy the bound `std::clone::Clone` - | this trait doesn't satisfy the bound `std::marker::Sized` + | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::clone::Clone` + | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::marker::Sized` ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - `dyn Foo: std::marker::Sized` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 2557ea8acb8..26b82ecda48 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,13 +2,11 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in t --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { - | -------- this type doesn't satisfy the bound `std::clone::Clone` + | -------- the method `clone` exists but this type doesn't satisfy the bound `R: std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 8119d0853d6f227c5e36ab423b6e2f22604fa87d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 16:35:47 -0800 Subject: [PATCH 0585/1250] Track all predicates in errors, not just trait obligations Surface associated type projection bounds that could not be fulfilled in E0599 errors. Always present the list of unfulfilled trait bounds, regardless of whether we're pointing at the ADT or trait that didn't satisfy it. --- src/librustc/traits/mod.rs | 14 +++ src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 80 ++++++++--------- src/librustc_typeck/check/method/suggest.rs | 87 +++++++++---------- .../derives/derive-assoc-type-not-impl.stderr | 4 +- src/test/ui/issues/issue-31173.stderr | 6 +- .../option-as_deref.stderr | 1 + .../option-as_deref_mut.stderr | 1 + .../result-as_deref.stderr | 1 + .../result-as_deref_err.stderr | 1 + .../result-as_deref_mut.stderr | 1 + .../result-as_deref_mut_err.stderr | 1 + .../ui/methods/method-call-err-msg.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 6 +- .../method-help-unsatisfied-bound.stderr | 5 +- ...pecialization-trait-not-implemented.stderr | 4 +- src/test/ui/union/union-derive-clone.stderr | 4 +- src/test/ui/unique-object-noncopyable.stderr | 7 +- src/test/ui/unique-pinned-nocopy.stderr | 4 +- 19 files changed, 134 insertions(+), 103 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index b05bd26f048..77c612cf34a 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -581,6 +581,20 @@ impl<'tcx, N> Vtable<'tcx, N> { } } + pub fn borrow_nested_obligations(&self) -> &[N] { + match &self { + VtableImpl(i) => &i.nested[..], + VtableParam(n) => &n[..], + VtableBuiltin(i) => &i.nested[..], + VtableAutoImpl(d) => &d.nested[..], + VtableClosure(c) => &c.nested[..], + VtableGenerator(c) => &c.nested[..], + VtableObject(d) => &d.nested[..], + VtableFnPointer(d) => &d.nested[..], + VtableTraitAlias(d) => &d.nested[..], + } + } + pub fn map(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index de824648a25..fd85397760a 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -14,7 +14,7 @@ use crate::check::FnCtxt; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> { // could lead to matches if satisfied, and a list of not-in-scope traits which may work. pub struct NoMatchData<'tcx> { pub static_candidates: Vec, - pub unsatisfied_predicates: Vec>, + pub unsatisfied_predicates: Vec>, pub out_of_scope_traits: Vec, pub lev_candidate: Option, pub mode: probe::Mode, @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec, - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec>, out_of_scope_traits: Vec, lev_candidate: Option, mode: probe::Mode, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1bf173e3b13..4f729c593cb 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,8 +14,7 @@ use rustc::session::config::nightly_options; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ - self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, - WithConstness, + self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -78,7 +77,7 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec>, is_suggestion: IsSuggestion, } @@ -1224,7 +1223,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probes: ProbesIter, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec>, unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, ) -> Option> where @@ -1343,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1398,47 +1397,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let predicate = trait_ref.without_const().to_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { - if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { + if self.probe(|_| { + match self.select_trait_candidate(trait_ref) { + Err(_) => return true, + Ok(Some(vtable)) + if !vtable.borrow_nested_obligations().is_empty() => + { + for obligation in vtable.borrow_nested_obligations() { + // Determine exactly which obligation wasn't met, so + // that we can give more context in the error. + if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; + let o = self.resolve_vars_if_possible(obligation); + possibly_unsatisfied_predicates.push(o.predicate); + } + } + } + _ => { + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let predicate = self.resolve_vars_if_possible(&predicate); + possibly_unsatisfied_predicates.push(predicate); + } + } + false + }) { // This candidate's primary obligation doesn't even // select - don't bother registering anything in // `potentially_unsatisfied_predicates`. return ProbeResult::NoMatch; - } else { - self.probe(|_| { - match self.select_trait_candidate(trait_ref) { - Ok(Some(traits::VtableImpl(traits::VtableImplData { - nested, - .. - }))) if !nested.is_empty() => { - for obligation in nested { - // Determine exactly which obligation wasn't met, so - // that we can give more context in the error. - if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; - if let Some(poly_trait_ref) = - obligation.predicate.to_opt_poly_trait_ref() - { - let trait_ref = poly_trait_ref.clone(); - let trait_ref = trait_ref.skip_binder(); - possibly_unsatisfied_predicates - .push(*trait_ref); - } - } - } - } - _ => { - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); - } - } - }); } } vec![] @@ -1455,9 +1447,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - if let &ty::Predicate::Trait(ref pred, _) = &o.predicate { - possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); - } + possibly_unsatisfied_predicates.push(o.predicate); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 8eb42f01984..6edceeb15b3 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -535,57 +535,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !unsatisfied_predicates.is_empty() { + let def_span = + |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .filter_map(|p| { - let self_ty = p.self_ty(); - match &self_ty.kind { - ty::Adt(def, _) => { - bound_spans.push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(def.did)), - format!( - "the method `{}` exists but this type doesn't satisfy \ - the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )); - None - } - ty::Dynamic(preds, _) => { - for pred in *preds.skip_binder() { - match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(tr.def_id)), - format!( - "the method `{}` exists but this trait \ - doesn't satisfy the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} + .filter_map(|pred| match pred { + ty::Predicate::Projection(pred) => { + // `::Item = String`. + let trait_ref = + pred.skip_binder().projection_ty.trait_ref(self.tcx); + let assoc = self + .tcx + .associated_item(pred.skip_binder().projection_ty.item_def_id); + let ty = pred.skip_binder().ty; + Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty)) + } + ty::Predicate::Trait(poly_trait_ref, _) => { + let p = poly_trait_ref.skip_binder().trait_ref; + let self_ty = p.self_ty(); + let path = p.print_only_trait_path(); + match &self_ty.kind { + ty::Adt(def, _) => { + // Point at the type that couldn't satisfy the bound. + bound_spans.push(( + def_span(def.did), + format!("doesn't satisfy `{}: {}`", self_ty, path), + )); + } + ty::Dynamic(preds, _) => { + // Point at the trait object that couldn't satisfy the bound. + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push(( + def_span(tr.def_id), + format!( + "doesn't satisfy `{}: {}`", + self_ty, path + ), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } } } - None + _ => {} } - _ => Some(format!( - "`{}: {}`", - p.self_ty(), - p.print_only_trait_path() - )), + Some(format!("`{}: {}`", self_ty, path)) } + _ => None, }) .collect::>(); bound_list.sort(); diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index fd74d992299..3ed726dea35 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,11 +5,13 @@ LL | struct Bar { | ------------------ method `clone` not found for this ... LL | struct NotClone; - | ---------------- the method `clone` exists but this type doesn't satisfy the bound `NotClone: std::clone::Clone` + | ---------------- doesn't satisfy `NotClone: std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 4a5940f610e..d5e3cf48f38 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,7 +16,11 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- the method `collect` exists but this type doesn't satisfy the bound `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | + = note: the method `collect` exists but the following trait bounds were not satisfied: + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index c6d9a8415dd..63359be56bf 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index ae51052a22c..b01b3448e17 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 3f7904a8521..75482841987 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index eb591b419ea..cf31bc4b56b 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 115518dcf67..586b3555455 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 49f4a16d8ae..fd0e43d7dbc 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index aa38e4da018..b0d747d201d 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -38,11 +38,13 @@ LL | pub struct Foo; | --------------- | | | method `take` not found for this - | the method `take` exists but this type doesn't satisfy the bound `Foo: std::iter::Iterator` + | doesn't satisfy `Foo: std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | + = note: the method `take` exists but the following trait bounds were not satisfied: + `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index dc0bd310de8..5f3353c89cc 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -7,10 +7,12 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- the method `count` exists but this type doesn't satisfy the bound `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index e95141b393a..5ab191b9270 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,10 +2,13 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; - | ----------- the method `unwrap` exists but this type doesn't satisfy the bound `Foo: std::fmt::Debug` + | ----------- doesn't satisfy `Foo: std::fmt::Debug` ... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` + | + = note: the method `unwrap` exists but the following trait bounds were not satisfied: + `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 2738bac8cc8..14f37150c80 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,11 +8,13 @@ LL | struct MyStruct; | ---------------- | | | method `foo_one` not found for this - | the method `foo_one` exists but this type doesn't satisfy the bound `MyStruct: Foo` + | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | + = note: the method `foo_one` exists but the following trait bounds were not satisfied: + `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index c0d99c56cc0..2051ea33391 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -14,11 +14,13 @@ LL | union U5 { | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; - | ------------------- the method `clone` exists but this type doesn't satisfy the bound `CloneNoCopy: std::marker::Copy` + | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `CloneNoCopy: std::marker::Copy` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index b786a3d6d86..f230d0d14d2 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -4,12 +4,15 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box LL | trait Foo { | --------- | | - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::clone::Clone` - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::marker::Sized` + | doesn't satisfy `dyn Foo: std::clone::Clone` + | doesn't satisfy `dyn Foo: std::marker::Sized` ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `dyn Foo: std::clone::Clone` + `dyn Foo: std::marker::Sized` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 26b82ecda48..12d719a1027 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,11 +2,13 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in t --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { - | -------- the method `clone` exists but this type doesn't satisfy the bound `R: std::clone::Clone` + | -------- doesn't satisfy `R: std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `R: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 9a64c3f5cb33d8504b824ae67dcf8482588586f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 17:53:25 -0800 Subject: [PATCH 0586/1250] Show information of chain of bound obligations When the obligation that couldn't be fulfilled is specific to a nested obligation, maintain both the nested and parent obligations around for more accurate and detailed error reporting. --- src/librustc_typeck/check/method/mod.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 31 ++++--- src/librustc_typeck/check/method/suggest.rs | 82 +++++++++++-------- .../derives/derive-assoc-type-not-impl.stderr | 7 +- src/test/ui/issues/issue-21596.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 7 +- .../ui/methods/method-call-err-msg.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 6 +- .../mut-borrow-needed-by-trait.stderr | 7 +- src/test/ui/union/union-derive-clone.stderr | 7 +- src/test/ui/unique-object-noncopyable.stderr | 9 +- src/test/ui/unique-pinned-nocopy.stderr | 7 +- 12 files changed, 111 insertions(+), 60 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index fd85397760a..b09522bbd33 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> { // could lead to matches if satisfied, and a list of not-in-scope traits which may work. pub struct NoMatchData<'tcx> { pub static_candidates: Vec, - pub unsatisfied_predicates: Vec>, + pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, pub out_of_scope_traits: Vec, pub lev_candidate: Option, pub mode: probe::Mode, @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec, - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, out_of_scope_traits: Vec, lev_candidate: Option, mode: probe::Mode, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4f729c593cb..3e2826907b8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -77,7 +77,7 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, is_suggestion: IsSuggestion, } @@ -1223,7 +1223,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probes: ProbesIter, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec<( + ty::Predicate<'tcx>, + Option>, + )>, unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, ) -> Option> where @@ -1342,7 +1345,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec<( + ty::Predicate<'tcx>, + Option>, + )>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1409,20 +1415,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if !self.predicate_may_hold(&obligation) { result = ProbeResult::NoMatch; let o = self.resolve_vars_if_possible(obligation); - possibly_unsatisfied_predicates.push(o.predicate); + let predicate = + self.resolve_vars_if_possible(&predicate); + let p = if predicate == o.predicate { + // Avoid "`MyStruct: Foo` which is required by + // `MyStruct: Foo`" in E0599. + None + } else { + Some(predicate) + }; + possibly_unsatisfied_predicates.push((o.predicate, p)); } } } _ => { // Some nested subobligation of this predicate // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? result = ProbeResult::NoMatch; let predicate = self.resolve_vars_if_possible(&predicate); - possibly_unsatisfied_predicates.push(predicate); + possibly_unsatisfied_predicates.push((predicate, None)); } } false @@ -1447,7 +1458,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push(o.predicate); + possibly_unsatisfied_predicates.push((o.predicate, None)); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6edceeb15b3..973f8208f16 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,9 +538,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; - let mut bound_list = unsatisfied_predicates - .iter() - .filter_map(|pred| match pred { + let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str| { + match &self_ty.kind { + ty::Adt(def, _) => { + // Point at the type that couldn't satisfy the bound. + bound_spans.push(( + def_span(def.did), + format!("doesn't satisfy {}", obligation), + )); + } + ty::Dynamic(preds, _) => { + // Point at the trait object that couldn't satisfy the bound. + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans.push(( + def_span(tr.def_id), + format!("doesn't satisfy {}", obligation), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + } + _ => {} + } + }; + let mut format_pred = |pred| { + match pred { ty::Predicate::Projection(pred) => { // `::Item = String`. let trait_ref = @@ -549,44 +573,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty)) + let obligation = + format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + bound_span_label(trait_ref.self_ty(), &obligation); + Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { let p = poly_trait_ref.skip_binder().trait_ref; let self_ty = p.self_ty(); let path = p.print_only_trait_path(); - match &self_ty.kind { - ty::Adt(def, _) => { - // Point at the type that couldn't satisfy the bound. - bound_spans.push(( - def_span(def.did), - format!("doesn't satisfy `{}: {}`", self_ty, path), - )); - } - ty::Dynamic(preds, _) => { - // Point at the trait object that couldn't satisfy the bound. - for pred in *preds.skip_binder() { - match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push(( - def_span(tr.def_id), - format!( - "doesn't satisfy `{}: {}`", - self_ty, path - ), - )), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} - } - } - } - _ => {} - } - Some(format!("`{}: {}`", self_ty, path)) + let obligation = format!("`{}: {}`", self_ty, path); + bound_span_label(self_ty, &obligation); + Some(obligation) } _ => None, + } + }; + let mut bound_list = unsatisfied_predicates + .iter() + .filter_map(|(pred, parent_pred)| { + format_pred(*pred).map(|pred| match parent_pred { + None => pred, + Some(parent_pred) => match format_pred(*parent_pred) { + None => pred, + Some(parent_pred) => { + format!("{} which is required by {}", pred, parent_pred) + } + }, + }) }) - .collect::>(); + .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 3ed726dea35..e837c7721af 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,7 +2,10 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ method `clone` not found for this + | ------------------ + | | + | method `clone` not found for this + | doesn't satisfy `Bar: std::clone::Clone` ... LL | struct NotClone; | ---------------- doesn't satisfy `NotClone: std::clone::Clone` @@ -11,7 +14,7 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` + `NotClone: std::clone::Clone` which is required by `Bar: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index 10b634b4603..bbd16618049 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,7 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8: std::fmt::Display` + `*const u8: std::fmt::Display` which is required by `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index d5e3cf48f38..9100f2c3a93 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -17,10 +17,13 @@ LL | .collect(); | LL | pub struct Cloned { | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` +... +LL | pub struct TakeWhile { + | -------------------------- doesn't satisfy `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b0d747d201d..b4e54ab7783 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,7 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 5f3353c89cc..5899dfffa41 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -10,9 +10,9 @@ LL | pub struct Filter { | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 3a9fddc474a..5d297728eca 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -30,9 +30,14 @@ error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<& | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` + | + ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL + | +LL | pub struct BufWriter { + | ------------------------------ doesn't satisfy `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `&dyn std::io::Write: std::io::Write` + `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 2051ea33391..456e1cd83ef 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,7 +11,10 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- method `clone` not found for this + | ----------- + | | + | method `clone` not found for this + | doesn't satisfy `U5: std::clone::Clone` ... LL | struct CloneNoCopy; | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy` @@ -20,7 +23,7 @@ LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` + `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index f230d0d14d2..c3be38e1cf1 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -9,10 +9,15 @@ LL | trait Foo { ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - `dyn Foo: std::marker::Sized` + `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 12d719a1027..fb2f4c01b63 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -6,9 +6,14 @@ LL | struct R { ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` + `R: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 89e96e9bc575b370c7b55055aad28bebd14e8dfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:06:03 -0800 Subject: [PATCH 0587/1250] Point at closure definitions --- src/librustc_typeck/check/method/suggest.rs | 41 +++++++++++-------- src/test/ui/issues/issue-31173.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 7 +++- .../mut-borrow-needed-by-trait.stderr | 2 +- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 973f8208f16..5d4a143598f 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,28 +538,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; - let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str| { + let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { + let msg = format!( + "doesn't satisfy {}", + if obligation.len() > 50 { quiet } else { obligation } + ); match &self_ty.kind { - ty::Adt(def, _) => { - // Point at the type that couldn't satisfy the bound. - bound_spans.push(( - def_span(def.did), - format!("doesn't satisfy {}", obligation), - )); - } + // Point at the type that couldn't satisfy the bound. + ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)), + // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { - // Point at the trait object that couldn't satisfy the bound. for pred in *preds.skip_binder() { match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans.push(( - def_span(tr.def_id), - format!("doesn't satisfy {}", obligation), - )), + ty::ExistentialPredicate::Trait(tr) => { + bound_spans.push((def_span(tr.def_id), msg.clone())) + } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => {} } } } + // Point at the closure that couldn't satisfy the bound. + ty::Closure(def_id, _) => bound_spans + .push((def_span(*def_id), format!("doesn't satisfy {}", quiet))), _ => {} } }; @@ -573,9 +574,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let obligation = - format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); - bound_span_label(trait_ref.self_ty(), &obligation); + let msg = format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let quiet = format!( + "`<_ as {}>::{} = {}`", + trait_ref.print_only_trait_path(), + assoc.ident, + ty + ); + bound_span_label(trait_ref.self_ty(), &msg, &quiet); Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { @@ -583,7 +589,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let self_ty = p.self_ty(); let path = p.print_only_trait_path(); let obligation = format!("`{}: {}`", self_ty, path); - bound_span_label(self_ty, &obligation); + let quiet = format!("`_: {}`", path); + bound_span_label(self_ty, &obligation, &quiet); Some(obligation) } _ => None, diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 9100f2c3a93..ca8e63550d6 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,10 +16,10 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- doesn't satisfy `_: std::iter::Iterator` ... LL | pub struct TakeWhile { - | -------------------------- doesn't satisfy `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 5899dfffa41..49e61cd2327 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -2,12 +2,15 @@ error[E0599]: no method named `count` found for struct `std::iter::Filter $DIR/issue-36053-2.rs:11:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | -------------- ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | | + | doesn't satisfy `<_ as std::ops::FnOnce<(&&str,)>>::Output = bool` + | doesn't satisfy `_: std::ops::FnMut<(&&str,)>` | ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + | ----------------------- doesn't satisfy `_: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 5d297728eca..16a03c42a4d 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -34,7 +34,7 @@ LL | writeln!(fp, "hello world").unwrap(); ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL | LL | pub struct BufWriter { - | ------------------------------ doesn't satisfy `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` + | ------------------------------ doesn't satisfy `_: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` From 0387f0d19b3e439b4f361cecd5be8977665f35c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:20:23 -0800 Subject: [PATCH 0588/1250] Mention the full path of the implementing trait --- src/librustc_typeck/check/method/suggest.rs | 11 ++++++++--- .../associated-const/associated-const-no-item.stderr | 2 +- src/test/ui/auto-ref-slice-plus-ref.stderr | 8 ++++---- .../issue-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/no-method-suggested-traits.stderr | 12 ++++++------ src/test/ui/issues/issue-5153.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 2 +- src/test/ui/issues/issue-57362-2.stderr | 2 +- src/test/ui/never_type/issue-2149.stderr | 2 +- src/test/ui/object-pointer-types.stderr | 4 ++-- .../point-at-arbitrary-self-type-trait-method.stderr | 2 +- .../specialization-trait-not-implemented.stderr | 2 +- src/test/ui/traits/trait-item-privacy.stderr | 6 +++--- .../ui/trivial-bounds/trivial-bounds-leak.stderr | 2 +- 14 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5d4a143598f..af7f63772c3 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -574,14 +574,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let msg = format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let obligation = + format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); let quiet = format!( "`<_ as {}>::{} = {}`", trait_ref.print_only_trait_path(), assoc.ident, ty ); - bound_span_label(trait_ref.self_ty(), &msg, &quiet); + bound_span_label(trait_ref.self_ty(), &obligation, &quiet); Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { @@ -994,7 +995,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { err.span_label( self.tcx.sess.source_map().def_span(span), - &format!("this trait defines an item `{}`", item_name), + &format!( + "`{}` defines an item `{}`", + self.tcx.def_path_str(trait_info.def_id), + item_name + ), ); use_note = false } diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index e6765bc3dd6..02d4866e3f5 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current --> $DIR/associated-const-no-item.rs:5:23 | LL | trait Foo { - | --------- this trait defines an item `ID` + | --------- `Foo` defines an item `ID` ... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 3e14dc80122..26b2c44fdd9 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -5,7 +5,7 @@ LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` ... LL | trait MyIter { - | ------------ this trait defines an item `test_mut` + | ------------ `MyIter` defines an item `test_mut` | = help: items from traits can only be used if the trait is implemented and in scope @@ -16,7 +16,7 @@ LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope @@ -27,7 +27,7 @@ LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope @@ -38,7 +38,7 @@ LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 32a677a7d7f..cdcf84a7063 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | trait Foo { - | ------------ this trait defines an item `foo` + | ------------ `Foo` defines an item `foo` ... LL | struct Bar; | ----------- method `foo` not found for this diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 8025c12047f..b3da4a6ead6 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -123,7 +123,7 @@ error[E0599]: no method named `method2` found for type `u64` in the current scop --> $DIR/no-method-suggested-traits.rs:45:10 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` @@ -134,7 +134,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:47:44 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` @@ -145,7 +145,7 @@ error[E0599]: no method named `method2` found for struct `no_method_suggested_tr --> $DIR/no-method-suggested-traits.rs:50:37 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` @@ -156,7 +156,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:52:71 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` @@ -167,7 +167,7 @@ error[E0599]: no method named `method2` found for enum `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:54:40 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` @@ -178,7 +178,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:56:74 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 730da21ddf5..bf48c662383 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the curren --> $DIR/issue-5153.rs:10:27 | LL | trait Foo { - | --------- this trait defines an item `foo` + | --------- `Foo` defines an item `foo` ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 3a5189b132d..4eaa5adbea4 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current --> $DIR/issue-57362-1.rs:20:7 | LL | trait Trait { - | ----------- this trait defines an item `f` + | ----------- `Trait` defines an item `f` ... LL | a.f(); | ^ method not found in `fn(&u8)` diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index e2d80b3b4df..ce689334cc1 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer --> $DIR/issue-57362-2.rs:22:25 | LL | trait X { - | ------- this trait defines an item `make_g` + | ------- `X` defines an item `make_g` ... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 4fadf49bd6d..b92ab5dde27 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -10,7 +10,7 @@ error[E0599]: no method named `bind` found for array `[&str; 1]` in the current --> $DIR/issue-2149.rs:13:12 | LL | trait VecMonad { - | ----------------- this trait defines an item `bind` + | ----------------- `VecMonad` defines an item `bind` ... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 5ca326bca31..7364ead97f6 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the curr --> $DIR/object-pointer-types.rs:11:7 | LL | trait Foo { - | --------- this trait defines an item `owned` + | --------- `Foo` defines an item `owned` ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` @@ -13,7 +13,7 @@ error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` --> $DIR/object-pointer-types.rs:17:7 | LL | trait Foo { - | --------- this trait defines an item `owned` + | --------- `Foo` defines an item `owned` ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 8ed2b8b5c95..fefa6dab15a 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope LL | trait B { fn foo(self: Box); } | ------- --- the method is available for `std::boxed::Box` here | | - | this trait defines an item `foo` + | `B` defines an item `foo` LL | struct A; | --------- method `foo` not found for this ... diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 14f37150c80..93a5f3051fe 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | trait Foo { - | --------- this trait defines an item `foo_one` + | --------- `Foo` defines an item `foo_one` ... LL | struct MyStruct; | ---------------- diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 5b7f0a8ce5f..23f08f37826 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -5,7 +5,7 @@ LL | struct S; | --------- method `a` not found for this ... LL | trait A { - | ------- this trait defines an item `a` + | ------- `method::A` defines an item `a` ... LL | S.a(); | ^ method not found in `S` @@ -47,7 +47,7 @@ LL | struct S; | --------- function or associated item `a` not found for this ... LL | trait A { - | ------- this trait defines an item `a` + | ------- `method::A` defines an item `a` ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -82,7 +82,7 @@ LL | struct S; | --------- associated item `A` not found for this ... LL | trait A { - | ------- this trait defines an item `A` + | ------- `assoc_const::A` defines an item `A` ... LL | S::A; | ^ associated item not found in `S` diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 7ed24591e66..0bd18763ac9 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -12,7 +12,7 @@ error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | LL | pub trait Foo { - | ------------- this trait defines an item `test` + | ------------- `Foo` defines an item `test` ... LL | 3i32.test(); | ^^^^ method not found in `i32` From 1e7bcc733a10098bc06d93c8fe183c8c61307298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:36:56 -0800 Subject: [PATCH 0589/1250] Tweak wording --- src/librustc_typeck/check/method/suggest.rs | 6 ++++-- .../associated-const/associated-const-no-item.stderr | 2 +- src/test/ui/auto-ref-slice-plus-ref.stderr | 8 ++++---- .../issue-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/no-method-suggested-traits.stderr | 12 ++++++------ src/test/ui/issues/issue-5153.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 2 +- src/test/ui/issues/issue-57362-2.stderr | 2 +- src/test/ui/never_type/issue-2149.stderr | 2 +- src/test/ui/object-pointer-types.stderr | 4 ++-- .../point-at-arbitrary-self-type-trait-method.stderr | 2 +- .../specialization-trait-not-implemented.stderr | 2 +- src/test/ui/traits/trait-item-privacy.stderr | 6 +++--- .../ui/trivial-bounds/trivial-bounds-leak.stderr | 2 +- 14 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index af7f63772c3..7e98797d0c2 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -988,6 +988,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let action = if let Some(param) = param_type { format!("restrict type parameter `{}` with", param) } else { + // FIXME: it might only need to be imported into scope, not implemented. "implement".to_string() }; let mut use_note = true; @@ -996,9 +997,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( self.tcx.sess.source_map().def_span(span), &format!( - "`{}` defines an item `{}`", + "`{}` defines an item `{}`, perhaps you need to {} it", self.tcx.def_path_str(trait_info.def_id), - item_name + item_name, + action ), ); use_note = false diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index 02d4866e3f5..c3339e453e8 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current --> $DIR/associated-const-no-item.rs:5:23 | LL | trait Foo { - | --------- `Foo` defines an item `ID` + | --------- `Foo` defines an item `ID`, perhaps you need to implement it ... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 26b2c44fdd9..3500cef6c39 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -5,7 +5,7 @@ LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test_mut` + | ------------ `MyIter` defines an item `test_mut`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -16,7 +16,7 @@ LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -27,7 +27,7 @@ LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -38,7 +38,7 @@ LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index cdcf84a7063..75a2e9a99a9 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | trait Foo { - | ------------ `Foo` defines an item `foo` + | ------------ `Foo` defines an item `foo`, perhaps you need to implement it ... LL | struct Bar; | ----------- method `foo` not found for this diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index b3da4a6ead6..c6017a5fea1 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -123,7 +123,7 @@ error[E0599]: no method named `method2` found for type `u64` in the current scop --> $DIR/no-method-suggested-traits.rs:45:10 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` @@ -134,7 +134,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:47:44 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` @@ -145,7 +145,7 @@ error[E0599]: no method named `method2` found for struct `no_method_suggested_tr --> $DIR/no-method-suggested-traits.rs:50:37 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` @@ -156,7 +156,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:52:71 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` @@ -167,7 +167,7 @@ error[E0599]: no method named `method2` found for enum `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:54:40 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` @@ -178,7 +178,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:56:74 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index bf48c662383..44ef73550f8 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the curren --> $DIR/issue-5153.rs:10:27 | LL | trait Foo { - | --------- `Foo` defines an item `foo` + | --------- `Foo` defines an item `foo`, perhaps you need to implement it ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 4eaa5adbea4..c48f51e2b2a 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current --> $DIR/issue-57362-1.rs:20:7 | LL | trait Trait { - | ----------- `Trait` defines an item `f` + | ----------- `Trait` defines an item `f`, perhaps you need to implement it ... LL | a.f(); | ^ method not found in `fn(&u8)` diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index ce689334cc1..b3b30dbd1c8 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer --> $DIR/issue-57362-2.rs:22:25 | LL | trait X { - | ------- `X` defines an item `make_g` + | ------- `X` defines an item `make_g`, perhaps you need to implement it ... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index b92ab5dde27..74512619966 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -10,7 +10,7 @@ error[E0599]: no method named `bind` found for array `[&str; 1]` in the current --> $DIR/issue-2149.rs:13:12 | LL | trait VecMonad { - | ----------------- `VecMonad` defines an item `bind` + | ----------------- `VecMonad` defines an item `bind`, perhaps you need to implement it ... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 7364ead97f6..07b7da94097 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the curr --> $DIR/object-pointer-types.rs:11:7 | LL | trait Foo { - | --------- `Foo` defines an item `owned` + | --------- `Foo` defines an item `owned`, perhaps you need to implement it ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` @@ -13,7 +13,7 @@ error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` --> $DIR/object-pointer-types.rs:17:7 | LL | trait Foo { - | --------- `Foo` defines an item `owned` + | --------- `Foo` defines an item `owned`, perhaps you need to implement it ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index fefa6dab15a..999bbcca6bc 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope LL | trait B { fn foo(self: Box); } | ------- --- the method is available for `std::boxed::Box` here | | - | `B` defines an item `foo` + | `B` defines an item `foo`, perhaps you need to implement it LL | struct A; | --------- method `foo` not found for this ... diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 93a5f3051fe..f4d29e61cc1 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | trait Foo { - | --------- `Foo` defines an item `foo_one` + | --------- `Foo` defines an item `foo_one`, perhaps you need to implement it ... LL | struct MyStruct; | ---------------- diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 23f08f37826..f893456a17c 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -5,7 +5,7 @@ LL | struct S; | --------- method `a` not found for this ... LL | trait A { - | ------- `method::A` defines an item `a` + | ------- `method::A` defines an item `a`, perhaps you need to implement it ... LL | S.a(); | ^ method not found in `S` @@ -47,7 +47,7 @@ LL | struct S; | --------- function or associated item `a` not found for this ... LL | trait A { - | ------- `method::A` defines an item `a` + | ------- `method::A` defines an item `a`, perhaps you need to implement it ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -82,7 +82,7 @@ LL | struct S; | --------- associated item `A` not found for this ... LL | trait A { - | ------- `assoc_const::A` defines an item `A` + | ------- `assoc_const::A` defines an item `A`, perhaps you need to implement it ... LL | S::A; | ^ associated item not found in `S` diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 0bd18763ac9..ef41c0e5fa0 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -12,7 +12,7 @@ error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | LL | pub trait Foo { - | ------------- `Foo` defines an item `test` + | ------------- `Foo` defines an item `test`, perhaps you need to implement it ... LL | 3i32.test(); | ^^^^ method not found in `i32` From 392d853589721ffef1f32181d6c3959f0284e4fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 19 Feb 2020 14:26:46 -0800 Subject: [PATCH 0590/1250] Suggest constraining type parameters --- src/librustc_parse/parser/generics.rs | 6 +- src/librustc_typeck/check/method/suggest.rs | 80 +++++++++++++++---- .../missing-trait-bounds-for-method-call.rs | 31 +++++++ ...issing-trait-bounds-for-method-call.stderr | 44 ++++++++++ 4 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs create mode 100644 src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs index 0984263bb28..4d9a3266567 100644 --- a/src/librustc_parse/parser/generics.rs +++ b/src/librustc_parse/parser/generics.rs @@ -1,7 +1,6 @@ use super::Parser; use rustc_errors::PResult; -use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, sym}; use syntax::ast::{self, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause}; use syntax::token; @@ -160,7 +159,10 @@ impl<'a> Parser<'a> { }; Ok(ast::Generics { params, - where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP }, + where_clause: WhereClause { + predicates: Vec::new(), + span: self.prev_span.shrink_to_hi(), + }, span, }) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7e98797d0c2..410b8883a29 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -7,7 +7,7 @@ use rustc::hir::map as hir_map; use rustc::hir::map::Map; use rustc::ty::print::with_crate_prefix; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -537,10 +537,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !unsatisfied_predicates.is_empty() { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); + let mut type_params = FxHashMap::default(); let mut bound_spans = vec![]; + let mut collect_type_param_suggestions = + |self_ty: Ty<'_>, parent_pred: &ty::Predicate<'_>, obligation: &str| { + if let (ty::Param(_), ty::Predicate::Trait(p, _)) = + (&self_ty.kind, parent_pred) + { + if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind { + let id = self.tcx.hir().as_local_hir_id(def.did).unwrap(); + let node = self.tcx.hir().get(id); + match node { + hir::Node::Item(hir::Item { kind, .. }) => { + if let Some(g) = kind.generics() { + let key = match &g.where_clause.predicates[..] { + [.., pred] => { + (pred.span().shrink_to_hi(), false) + } + [] => ( + g.where_clause + .span_for_predicates_or_empty_place(), + true, + ), + }; + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); + } + } + _ => {} + } + } + } + }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!( - "doesn't satisfy {}", + "doesn't satisfy `{}`", if obligation.len() > 50 { quiet } else { obligation } ); match &self_ty.kind { @@ -560,7 +593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => bound_spans - .push((def_span(*def_id), format!("doesn't satisfy {}", quiet))), + .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))), _ => {} } }; @@ -574,25 +607,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let obligation = - format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty); let quiet = format!( - "`<_ as {}>::{} = {}`", + "<_ as {}>::{} = {}", trait_ref.print_only_trait_path(), assoc.ident, ty ); bound_span_label(trait_ref.self_ty(), &obligation, &quiet); - Some(obligation) + Some((obligation, trait_ref.self_ty())) } ty::Predicate::Trait(poly_trait_ref, _) => { let p = poly_trait_ref.skip_binder().trait_ref; let self_ty = p.self_ty(); let path = p.print_only_trait_path(); - let obligation = format!("`{}: {}`", self_ty, path); - let quiet = format!("`_: {}`", path); + let obligation = format!("{}: {}", self_ty, path); + let quiet = format!("_: {}", path); bound_span_label(self_ty, &obligation, &quiet); - Some(obligation) + Some((obligation, self_ty)) } _ => None, } @@ -600,17 +632,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_list = unsatisfied_predicates .iter() .filter_map(|(pred, parent_pred)| { - format_pred(*pred).map(|pred| match parent_pred { - None => pred, + format_pred(*pred).map(|(p, self_ty)| match parent_pred { + None => format!("`{}`", p), Some(parent_pred) => match format_pred(*parent_pred) { - None => pred, - Some(parent_pred) => { - format!("{} which is required by {}", pred, parent_pred) + None => format!("`{}`", p), + Some((parent_p, _)) => { + collect_type_param_suggestions(self_ty, parent_pred, &p); + format!("`{}` which is required by `{}`", p, parent_p) } }, }) }) .collect::>(); + for ((span, empty_where), obligations) in type_params.into_iter() { + err.span_suggestion_verbose( + span, + &format!( + "consider restricting the type parameter{s} to satisfy the \ + obligation{s}", + s = pluralize!(obligations.len()) + ), + format!( + "{} {}", + if empty_where { " where" } else { "," }, + obligations.into_iter().collect::>().join(", ") + ), + Applicability::MaybeIncorrect, + ); + } + bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs new file mode 100644 index 00000000000..fefdf149f55 --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs @@ -0,0 +1,31 @@ +#[derive(Default, PartialEq)] +struct Foo { + bar: Box<[T]>, +} + +trait Bar { + fn foo(&self) {} +} + +impl Bar for Foo {} + +impl Foo { + fn bar(&self) { + self.foo(); + //~^ ERROR no method named `foo` found for reference `&Foo` in the current scope + } +} + +struct Fin where T: Bar { + bar: Box<[T]>, +} + +impl Bar for Fin {} + +impl Fin { + fn bar(&self) { + self.foo(); + //~^ ERROR no method named `foo` found for reference `&Fin` in the current scope + } +} +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr new file mode 100644 index 00000000000..b1b31a67650 --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -0,0 +1,44 @@ +error[E0599]: no method named `foo` found for reference `&Foo` in the current scope + --> $DIR/missing-trait-bounds-for-method-call.rs:14:14 + | +LL | struct Foo { + | ------------- doesn't satisfy `Foo: Bar` +... +LL | trait Bar { + | --------- `Bar` defines an item `foo`, perhaps you need to implement it +... +LL | self.foo(); + | ^^^ method not found in `&Foo` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `T: Bar` which is required by `Foo: Bar` + `T: std::default::Default` which is required by `Foo: Bar` + = help: items from traits can only be used if the trait is implemented and in scope +help: consider restricting the type parameters to satisfy the obligations + | +LL | struct Foo where T: Bar, T: std::default::Default { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `foo` found for reference `&Fin` in the current scope + --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 + | +LL | trait Bar { + | --------- `Bar` defines an item `foo`, perhaps you need to implement it +... +LL | struct Fin where T: Bar { + | -------------------------- doesn't satisfy `Fin: Bar` +... +LL | self.foo(); + | ^^^ method not found in `&Fin` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `T: std::default::Default` which is required by `Fin: Bar` + = help: items from traits can only be used if the trait is implemented and in scope +help: consider restricting the type parameter to satisfy the obligation + | +LL | struct Fin where T: Bar, T: std::default::Default { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From 01286408c1d4ac9d862801ac102ce4de44fc095b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 19 Feb 2020 15:57:21 -0800 Subject: [PATCH 0591/1250] Account for arbitrary self types in E0599 --- src/librustc_typeck/check/method/suggest.rs | 51 +++++++++++++++++++ src/test/ui/issues/issue-5153.stderr | 6 +-- src/test/ui/object-pointer-types.stderr | 12 ++--- ...at-arbitrary-self-type-trait-method.stderr | 8 ++- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 410b8883a29..cfd6356b0a1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; +use rustc_span::symbol::kw; use rustc_span::{source_map, FileName, Span}; use syntax::ast; use syntax::util::lev_distance; @@ -893,6 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source); + let mut arbitrary_rcvr = vec![]; // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are // legal to implement. @@ -909,12 +911,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { + if let ty::AssocKind::Method = item.kind { + let id = self.tcx.hir().as_local_hir_id(item.def_id); + if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Method(fn_sig, method), + .. + })) = id.map(|id| self.tcx.hir().get(id)) + { + let self_first_arg = match method { + hir::TraitMethod::Required([ident, ..]) => { + ident.name == kw::SelfLower + } + hir::TraitMethod::Provided(body_id) => { + match &self.tcx.hir().body(*body_id).params[..] { + [hir::Param { + pat: + hir::Pat { + kind: + hir::PatKind::Binding( + _, + _, + ident, + .., + ), + .. + }, + .. + }, ..] => ident.name == kw::SelfLower, + _ => false, + } + } + _ => false, + }; + + if !fn_sig.decl.implicit_self.has_implicit_self() + && self_first_arg + { + if let Some(ty) = fn_sig.decl.inputs.get(0) { + arbitrary_rcvr.push(ty.span); + } + return false; + } + } + } // We only want to suggest public or local traits (#45781). item.vis == ty::Visibility::Public || info.def_id.is_local() }) .is_some() }) .collect::>(); + for span in &arbitrary_rcvr { + err.span_label( + *span, + "the method might not be found because of this arbitrary self type", + ); + } if !candidates.is_empty() { // Sort from most relevant to least relevant. diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 44ef73550f8..93aaf4b9d82 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -1,13 +1,11 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope --> $DIR/issue-5153.rs:10:27 | -LL | trait Foo { - | --------- `Foo` defines an item `foo`, perhaps you need to implement it +LL | fn foo(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 07b7da94097..021aa8670f7 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -1,24 +1,20 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:11:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:17:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope --> $DIR/object-pointer-types.rs:23:7 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 999bbcca6bc..37873031da3 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -2,16 +2,14 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 | LL | trait B { fn foo(self: Box); } - | ------- --- the method is available for `std::boxed::Box` here - | | - | `B` defines an item `foo`, perhaps you need to implement it + | --- --------- the method might not be found because of this arbitrary self type + | | + | the method is available for `std::boxed::Box` here LL | struct A; | --------- method `foo` not found for this ... LL | A.foo() | ^^^ method not found in `A` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error From 7c29441ef2efcd47512402d5558b41a235648841 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 21 Feb 2020 13:39:47 -0800 Subject: [PATCH 0592/1250] Review comments: split requirement text to multiple lines for readability --- src/librustc_typeck/check/method/suggest.rs | 2 +- src/test/ui/derives/derive-assoc-type-not-impl.stderr | 3 ++- src/test/ui/issues/issue-21596.stderr | 3 ++- src/test/ui/issues/issue-31173.stderr | 6 ++++-- src/test/ui/methods/method-call-err-msg.stderr | 3 ++- src/test/ui/mismatched_types/issue-36053-2.stderr | 9 ++++++--- .../missing-trait-bounds-for-method-call.stderr | 9 ++++++--- .../ui/suggestions/mut-borrow-needed-by-trait.stderr | 3 ++- src/test/ui/union/union-derive-clone.stderr | 3 ++- src/test/ui/unique-object-noncopyable.stderr | 6 ++++-- src/test/ui/unique-pinned-nocopy.stderr | 3 ++- 11 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index cfd6356b0a1..9fcb1c75fae 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -639,7 +639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => format!("`{}`", p), Some((parent_p, _)) => { collect_type_param_suggestions(self_ty, parent_pred, &p); - format!("`{}` which is required by `{}`", p, parent_p) + format!("`{}`\nwhich is required by `{}`", p, parent_p) } }, }) diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index e837c7721af..c4c85773fbc 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -14,7 +14,8 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` which is required by `Bar: std::clone::Clone` + `NotClone: std::clone::Clone` + which is required by `Bar: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index bbd16618049..3e0a532b2b8 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,8 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8: std::fmt::Display` which is required by `*const u8: std::string::ToString` + `*const u8: std::fmt::Display` + which is required by `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index ca8e63550d6..20bfdeea4b1 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -22,8 +22,10 @@ LL | pub struct TakeWhile { | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b4e54ab7783..ecb69506157 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,8 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` + which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 49e61cd2327..f8c0470172d 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -13,9 +13,12 @@ LL | pub struct Filter { | ----------------------- doesn't satisfy `_: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` + which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` + which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index b1b31a67650..4f6620b47c2 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -11,8 +11,10 @@ LL | self.foo(); | ^^^ method not found in `&Foo` | = note: the method `foo` exists but the following trait bounds were not satisfied: - `T: Bar` which is required by `Foo: Bar` - `T: std::default::Default` which is required by `Foo: Bar` + `T: Bar` + which is required by `Foo: Bar` + `T: std::default::Default` + which is required by `Foo: Bar` = help: items from traits can only be used if the trait is implemented and in scope help: consider restricting the type parameters to satisfy the obligations | @@ -32,7 +34,8 @@ LL | self.foo(); | ^^^ method not found in `&Fin` | = note: the method `foo` exists but the following trait bounds were not satisfied: - `T: std::default::Default` which is required by `Fin: Bar` + `T: std::default::Default` + which is required by `Fin: Bar` = help: items from traits can only be used if the trait is implemented and in scope help: consider restricting the type parameter to satisfy the obligation | diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 16a03c42a4d..57a389cbb49 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -37,7 +37,8 @@ LL | pub struct BufWriter { | ------------------------------ doesn't satisfy `_: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` + `&dyn std::io::Write: std::io::Write` + which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 456e1cd83ef..fdf2393656e 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -23,7 +23,8 @@ LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` + `CloneNoCopy: std::marker::Copy` + which is required by `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index c3be38e1cf1..6a0a6c87079 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -16,8 +16,10 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` - `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::marker::Sized` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index fb2f4c01b63..32f751fbcf7 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -13,7 +13,8 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` + `R: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From c764a82310fe5dcec5586d5a6afb87a8a29f62c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Feb 2020 18:55:51 -0800 Subject: [PATCH 0593/1250] keep predicate order and tweak output --- src/librustc_typeck/check/method/suggest.rs | 16 +++++-- .../associated-const-no-item.stderr | 8 ++-- src/test/ui/auto-ref-slice-plus-ref.stderr | 32 ++++++++----- ...e-21659-show-relevant-trait-impls-3.stderr | 8 ++-- .../no-method-suggested-traits.stderr | 48 ++++++++++++------- .../option-as_deref.stderr | 2 +- .../option-as_deref_mut.stderr | 2 +- .../result-as_deref.stderr | 2 +- .../result-as_deref_err.stderr | 2 +- .../result-as_deref_mut.stderr | 2 +- .../result-as_deref_mut_err.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 8 ++-- src/test/ui/issues/issue-57362-2.stderr | 8 ++-- src/test/ui/never_type/issue-2149.stderr | 8 ++-- ...pecialization-trait-not-implemented.stderr | 8 ++-- ...issing-trait-bounds-for-method-call.stderr | 16 ++++--- src/test/ui/traits/trait-item-privacy.stderr | 24 ++++++---- .../trivial-bounds/trivial-bounds-leak.stderr | 8 ++-- src/test/ui/unique-object-noncopyable.stderr | 4 +- 19 files changed, 129 insertions(+), 79 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9fcb1c75fae..f9b5ff8e2ab 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -644,7 +644,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }) }) - .collect::>(); + .enumerate() + .collect::>(); for ((span, empty_where), obligations) in type_params.into_iter() { err.span_suggestion_verbose( span, @@ -662,15 +663,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - bound_list.sort(); - bound_list.dedup(); // #35677 + bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically. + bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677 + bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order. bound_spans.sort(); bound_spans.dedup(); for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } if !bound_list.is_empty() { - let bound_list = bound_list.join("\n"); + let bound_list = bound_list + .into_iter() + .map(|(_, path)| path) + .collect::>() + .join("\n"); err.note(&format!( "the method `{}` exists but the following trait bounds were not \ satisfied:\n{}", @@ -1095,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut use_note = true; if let [trait_info] = &candidates[..] { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { - err.span_label( + err.span_note( self.tcx.sess.source_map().def_span(span), &format!( "`{}` defines an item `{}`, perhaps you need to {} it", diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index c3339e453e8..fe27da5ac64 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,13 +1,15 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope --> $DIR/associated-const-no-item.rs:5:23 | -LL | trait Foo { - | --------- `Foo` defines an item `ID`, perhaps you need to implement it -... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `ID`, perhaps you need to implement it + --> $DIR/associated-const-no-item.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 3500cef6c39..50ca5cad4bc 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -3,44 +3,52 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege | LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test_mut`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test_mut`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:8:7 | LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:10:11 | LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:11:12 | LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 75a2e9a99a9..64cce056a26 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -1,9 +1,6 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | -LL | trait Foo { - | ------------ `Foo` defines an item `foo`, perhaps you need to implement it -... LL | struct Bar; | ----------- method `foo` not found for this ... @@ -11,6 +8,11 @@ LL | f1.foo(1usize); | ^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo`, perhaps you need to implement it + --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index c6017a5fea1..c0ca341385d 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -122,68 +122,80 @@ LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); error[E0599]: no method named `method2` found for type `u64` in the current scope --> $DIR/no-method-suggested-traits.rs:45:10 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope --> $DIR/no-method-suggested-traits.rs:47:44 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:50:37 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:52:71 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:54:40 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:56:74 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method3` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:59:9 diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 63359be56bf..5db521536a8 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,8 +5,8 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index b01b3448e17..f2133c8c84d 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 75482841987..2dfc6d53750 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,8 +5,8 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index cf31bc4b56b..1d65c57e5e9 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,8 +5,8 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 586b3555455..2f4bf0c94b5 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index fd0e43d7dbc..b76d36c804e 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index c48f51e2b2a..5c611cd43d3 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,14 +1,16 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | -LL | trait Trait { - | ----------- `Trait` defines an item `f`, perhaps you need to implement it -... LL | a.f(); | ^ method not found in `fn(&u8)` | = note: `a` is a function, perhaps you wish to call it = help: items from traits can only be used if the trait is implemented and in scope +note: `Trait` defines an item `f`, perhaps you need to implement it + --> $DIR/issue-57362-1.rs:8:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index b3b30dbd1c8..2edc0097464 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,13 +1,15 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | -LL | trait X { - | ------- `X` defines an item `make_g`, perhaps you need to implement it -... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | = help: items from traits can only be used if the trait is implemented and in scope +note: `X` defines an item `make_g`, perhaps you need to implement it + --> $DIR/issue-57362-2.rs:8:1 + | +LL | trait X { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 74512619966..3cdd6372ec1 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -9,13 +9,15 @@ LL | for elt in self { r = r + f(*elt); } error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope --> $DIR/issue-2149.rs:13:12 | -LL | trait VecMonad { - | ----------------- `VecMonad` defines an item `bind`, perhaps you need to implement it -... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` | = help: items from traits can only be used if the trait is implemented and in scope +note: `VecMonad` defines an item `bind`, perhaps you need to implement it + --> $DIR/issue-2149.rs:1:1 + | +LL | trait VecMonad { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index f4d29e61cc1..a55d79ee035 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -1,9 +1,6 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope --> $DIR/specialization-trait-not-implemented.rs:22:29 | -LL | trait Foo { - | --------- `Foo` defines an item `foo_one`, perhaps you need to implement it -... LL | struct MyStruct; | ---------------- | | @@ -16,6 +13,11 @@ LL | println!("{}", MyStruct.foo_one()); = note: the method `foo_one` exists but the following trait bounds were not satisfied: `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo_one`, perhaps you need to implement it + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index 4f6620b47c2..1692af351f9 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -4,9 +4,6 @@ error[E0599]: no method named `foo` found for reference `&Foo` in the current LL | struct Foo { | ------------- doesn't satisfy `Foo: Bar` ... -LL | trait Bar { - | --------- `Bar` defines an item `foo`, perhaps you need to implement it -... LL | self.foo(); | ^^^ method not found in `&Foo` | @@ -16,6 +13,11 @@ LL | self.foo(); `T: std::default::Default` which is required by `Foo: Bar` = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `foo`, perhaps you need to implement it + --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 + | +LL | trait Bar { + | ^^^^^^^^^ help: consider restricting the type parameters to satisfy the obligations | LL | struct Foo where T: Bar, T: std::default::Default { @@ -24,9 +26,6 @@ LL | struct Foo where T: Bar, T: std::default::Default { error[E0599]: no method named `foo` found for reference `&Fin` in the current scope --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 | -LL | trait Bar { - | --------- `Bar` defines an item `foo`, perhaps you need to implement it -... LL | struct Fin where T: Bar { | -------------------------- doesn't satisfy `Fin: Bar` ... @@ -37,6 +36,11 @@ LL | self.foo(); `T: std::default::Default` which is required by `Fin: Bar` = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `foo`, perhaps you need to implement it + --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 + | +LL | trait Bar { + | ^^^^^^^^^ help: consider restricting the type parameter to satisfy the obligation | LL | struct Fin where T: Bar, T: std::default::Default { diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index f893456a17c..2c0591c95f6 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -4,13 +4,15 @@ error[E0599]: no method named `a` found for struct `S` in the current scope LL | struct S; | --------- method `a` not found for this ... -LL | trait A { - | ------- `method::A` defines an item `a`, perhaps you need to implement it -... LL | S.a(); | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:68:7 @@ -46,13 +48,15 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t LL | struct S; | --------- function or associated item `a` not found for this ... -LL | trait A { - | ------- `method::A` defines an item `a`, perhaps you need to implement it -... LL | S::a(&S); | ^ function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no function or associated item named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:80:8 @@ -81,13 +85,15 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s LL | struct S; | --------- associated item `A` not found for this ... -LL | trait A { - | ------- `assoc_const::A` defines an item `A`, perhaps you need to implement it -... LL | S::A; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `assoc_const::A` defines an item `A`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:24:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no associated item named `B` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:98:8 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index ef41c0e5fa0..4e153081d9f 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -11,13 +11,15 @@ LL | fn cant_return_str() -> str { error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | -LL | pub trait Foo { - | ------------- `Foo` defines an item `test`, perhaps you need to implement it -... LL | 3i32.test(); | ^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `test`, perhaps you need to implement it + --> $DIR/trivial-bounds-leak.rs:4:1 + | +LL | pub trait Foo { + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 6a0a6c87079..1c5fed2c33b 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -16,10 +16,10 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - which is required by `std::boxed::Box: std::clone::Clone` `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From a29f6916d88c4a479139cebc95a98028efa51611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Feb 2020 23:25:54 -0800 Subject: [PATCH 0594/1250] Reduce verbosity when suggesting restricting type params --- src/librustc_typeck/check/method/suggest.rs | 4 +++- .../missing-trait-bounds-for-method-call.stderr | 12 ------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f9b5ff8e2ab..55b15925bf7 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -535,6 +535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { report_candidates(span, &mut err, static_sources, sugg_span); } + let mut restrict_type_params = false; if !unsatisfied_predicates.is_empty() { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); @@ -647,6 +648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .collect::>(); for ((span, empty_where), obligations) in type_params.into_iter() { + restrict_type_params = true; err.span_suggestion_verbose( span, &format!( @@ -685,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if actual.is_numeric() && actual.is_fresh() { + if actual.is_numeric() && actual.is_fresh() || restrict_type_params { } else { self.suggest_traits_to_import( &mut err, diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index 1692af351f9..a9b57cfc0bd 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -12,12 +12,6 @@ LL | self.foo(); which is required by `Foo: Bar` `T: std::default::Default` which is required by `Foo: Bar` - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `foo`, perhaps you need to implement it - --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 - | -LL | trait Bar { - | ^^^^^^^^^ help: consider restricting the type parameters to satisfy the obligations | LL | struct Foo where T: Bar, T: std::default::Default { @@ -35,12 +29,6 @@ LL | self.foo(); = note: the method `foo` exists but the following trait bounds were not satisfied: `T: std::default::Default` which is required by `Fin: Bar` - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `foo`, perhaps you need to implement it - --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 - | -LL | trait Bar { - | ^^^^^^^^^ help: consider restricting the type parameter to satisfy the obligation | LL | struct Fin where T: Bar, T: std::default::Default { From 61bc7a346217ff7f180662d10dd34605a876901d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Feb 2020 12:08:22 -0800 Subject: [PATCH 0595/1250] Reword message --- src/librustc_typeck/check/method/suggest.rs | 4 ++-- .../suggestions/missing-trait-bounds-for-method-call.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 55b15925bf7..5528895ad03 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !static_sources.is_empty() { err.note( "found the following associated functions; to be used as methods, \ - functions must have a `self` parameter", + functions must have a `self` parameter", ); err.span_label(span, "this is an associated function, not a method"); } @@ -653,7 +653,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, &format!( "consider restricting the type parameter{s} to satisfy the \ - obligation{s}", + trait bound{s}", s = pluralize!(obligations.len()) ), format!( diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index a9b57cfc0bd..c6d94826c0c 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -12,7 +12,7 @@ LL | self.foo(); which is required by `Foo: Bar` `T: std::default::Default` which is required by `Foo: Bar` -help: consider restricting the type parameters to satisfy the obligations +help: consider restricting the type parameters to satisfy the trait bounds | LL | struct Foo where T: Bar, T: std::default::Default { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | self.foo(); = note: the method `foo` exists but the following trait bounds were not satisfied: `T: std::default::Default` which is required by `Fin: Bar` -help: consider restricting the type parameter to satisfy the obligation +help: consider restricting the type parameter to satisfy the trait bound | LL | struct Fin where T: Bar, T: std::default::Default { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From a9a99df0a2976f1fd0dfc146f818778e5fdd635e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Feb 2020 12:10:48 -0800 Subject: [PATCH 0596/1250] Do not suggest implementing traits if present in predicates --- src/librustc_typeck/check/method/suggest.rs | 10 +++++++++- src/test/ui/methods/method-call-err-msg.stderr | 5 ++--- src/test/ui/union/union-derive-clone.stderr | 3 --- src/test/ui/unique-object-noncopyable.stderr | 3 --- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5528895ad03..44f87319ebf 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -696,6 +696,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, source, out_of_scope_traits, + &unsatisfied_predicates, ); } @@ -895,6 +896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: ast::Ident, source: SelfSource<'b>, valid_out_of_scope_traits: Vec, + unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], ) { if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; @@ -915,7 +917,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - (type_is_local || info.def_id.is_local()) + !unsatisfied_predicates.iter().any(|(p, _)| match p { + // Hide traits if they are present in predicates as they can be fixed without + // having to implement them. + ty::Predicate::Trait(t, _) => t.def_id() != info.def_id, + ty::Predicate::Projection(p) => p.item_def_id() != info.def_id, + _ => true, + }) && (type_is_local || info.def_id.is_local()) && self .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index ecb69506157..4678642dd6d 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -47,9 +47,8 @@ LL | .take() `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope - = note: the following traits define an item `take`, perhaps you need to implement one of them: - candidate #1: `std::io::Read` - candidate #2: `std::iter::Iterator` + = note: the following trait defines an item `take`, perhaps you need to implement it: + candidate #1: `std::iter::Iterator` error[E0061]: this function takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index fdf2393656e..01c8e8471aa 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -25,9 +25,6 @@ LL | let w = u.clone(); = note: the method `clone` exists but the following trait bounds were not satisfied: `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `std::clone::Clone` error: aborting due to 2 previous errors diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 1c5fed2c33b..286008188fc 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -20,9 +20,6 @@ LL | pub struct Box(Unique); which is required by `std::boxed::Box: std::clone::Clone` `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `std::clone::Clone` error: aborting due to previous error From 2fb35adc4873017fa5d8fdd94ee0d508614cbc94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 28 Feb 2020 12:01:29 -0800 Subject: [PATCH 0597/1250] Ignore output for some platforms with diverging test output Get around #53081. --- src/test/ui/suggestions/mut-borrow-needed-by-trait.rs | 4 ++++ src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr | 8 ++++---- src/test/ui/unique-object-noncopyable.rs | 4 ++++ src/test/ui/unique-object-noncopyable.stderr | 2 +- src/test/ui/unique-pinned-nocopy.rs | 4 ++++ src/test/ui/unique-pinned-nocopy.stderr | 2 +- 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index f8b86377187..49a37498fd9 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl use std::env::args; use std::fs::File; use std::io::{stdout, Write, BufWriter}; diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 57a389cbb49..e4234cfcd51 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + --> $DIR/mut-borrow-needed-by-trait.rs:21:29 | LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -8,7 +8,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -17,7 +17,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -26,7 +26,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:22:5 + --> $DIR/mut-borrow-needed-by-trait.rs:26:5 | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index dd38a7190aa..bedaf27c2dd 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #![feature(box_syntax)] trait Foo { diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 286008188fc..fb78095224b 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-object-noncopyable.rs:24:16 + --> $DIR/unique-object-noncopyable.rs:28:16 | LL | trait Foo { | --------- diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 4c30450c704..091b8a43862 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #[derive(Debug)] struct R { b: bool, diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 32f751fbcf7..ea6575d1d85 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-pinned-nocopy.rs:12:16 + --> $DIR/unique-pinned-nocopy.rs:16:16 | LL | struct R { | -------- doesn't satisfy `R: std::clone::Clone` From 52ad1e73ceddcc746d2b6e01f238860cf4c53bde Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 28 Feb 2020 12:06:06 -0800 Subject: [PATCH 0598/1250] Don't bug when taking discriminant of generator --- src/librustc_mir/dataflow/generic/engine.rs | 126 +++++++++++--------- 1 file changed, 72 insertions(+), 54 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index 371bfa9a6fd..f223c2ec4d1 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -239,14 +239,24 @@ where } SwitchInt { ref targets, ref values, ref discr, .. } => { - self.propagate_bits_into_switch_int_successors( - in_out, - (bb, bb_data), - dirty_list, - discr, - &*values, - &*targets, - ); + // If this is a switch on an enum discriminant, a custom effect may be applied + // along each outgoing edge. + if let Some(place) = discr.place() { + let enum_def = switch_on_enum_discriminant(self.tcx, self.body, bb_data, place); + if let Some(enum_def) = enum_def { + self.propagate_bits_into_enum_discriminant_switch_successors( + in_out, bb, enum_def, place, dirty_list, &*values, &*targets, + ); + + return; + } + } + + // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same + // exit state. + for target in targets.iter().copied() { + self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list); + } } Call { cleanup, ref destination, ref func, ref args, .. } => { @@ -293,64 +303,72 @@ where } } - fn propagate_bits_into_switch_int_successors( + fn propagate_bits_into_enum_discriminant_switch_successors( &mut self, in_out: &mut BitSet, - (bb, bb_data): (BasicBlock, &mir::BasicBlockData<'tcx>), + bb: BasicBlock, + enum_def: &'tcx ty::AdtDef, + enum_place: &mir::Place<'tcx>, dirty_list: &mut WorkQueue, - switch_on: &mir::Operand<'tcx>, values: &[u128], targets: &[BasicBlock], ) { - match bb_data.statements.last().map(|stmt| &stmt.kind) { - // Look at the last statement to see if it is an assignment of an enum discriminant to - // the local that determines the target of a `SwitchInt` like so: - // _42 = discriminant(..) - // SwitchInt(_42, ..) - Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(enum_)))) - if Some(lhs) == switch_on.place() => - { - let adt = match enum_.ty(self.body, self.tcx).ty.kind { - ty::Adt(def, _) => def, - _ => bug!("Switch on discriminant of non-ADT"), - }; - - // MIR building adds discriminants to the `values` array in the same order as they - // are yielded by `AdtDef::discriminants`. We rely on this to match each - // discriminant in `values` to its corresponding variant in linear time. - let mut tmp = BitSet::new_empty(in_out.domain_size()); - let mut discriminants = adt.discriminants(self.tcx); - for (value, target) in values.iter().zip(targets.iter().copied()) { - let (variant_idx, _) = - discriminants.find(|&(_, discr)| discr.val == *value).expect( - "Order of `AdtDef::discriminants` differed \ - from that of `SwitchInt::values`", - ); + // MIR building adds discriminants to the `values` array in the same order as they + // are yielded by `AdtDef::discriminants`. We rely on this to match each + // discriminant in `values` to its corresponding variant in linear time. + let mut tmp = BitSet::new_empty(in_out.domain_size()); + let mut discriminants = enum_def.discriminants(self.tcx); + for (value, target) in values.iter().zip(targets.iter().copied()) { + let (variant_idx, _) = discriminants.find(|&(_, discr)| discr.val == *value).expect( + "Order of `AdtDef::discriminants` differed from that of `SwitchInt::values`", + ); - tmp.overwrite(in_out); - self.analysis.apply_discriminant_switch_effect( - &mut tmp, - bb, - enum_, - adt, - variant_idx, - ); - self.propagate_bits_into_entry_set_for(&tmp, target, dirty_list); - } + tmp.overwrite(in_out); + self.analysis.apply_discriminant_switch_effect( + &mut tmp, + bb, + enum_place, + enum_def, + variant_idx, + ); + self.propagate_bits_into_entry_set_for(&tmp, target, dirty_list); + } - std::mem::drop(tmp); + std::mem::drop(tmp); - // Propagate dataflow state along the "otherwise" edge. - let otherwise = targets.last().copied().unwrap(); - self.propagate_bits_into_entry_set_for(&in_out, otherwise, dirty_list); - } + // Propagate dataflow state along the "otherwise" edge. + let otherwise = targets.last().copied().unwrap(); + self.propagate_bits_into_entry_set_for(&in_out, otherwise, dirty_list); + } +} - _ => { - for target in targets.iter().copied() { - self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list); - } +/// Look at the last statement of a block that ends with to see if it is an assignment of an enum +/// discriminant to the local that determines the target of a `SwitchInt` like so: +/// _42 = discriminant(..) +/// SwitchInt(_42, ..) +fn switch_on_enum_discriminant( + tcx: TyCtxt<'tcx>, + body: &mir::Body<'tcx>, + block: &mir::BasicBlockData<'tcx>, + switch_on: &mir::Place<'tcx>, +) -> Option<&'tcx ty::AdtDef> { + match block.statements.last().map(|stmt| &stmt.kind) { + Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))) + if lhs == switch_on => + { + match &discriminated.ty(body, tcx).ty.kind { + ty::Adt(def, _) => Some(def), + + // `Rvalue::Discriminant` is also used to get the active yield point for a + // generator, but we do not need edge-specific effects in that case. This may + // change in the future. + ty::Generator(..) => None, + + t => bug!("`discriminant` called on unexpected type {:?}", t), } } + + _ => None, } } From 7cf2bfb6578281b568735847549305059a3d6a48 Mon Sep 17 00:00:00 2001 From: Andre Richter Date: Fri, 28 Feb 2020 21:51:16 +0100 Subject: [PATCH 0599/1250] Fix no_std detection for target triples The current check for wether a target is no_std or not is matching for the string "-none-" in a target triple. This doesn't work for triples that end in "-none", like "aarch64-unknown-none". Fix this by matching for "-none" instead. I checked for all the current target triples containing "none", and this should not generate any false positives. This fixes an issue encountered in https://github.com/rust-lang/rust/pull/68334 --- src/bootstrap/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 746cddbabd6..56164b74f30 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -180,7 +180,7 @@ pub struct Target { impl Target { pub fn from_triple(triple: &str) -> Self { let mut target: Self = Default::default(); - if triple.contains("-none-") || triple.contains("nvptx") { + if triple.contains("-none") || triple.contains("nvptx") { target.no_std = true; } target From 6f568e72f336cd64fecb240c6aafbe4bf7ed4379 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Feb 2020 22:54:10 +0100 Subject: [PATCH 0600/1250] miri engine: turn some debug_assert into assert --- src/librustc_mir/interpret/cast.rs | 2 +- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_mir/interpret/operator.rs | 2 +- src/librustc_mir/interpret/place.rs | 10 ++++------ src/librustc_mir/interpret/step.rs | 2 +- src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/interpret/validity.rs | 6 +++--- 7 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/interpret/cast.rs b/src/librustc_mir/interpret/cast.rs index 9461a066902..78e7db44b87 100644 --- a/src/librustc_mir/interpret/cast.rs +++ b/src/librustc_mir/interpret/cast.rs @@ -202,7 +202,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Char => { // `u8` to `char` cast - debug_assert_eq!(v as u8 as u128, v); + assert_eq!(v as u8 as u128, v); Ok(Scalar::from_uint(v, Size::from_bytes(4))) } diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 1df389d9c8b..673afc6c06d 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -195,7 +195,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { kind: MemoryKind, ) -> Pointer { let id = self.tcx.alloc_map.lock().reserve(); - debug_assert_ne!( + assert_ne!( Some(kind), M::STATIC_KIND.map(MemoryKind::Machine), "dynamically allocating static memory" diff --git a/src/librustc_mir/interpret/operator.rs b/src/librustc_mir/interpret/operator.rs index 2e8c94903ca..3b074e7b5a2 100644 --- a/src/librustc_mir/interpret/operator.rs +++ b/src/librustc_mir/interpret/operator.rs @@ -234,7 +234,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { BitXor => (Scalar::from_uint(l ^ r, size), left_layout.ty), Add | Sub | Mul | Rem | Div => { - debug_assert!(!left_layout.abi.is_signed()); + assert!(!left_layout.abi.is_signed()); let op: fn(u128, u128) -> (u128, bool) = match bin_op { Add => u128::overflowing_add, Sub => u128::overflowing_sub, diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4f96cb69891..8215b4c5aa4 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -1130,12 +1130,10 @@ where let layout = self.layout_of(ty)?; // More sanity checks - if cfg!(debug_assertions) { - let (size, align) = self.read_size_and_align_from_vtable(vtable)?; - assert_eq!(size, layout.size); - // only ABI alignment is preserved - assert_eq!(align, layout.align.abi); - } + let (size, align) = self.read_size_and_align_from_vtable(vtable)?; + assert_eq!(size, layout.size); + // only ABI alignment is preserved + assert_eq!(align, layout.align.abi); let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..*mplace }, layout }; Ok((instance, mplace)) diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 7d59c0181a8..f298a6677d6 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -287,7 +287,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.eval_terminator(terminator)?; if !self.stack.is_empty() { // This should change *something* - debug_assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); + assert!(self.cur_frame() != old_stack || self.frame().block != old_bb); if let Some(block) = self.frame().block { info!("// executing {:?}", block); } diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index a02a6898c1d..28922f2c753 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -172,7 +172,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } let caller_arg = caller_arg.next().ok_or_else(|| err_unsup!(FunctionArgCountMismatch))?; if rust_abi { - debug_assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); + assert!(!caller_arg.layout.is_zst(), "ZSTs must have been already filtered out"); } // Now, check if !Self::check_argument_compat(rust_abi, caller_arg.layout, callee_arg.layout) { diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index aa2b3040a71..77c911a5165 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -142,16 +142,16 @@ fn wrapping_range_contains(r: &RangeInclusive, test: u128) -> bool { // "expected something " makes sense. fn wrapping_range_format(r: &RangeInclusive, max_hi: u128) -> String { let (lo, hi) = r.clone().into_inner(); - debug_assert!(hi <= max_hi); + assert!(hi <= max_hi); if lo > hi { format!("less or equal to {}, or greater or equal to {}", hi, lo) } else if lo == hi { format!("equal to {}", lo) } else if lo == 0 { - debug_assert!(hi < max_hi, "should not be printing if the range covers everything"); + assert!(hi < max_hi, "should not be printing if the range covers everything"); format!("less or equal to {}", hi) } else if hi == max_hi { - debug_assert!(lo > 0, "should not be printing if the range covers everything"); + assert!(lo > 0, "should not be printing if the range covers everything"); format!("greater or equal to {}", lo) } else { format!("in the range {:?}", r) From 2ad52cd16d9535383bfabaf47a56bf80858b91b0 Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Fri, 28 Feb 2020 19:28:26 -0500 Subject: [PATCH 0601/1250] Clarify explanation of 'fn resize' 1. Clarified on what should implement 'Clone' trait. 2. Minor grammar fix: to be able clone => to be able to clone --- src/liballoc/vec.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 29987ac44e6..bcbf931d162 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1472,8 +1472,9 @@ impl Vec { /// difference, with each additional slot filled with `value`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// - /// This method requires [`Clone`] to be able clone the passed value. If - /// you need more flexibility (or want to rely on [`Default`] instead of + /// This method requires `value` to implement [`Clone`], + /// in order to be able to clone the passed value. + /// If you need more flexibility (or want to rely on [`Default`] instead of /// [`Clone`]), use [`resize_with`]. /// /// # Examples From 85e59b7664734b3fb0122aa8d341ed7e878569c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 00:35:24 +0100 Subject: [PATCH 0602/1250] use .to_string() instead of format!() macro to create strings --- src/librustc/query/mod.rs | 2 +- src/librustc_attr/builtin.rs | 2 +- src/librustc_errors/diagnostic.rs | 6 +++--- .../infer/error_reporting/mod.rs | 2 +- src/librustc_lint/builtin.rs | 16 ++++++++-------- src/librustc_lint/types.rs | 6 +++--- .../borrow_check/diagnostics/mod.rs | 18 +++++++++--------- .../borrow_check/diagnostics/move_errors.rs | 4 ++-- src/librustc_mir/util/pretty.rs | 2 +- src/librustc_parse/parser/pat.rs | 2 +- src/librustc_passes/check_const.rs | 2 +- src/librustc_resolve/diagnostics.rs | 5 +++-- src/librustc_resolve/late/diagnostics.rs | 14 ++++++-------- src/librustc_typeck/check/op.rs | 4 ++-- src/librustc_typeck/collect.rs | 4 ++-- 15 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 69698eabac4..f3249f5014d 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -18,7 +18,7 @@ use std::borrow::Cow; fn describe_as_module(def_id: DefId, tcx: TyCtxt<'_>) -> String { if def_id.is_top_level_module() { - format!("top-level module") + "top-level module".to_string() } else { format!("module `{}`", tcx.def_path_str(def_id)) } diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index ac1a191fa23..e8deee5b1f3 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -53,7 +53,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) { err.span_suggestion( span, "consider removing the prefix", - format!("{}", &lint_str[1..]), + lint_str[1..].to_string(), Applicability::MaybeIncorrect, ); } diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index 189b5bd0f9e..1cc5daafed1 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -167,17 +167,17 @@ impl Diagnostic { found: DiagnosticStyledString, ) -> &mut Self { let mut msg: Vec<_> = - vec![(format!("required when trying to coerce from type `"), Style::NoStyle)]; + vec![("required when trying to coerce from type `".to_string(), Style::NoStyle)]; msg.extend(expected.0.iter().map(|x| match *x { StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), })); - msg.push((format!("` to type '"), Style::NoStyle)); + msg.push(("` to type '".to_string(), Style::NoStyle)); msg.extend(found.0.iter().map(|x| match *x { StringPart::Normal(ref s) => (s.to_owned(), Style::NoStyle), StringPart::Highlighted(ref s) => (s.to_owned(), Style::Highlight), })); - msg.push((format!("`"), Style::NoStyle)); + msg.push(("`".to_string(), Style::NoStyle)); // For now, just attach these as notes self.highlighted_note(msg); diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index fd103c4c336..bd133738db7 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -143,7 +143,7 @@ pub(super) fn note_and_explain_region( // uh oh, hope no user ever sees THIS ty::ReEmpty(ui) => (format!("the empty lifetime in universe {:?}", ui), None), - ty::RePlaceholder(_) => (format!("any other region"), None), + ty::RePlaceholder(_) => ("any other region".to_string(), None), // FIXME(#13998) RePlaceholder should probably print like // ReFree rather than dumping Debug output on the user. diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca3727d1755..4d03f4579fd 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1919,21 +1919,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { use rustc::ty::TyKind::*; match ty.kind { // Primitive types that don't like 0 as a value. - Ref(..) => Some((format!("references must be non-null"), None)), - 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 `!` type has no valid value"), None)), + Ref(..) => Some(("references must be non-null".to_string(), None)), + Adt(..) if ty.is_box() => Some(("`Box` must be non-null".to_string(), None)), + FnPtr(..) => Some(("function pointers must be non-null".to_string(), None)), + Never => Some(("the `!` type has no valid value".to_string(), None)), RawPtr(tm) if matches!(tm.ty.kind, Dynamic(..)) => // raw ptr to dyn Trait { - Some((format!("the vtable of a wide raw pointer must be non-null"), None)) + Some(("the vtable of a wide raw pointer must be non-null".to_string(), None)) } // Primitive types with other constraints. Bool if init == InitKind::Uninit => { - Some((format!("booleans must be either `true` or `false`"), None)) + Some(("booleans must be either `true` or `false`".to_string(), None)) } Char if init == InitKind::Uninit => { - Some((format!("characters must be a valid Unicode codepoint"), None)) + Some(("characters must be a valid Unicode codepoint".to_string(), None)) } // Recurse and checks for some compound types. Adt(adt_def, substs) if !adt_def.is_union() => { @@ -1961,7 +1961,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidValue { } // Now, recurse. match adt_def.variants.len() { - 0 => Some((format!("enums with no variants have no valid value"), None)), + 0 => Some(("enums with no variants have no valid value".to_string(), None)), 1 => { // Struct, or enum with exactly one variant. // Proceed recursively, check all fields. diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 703a6959ab2..6901a66b1ce 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -83,9 +83,9 @@ fn lint_overflowing_range_endpoint<'a, 'tcx>( // We need to preserve the literal's suffix, // as it may determine typing information. let suffix = match lit.node { - LitKind::Int(_, LitIntType::Signed(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsigned(s)) => format!("{}", s.name_str()), - LitKind::Int(_, LitIntType::Unsuffixed) => "".to_owned(), + LitKind::Int(_, LitIntType::Signed(s)) => s.name_str().to_string(), + LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str().to_string(), + LitKind::Int(_, LitIntType::Unsuffixed) => "".to_string(), _ => bug!(), }; let suggestion = format!("{}..={}{}", start, lit_val - 1, suffix); diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index ba4af59eede..cd6834a5a4d 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -619,14 +619,14 @@ pub(super) enum BorrowedContentSource<'tcx> { impl BorrowedContentSource<'tcx> { pub(super) fn describe_for_unnamed_place(&self) -> String { match *self { - BorrowedContentSource::DerefRawPointer => format!("a raw pointer"), - BorrowedContentSource::DerefSharedRef => format!("a shared reference"), - BorrowedContentSource::DerefMutableRef => format!("a mutable reference"), + BorrowedContentSource::DerefRawPointer => "a raw pointer".to_string(), + BorrowedContentSource::DerefSharedRef => "a shared reference".to_string(), + BorrowedContentSource::DerefMutableRef => "a mutable reference".to_string(), BorrowedContentSource::OverloadedDeref(ty) => { if ty.is_rc() { - format!("an `Rc`") + "an `Rc`".to_string() } else if ty.is_arc() { - format!("an `Arc`") + "an `Arc`".to_string() } else { format!("dereference of `{}`", ty) } @@ -649,16 +649,16 @@ impl BorrowedContentSource<'tcx> { pub(super) fn describe_for_immutable_place(&self) -> String { match *self { - BorrowedContentSource::DerefRawPointer => format!("a `*const` pointer"), - BorrowedContentSource::DerefSharedRef => format!("a `&` reference"), + BorrowedContentSource::DerefRawPointer => "a `*const` pointer".to_string(), + BorrowedContentSource::DerefSharedRef => "a `&` reference".to_string(), BorrowedContentSource::DerefMutableRef => { bug!("describe_for_immutable_place: DerefMutableRef isn't immutable") } BorrowedContentSource::OverloadedDeref(ty) => { if ty.is_rc() { - format!("an `Rc`") + "an `Rc`".to_string() } else if ty.is_arc() { - format!("an `Arc`") + "an `Arc`".to_string() } else { format!("a dereference of `{}`", ty) } diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 14f675c0fdf..27f0c0f1e47 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let place_ty = move_from.ty(*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(move_from.as_ref()) { Some(desc) => format!("`{}`", desc), - None => format!("value"), + None => "value".to_string(), }; self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span)); @@ -466,7 +466,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let place_ty = original_path.ty(*self.body, self.infcx.tcx).ty; let place_desc = match self.describe_place(original_path.as_ref()) { Some(desc) => format!("`{}`", desc), - None => format!("value"), + None => "value".to_string(), }; self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span)); diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index e0919e7e8f8..6fd8f06fe8f 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -477,7 +477,7 @@ fn write_scope_tree( indented_decl.push_str(";"); let local_name = - if local == RETURN_PLACE { format!(" return place") } else { String::new() }; + if local == RETURN_PLACE { " return place".to_string() } else { String::new() }; writeln!( w, diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 520d325f16b..4dc2f775173 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -216,7 +216,7 @@ impl<'a> Parser<'a> { .span_suggestion( seq_span, "...or a vertical bar to match on multiple alternatives", - format!("{}", seq_snippet.replace(",", " |")), + seq_snippet.replace(",", " |"), Applicability::MachineApplicable, ); } diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index b178110f4f9..d713a82fd88 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -35,7 +35,7 @@ impl NonConstExpr { match self { Self::Loop(src) => format!("`{}`", src.name()), Self::Match(src) => format!("`{}`", src.name()), - Self::OrPattern => format!("or-pattern"), + Self::OrPattern => "or-pattern".to_string(), } } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index b0206bb1a7a..d08ae3040bd 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -98,7 +98,7 @@ impl<'a> Resolver<'a> { E0401, "can't use generic parameters from outer function", ); - err.span_label(span, format!("use of generic parameter from outer function")); + err.span_label(span, "use of generic parameter from outer function".to_string()); let sm = self.session.source_map(); match outer_res { @@ -155,7 +155,8 @@ impl<'a> Resolver<'a> { } else if let Some(sp) = sm.generate_fn_name_span(span) { err.span_label( sp, - format!("try adding a local generic parameter in this method instead"), + "try adding a local generic parameter in this method instead" + .to_string(), ); } else { err.help("try using a local generic parameter instead"); diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index e2aa853e78c..b85f199edf3 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -177,7 +177,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { err.code(rustc_errors::error_code!(E0411)); err.span_label( span, - format!("`Self` is only available in impls, traits, and type definitions"), + "`Self` is only available in impls, traits, and type definitions".to_string(), ); return (err, Vec::new()); } @@ -186,12 +186,10 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { err.code(rustc_errors::error_code!(E0424)); err.span_label(span, match source { - PathSource::Pat => format!( - "`self` value is a keyword and may not be bound to variables or shadowed", - ), - _ => format!( - "`self` value is a keyword only available in methods with a `self` parameter", - ), + PathSource::Pat => "`self` value is a keyword and may not be bound to variables or shadowed" + .to_string(), + _ => "`self` value is a keyword only available in methods with a `self` parameter" + .to_string(), }); if let Some(span) = &self.diagnostic_metadata.current_function { err.span_label(*span, "this function doesn't have a `self` parameter"); @@ -558,7 +556,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { if is_expected(ctor_def) && !accessible_ctor { err.span_label( span, - format!("constructor is not visible here due to private fields"), + "constructor is not visible here due to private fields".to_string(), ); } } else { diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index 2c5dcdde5e8..b0d178794ea 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -605,7 +605,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if lstring.starts_with('&') { // let a = String::new(); // let _ = &a + "bar"; - format!("{}", &lstring[1..]) + lstring[1..].to_string() } else { format!("{}.to_owned()", lstring) }, @@ -633,7 +633,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let to_string = if l.starts_with('&') { // let a = String::new(); let b = String::new(); // let _ = &a + b; - format!("{}", &l[1..]) + l[1..].to_string() } else { format!("{}.to_owned()", l) }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 427bcab632d..166f2337c98 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -160,7 +160,7 @@ crate fn placeholder_type_error( }) { // Account for `_` already present in cases like `struct S<_>(_);` and suggest // `struct S(T);` instead of `struct S<_, T>(T);`. - sugg.push((arg.span, format!("{}", type_name))); + sugg.push((arg.span, type_name.to_string())); } else { sugg.push(( generics.iter().last().unwrap().span.shrink_to_hi(), @@ -475,7 +475,7 @@ fn get_new_lifetime_name<'tcx>( let a_to_z_repeat_n = |n| { (b'a'..=b'z').map(move |c| { - let mut s = format!("'"); + let mut s = '\''.to_string(); s.extend(std::iter::repeat(char::from(c)).take(n)); s }) From f55b2c9b12144375bfbe31f7c6b27105e601edb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 02:16:04 +0100 Subject: [PATCH 0603/1250] remove unneeded .as_ref() calls. --- src/librustc_privacy/lib.rs | 2 +- src/librustc_typeck/collect/type_of.rs | 2 +- src/libstd/path.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ef1e99c5a64..fd84be919d4 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -657,7 +657,7 @@ impl EmbargoVisitor<'tcx> { .map(|module_hir_id| self.tcx.hir().expect_item(module_hir_id)) { if let hir::ItemKind::Mod(m) = &item.kind { - for item_id in m.item_ids.as_ref() { + for item_id in m.item_ids { let item = self.tcx.hir().expect_item(item_id.id); let def_id = self.tcx.hir().local_def_id(item_id.id); if !self.tcx.hygienic_eq(segment.ident, item.ident, def_id) { diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 2ba97055a68..ec87112b7a8 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -239,7 +239,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .segments .iter() .filter_map(|seg| seg.args.as_ref()) - .map(|generic_args| generic_args.args.as_ref()) + .map(|generic_args| generic_args.args) .find_map(|args| { args.iter() .filter(|arg| arg.is_const()) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index a703cb748e0..b8361d3e825 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -2011,7 +2011,7 @@ impl Path { #[stable(feature = "rust1", since = "1.0.0")] pub fn file_name(&self) -> Option<&OsStr> { self.components().next_back().and_then(|p| match p { - Component::Normal(p) => Some(p.as_ref()), + Component::Normal(p) => Some(p), _ => None, }) } From a8a153b1a93996b73aafb1f1e93eb041778b09dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 02:48:27 +0100 Subject: [PATCH 0604/1250] don't use question mark operator on Err(), return the Result directly instead. --- src/librustc_save_analysis/sig.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 9670fb1e2c4..ad439e3950e 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -430,7 +430,7 @@ impl Sig for ast::Item { sig.text.push_str(" = "); let ty = match ty { Some(ty) => ty.make(offset + sig.text.len(), id, scx)?, - None => Err("Ty")?, + None => return Err("Ty"), }; sig.text.push_str(&ty.text); sig.text.push(';'); From de7c40c1686c1c4be74f14493c4b12955e9ed5f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 03:05:14 +0100 Subject: [PATCH 0605/1250] use .iter() instead of .into_iter() on references. --- src/librustc/ty/context.rs | 4 ++-- src/librustc_builtin_macros/proc_macro_harness.rs | 2 +- src/librustc_infer/infer/canonical/query_response.rs | 2 +- src/librustc_infer/traits/on_unimplemented.rs | 6 ++---- src/librustc_infer/traits/select.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_mir/borrow_check/diagnostics/move_errors.rs | 2 +- src/librustc_mir/dataflow/generic/engine.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 2 +- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 6 ++---- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/uninhabited_enum_branching.rs | 2 +- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_span/source_map.rs | 4 ++-- src/librustc_traits/lowering/mod.rs | 2 +- src/librustdoc/clean/mod.rs | 6 +++--- src/librustdoc/html/markdown.rs | 4 ++-- src/librustdoc/html/render/cache.rs | 2 +- 19 files changed, 26 insertions(+), 30 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 823cbf0966d..7f687060403 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2291,13 +2291,13 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn intern_tup(self, ts: &[Ty<'tcx>]) -> Ty<'tcx> { - let kinds: Vec<_> = ts.into_iter().map(|&t| GenericArg::from(t)).collect(); + let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); self.mk_ty(Tuple(self.intern_substs(&kinds))) } pub fn mk_tup], Ty<'tcx>>>(self, iter: I) -> I::Output { iter.intern_with(|ts| { - let kinds: Vec<_> = ts.into_iter().map(|&t| GenericArg::from(t)).collect(); + let kinds: Vec<_> = ts.iter().map(|&t| GenericArg::from(t)).collect(); self.mk_ty(Tuple(self.intern_substs(&kinds))) }) } diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index b925cad9fdc..8c1675ad29d 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -149,7 +149,7 @@ impl<'a> CollectProcMacros<'a> { .span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`"); &[] }) - .into_iter() + .iter() .filter_map(|attr| { let attr = match attr.meta_item() { Some(meta_item) => meta_item, diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs index f4196e57605..72fad3828ef 100644 --- a/src/librustc_infer/infer/canonical/query_response.rs +++ b/src/librustc_infer/infer/canonical/query_response.rs @@ -630,7 +630,7 @@ pub fn make_query_region_constraints<'tcx>( assert!(givens.is_empty()); let outlives: Vec<_> = constraints - .into_iter() + .iter() .map(|(k, _)| match *k { // Swap regions because we are going from sub (<=) to outlives // (>=). diff --git a/src/librustc_infer/traits/on_unimplemented.rs b/src/librustc_infer/traits/on_unimplemented.rs index 41201c1c7ae..24741462f43 100644 --- a/src/librustc_infer/traits/on_unimplemented.rs +++ b/src/librustc_infer/traits/on_unimplemented.rs @@ -237,10 +237,8 @@ impl<'tcx> OnUnimplementedDirective { } } - let options: FxHashMap = options - .into_iter() - .filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))) - .collect(); + let options: FxHashMap = + options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); OnUnimplementedNote { label: label.map(|l| l.format(tcx, trait_ref, &options)), message: message.map(|m| m.format(tcx, trait_ref, &options)), diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index c6878fad2a4..3938faf3c21 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2411,7 +2411,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { types .skip_binder() - .into_iter() + .iter() .flat_map(|ty| { // binder moved -\ let ty: ty::Binder> = ty::Binder::bind(ty); // <----/ diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ca3727d1755..c3ff30709b6 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -739,7 +739,7 @@ impl EarlyLintPass for DeprecatedAttr { } fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &[ast::Attribute]) { - let mut attrs = attrs.into_iter().peekable(); + let mut attrs = attrs.iter().peekable(); // Accumulate a single span for sugared doc comments. let mut sugared_span: Option = None; diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 14f675c0fdf..c770a4fb4f4 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -519,7 +519,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } fn add_move_error_details(&self, err: &mut DiagnosticBuilder<'a>, binds_to: &[Local]) { - for (j, local) in binds_to.into_iter().enumerate() { + for (j, local) in binds_to.iter().enumerate() { let bind_to = &self.body.local_decls[*local]; let binding_span = bind_to.source_info.span; diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index 371bfa9a6fd..d433a4a48d3 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -419,7 +419,7 @@ impl RustcMirAttrs { let mut ret = RustcMirAttrs::default(); let rustc_mir_attrs = attrs - .into_iter() + .iter() .filter(|attr| attr.check_name(sym::rustc_mir)) .flat_map(|attr| attr.meta_item_list().into_iter().flat_map(|v| v.into_iter())); diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 74d1094f964..a7c0efd63b1 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx> Borrows<'a, 'tcx> { .local_map .get(&place.local) .into_iter() - .flat_map(|bs| bs.into_iter()) + .flat_map(|bs| bs.iter()) .copied(); // If the borrowed place is a local with no projections, all other borrows of this diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 14b8a341e26..a035dff9f5a 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -509,7 +509,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { &self, ops: &[mir::Operand<'tcx>], ) -> InterpResult<'tcx, Vec>> { - ops.into_iter().map(|op| self.eval_operand(op, None)).collect() + ops.iter().map(|op| self.eval_operand(op, None)).collect() } // Used when the miri-engine runs into a constant and for extracting information from constants diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 0fa7d6a9b72..f6a93363dc1 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -401,10 +401,8 @@ fn record_accesses<'tcx>( // We collect this into a `SmallVec` to avoid calling `is_inlining_candidate` in the lock. // FIXME: Call `is_inlining_candidate` when pushing to `neighbors` in `collect_items_rec` // instead to avoid creating this `SmallVec`. - let accesses: SmallVec<[_; 128]> = callees - .into_iter() - .map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))) - .collect(); + let accesses: SmallVec<[_; 128]> = + callees.iter().map(|mono_item| (*mono_item, is_inlining_candidate(mono_item))).collect(); inlining_map.lock_mut().record_accesses(caller, &accesses); } diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index fab55018d30..4dcbcdcbae4 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -644,7 +644,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) { } } - let mut unsafe_blocks: Vec<_> = unsafe_blocks.into_iter().collect(); + let mut unsafe_blocks: Vec<_> = unsafe_blocks.iter().collect(); unsafe_blocks.sort_by_cached_key(|(hir_id, _)| tcx.hir().hir_to_node_id(*hir_id)); let used_unsafe: FxHashSet<_> = unsafe_blocks.iter().flat_map(|&&(id, used)| used.then_some(id)).collect(); diff --git a/src/librustc_mir/transform/uninhabited_enum_branching.rs b/src/librustc_mir/transform/uninhabited_enum_branching.rs index 0bf0ff2852d..190405f5e99 100644 --- a/src/librustc_mir/transform/uninhabited_enum_branching.rs +++ b/src/librustc_mir/transform/uninhabited_enum_branching.rs @@ -100,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { &mut body.basic_blocks_mut()[bb].terminator_mut().kind { let vals = &*values; - let zipped = vals.iter().zip(targets.into_iter()); + let zipped = vals.iter().zip(targets.iter()); let mut matched_values = Vec::with_capacity(allowed_variants.len()); let mut matched_targets = Vec::with_capacity(allowed_variants.len() + 1); diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index b0206bb1a7a..abbda0ca154 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1425,7 +1425,7 @@ crate fn show_candidates( // we want consistent results across executions, but candidates are produced // by iterating through a hash map, so make sure they are ordered: let mut path_strings: Vec<_> = - candidates.into_iter().map(|c| path_names_to_string(&c.path)).collect(); + candidates.iter().map(|c| path_names_to_string(&c.path)).collect(); path_strings.sort(); path_strings.dedup(); diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 31d397f040c..320039b7c91 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -395,7 +395,7 @@ impl SourceMap { .unwrap_or_else(|x| x); let special_chars = end_width_idx - start_width_idx; let non_narrow: usize = f.non_narrow_chars[start_width_idx..end_width_idx] - .into_iter() + .iter() .map(|x| x.width()) .sum(); col.0 - special_chars + non_narrow @@ -413,7 +413,7 @@ impl SourceMap { .binary_search_by_key(&pos, |x| x.pos()) .unwrap_or_else(|x| x); let non_narrow: usize = - f.non_narrow_chars[0..end_width_idx].into_iter().map(|x| x.width()).sum(); + f.non_narrow_chars[0..end_width_idx].iter().map(|x| x.width()).sum(); chpos.0 - end_width_idx + non_narrow }; Loc { file: f, line: 0, col: chpos, col_display } diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index b77c603da9a..e0c3dc8a961 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -256,7 +256,7 @@ fn program_clauses_for_trait(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { // `WellFormed(WC)` let wf_conditions = where_clauses - .into_iter() + .iter() .map(|wc| wc.subst(tcx, bound_vars)) .map(|wc| wc.map_bound(|goal| goal.into_well_formed_goal())); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 50c780e9ecb..06444f03f5d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2388,9 +2388,9 @@ impl Clean for hir::TypeBindingKind<'_> { hir::TypeBindingKind::Equality { ref ty } => { TypeBindingKind::Equality { ty: ty.clean(cx) } } - hir::TypeBindingKind::Constraint { ref bounds } => TypeBindingKind::Constraint { - bounds: bounds.into_iter().map(|b| b.clean(cx)).collect(), - }, + hir::TypeBindingKind::Constraint { ref bounds } => { + TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() } + } } } } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ff6431640d3..ed007fe383c 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -738,7 +738,7 @@ impl Markdown<'_> { return String::new(); } let replacer = |_: &str, s: &str| { - if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) { + if let Some(&(_, ref replace)) = links.iter().find(|link| &*link.0 == s) { Some((replace.clone(), s.to_owned())) } else { None @@ -816,7 +816,7 @@ impl MarkdownSummaryLine<'_> { } let replacer = |_: &str, s: &str| { - if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) { + if let Some(&(_, ref replace)) = links.iter().find(|link| &*link.0 == s) { Some((replace.clone(), s.to_owned())) } else { None diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index e9ebccb7ec0..a0a35e4ce4b 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -670,7 +670,7 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option match *clean_type { clean::ResolvedPath { ref path, .. } => { let segments = &path.segments; - let path_segment = segments.into_iter().last().unwrap_or_else(|| panic!( + let path_segment = segments.iter().last().unwrap_or_else(|| panic!( "get_index_type_name(clean_type: {:?}, accept_generic: {:?}) had length zero path", clean_type, accept_generic )); From 542d813475eeac7cac1bae5de32fe7809b4bf771 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 11 Feb 2020 14:38:16 +0100 Subject: [PATCH 0606/1250] Add a `parent_module_from_def_id` query --- src/librustc/hir/mod.rs | 11 ++++++++++- src/librustc/query/mod.rs | 4 ++++ src/librustc/ty/mod.rs | 6 ++---- src/librustc_lint/unused.rs | 3 +-- src/librustc_mir_build/hair/pattern/check_match.rs | 2 +- src/librustc_passes/liveness.rs | 4 ++-- src/librustc_privacy/lib.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 4 ++-- src/librustdoc/passes/collect_intra_doc_links.rs | 2 +- 9 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 7d48280661a..4ce335d0c95 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -7,9 +7,10 @@ pub mod map; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_hir::def_id::LOCAL_CRATE; +use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::print; use rustc_hir::Crate; +use rustc_hir::HirId; use std::ops::Deref; /// A wrapper type which allows you to access HIR. @@ -45,9 +46,17 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hir(self) -> Hir<'tcx> { Hir { tcx: self, map: &self.hir_map } } + + pub fn parent_module(self, id: HirId) -> DefId { + self.parent_module_from_def_id(DefId::local(id.owner)) + } } pub fn provide(providers: &mut Providers<'_>) { + providers.parent_module_from_def_id = |tcx, id| { + let hir = tcx.hir(); + hir.get_module_parent(hir.as_local_hir_id(id).unwrap()) + }; providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); map::provide(providers); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 69698eabac4..542a0033ade 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -98,6 +98,10 @@ rustc_queries! { eval_always desc { "computing the lint levels for items in this crate" } } + + query parent_module_from_def_id(_: DefId) -> DefId { + eval_always + } } Codegen { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index dae9f945ce0..8105f4faa0f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -385,9 +385,7 @@ impl Visibility { Res::Err => Visibility::Public, def => Visibility::Restricted(def.def_id()), }, - hir::VisibilityKind::Inherited => { - Visibility::Restricted(tcx.hir().get_module_parent(id)) - } + hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)), } } @@ -3087,7 +3085,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(actual_expansion) => { self.hir().definitions().parent_module_of_macro_def(actual_expansion) } - None => self.hir().get_module_parent(block), + None => self.parent_module(block), }; (ident, scope) } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 7870b9da4cb..60316a8db4f 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -124,8 +124,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_post: &str, plural_len: usize, ) -> bool { - if ty.is_unit() - || cx.tcx.is_ty_uninhabited_from(cx.tcx.hir().get_module_parent(expr.hir_id), ty) + if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty) { return true; } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 3dfe826ad2a..6dd6f8ad43f 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -142,7 +142,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { } fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { - let module = self.tcx.hir().get_module_parent(hir_id); + let module = self.tcx.parent_module(hir_id); MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx)); } diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index f0bb3cd08ad..4a7df8b3f0e 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1125,7 +1125,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - let m = self.ir.tcx.hir().get_module_parent(expr.hir_id); + let m = self.ir.tcx.parent_module(expr.hir_id); let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { @@ -1136,7 +1136,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - let m = self.ir.tcx.hir().get_module_parent(expr.hir_id); + let m = self.ir.tcx.parent_module(expr.hir_id); let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { self.s.exit_ln } else { diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ef1e99c5a64..6867aac9f8f 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>( } Node::Expr(expr) => { return ( - ty::Visibility::Restricted(tcx.hir().get_module_parent(expr.hir_id)), + ty::Visibility::Restricted(tcx.parent_module(expr.hir_id)), expr.span, "private", ); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index ea83b40a1cb..76614ca4fe2 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -426,7 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some((field, field_ty)) = field_receiver { - let scope = self.tcx.hir().get_module_parent(self.body_id); + let scope = self.tcx.parent_module(self.body_id); let is_accessible = field.vis.is_accessible_from(scope, self.tcx); if is_accessible { @@ -685,7 +685,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { mut msg: String, candidates: Vec, ) { - let module_did = self.tcx.hir().get_module_parent(self.body_id); + let module_did = self.tcx.parent_module(self.body_id); let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap(); let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 0b27e5cf806..5a2706ae20a 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| { // FIXME: this fails hard for impls in non-module scope, but is necessary for the // current `resolve()` implementation. - match self.cx.tcx.hir().get_module_parent_node(hir_id) { + match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id)).unwrap() { id if id != hir_id => Some(id), _ => None, } From 98251d8fb25eac95df205b79b11217b45d924efd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 22 Feb 2020 19:53:10 +0100 Subject: [PATCH 0607/1250] Reduce visibility of `get_module_parent_node` and remove `get_module_parent` --- src/librustc/hir/map/mod.rs | 8 +------- src/librustc/hir/mod.rs | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f7301280acd..d3de20fd970 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -746,15 +746,9 @@ impl<'hir> Map<'hir> { hir_id } - /// Returns the `DefId` of `id`'s nearest module parent, or `id` itself if no - /// module parent is in this map. - pub fn get_module_parent(&self, id: HirId) -> DefId { - self.local_def_id(self.get_module_parent_node(id)) - } - /// Returns the `HirId` of `id`'s nearest module parent, or `id` itself if no /// module parent is in this map. - pub fn get_module_parent_node(&self, hir_id: HirId) -> HirId { + pub(super) fn get_module_parent_node(&self, hir_id: HirId) -> HirId { for (hir_id, node) in self.parent_iter(hir_id) { if let Node::Item(&Item { kind: ItemKind::Mod(_), .. }) = node { return hir_id; diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 4ce335d0c95..1aa3b27bd1a 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -55,7 +55,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn provide(providers: &mut Providers<'_>) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.get_module_parent(hir.as_local_hir_id(id).unwrap()) + hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap())) }; providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); map::provide(providers); From 21cd1fe0bddf68062d6edd858781eaffd0dfcaaa Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 28 Feb 2020 20:57:36 -0800 Subject: [PATCH 0608/1250] Process `RequiresStorage` results in pre-order Reverse post-order requires an allocation. --- src/librustc_mir/transform/generator.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 770f93517d0..3107be1b622 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -619,8 +619,9 @@ fn compute_storage_conflicts( local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), }; - // FIXME: Do we need to do this in RPO? - requires_storage.visit_in_rpo_with(body, &mut visitor); + // Visit only reachable basic blocks. The exact order is not important. + let reachable_blocks = traversal::preorder(body).map(|(bb, _)| bb); + requires_storage.visit_with(body, reachable_blocks, &mut visitor); let local_conflicts = visitor.local_conflicts; From fb46d2b82e9d2cf6b9916b533dafb6b29857eaec Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Sat, 29 Feb 2020 00:52:32 -0500 Subject: [PATCH 0609/1250] Update src/liballoc/vec.rs Following suggestion from @jonas-schievink Co-Authored-By: Jonas Schievink --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index bcbf931d162..7a0c2c264bf 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1472,7 +1472,7 @@ impl Vec { /// difference, with each additional slot filled with `value`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// - /// This method requires `value` to implement [`Clone`], + /// This method requires `T` to implement [`Clone`], /// in order to be able to clone the passed value. /// If you need more flexibility (or want to rely on [`Default`] instead of /// [`Clone`]), use [`resize_with`]. From 6e265c5bc58ddf830445054907c69369d6b84162 Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Sat, 29 Feb 2020 00:55:05 -0500 Subject: [PATCH 0610/1250] Remove trailing whitespace Removed trailing whitespace which caused to fail pretty-check --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 7a0c2c264bf..55b313a9032 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1472,7 +1472,7 @@ impl Vec { /// difference, with each additional slot filled with `value`. /// If `new_len` is less than `len`, the `Vec` is simply truncated. /// - /// This method requires `T` to implement [`Clone`], + /// This method requires `T` to implement [`Clone`], /// in order to be able to clone the passed value. /// If you need more flexibility (or want to rely on [`Default`] instead of /// [`Clone`]), use [`resize_with`]. From 503026b622d1095770178fbe606a4ba783216992 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 Nov 2019 17:21:37 +0100 Subject: [PATCH 0611/1250] mem::zeroed/uninit: panic on types that do not permit zero-initialization --- src/libcore/intrinsics.rs | 10 ++ src/libcore/mem/mod.rs | 6 + src/librustc/ty/layout.rs | 30 ----- src/librustc_codegen_ssa/mir/block.rs | 31 ++++- src/librustc_index/vec.rs | 2 +- src/librustc_target/abi/mod.rs | 115 ++++++++++++++++++ src/librustc_target/lib.rs | 3 + src/librustc_typeck/check/intrinsic.rs | 5 +- .../intrinsics/panic-uninitialized-zeroed.rs | 113 +++++++++++++++++ .../never_type/panic-uninitialized-zeroed.rs | 102 ---------------- 10 files changed, 280 insertions(+), 137 deletions(-) create mode 100644 src/test/ui/intrinsics/panic-uninitialized-zeroed.rs delete mode 100644 src/test/ui/never_type/panic-uninitialized-zeroed.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 94928211a97..c02dabcacde 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -721,6 +721,16 @@ extern "rust-intrinsic" { /// This will statically either panic, or do nothing. pub fn panic_if_uninhabited(); + /// A guard for unsafe functions that cannot ever be executed if `T` does not permit + /// zero-initialization: This will statically either panic, or do nothing. + #[cfg(not(bootstrap))] + pub fn panic_if_zero_invalid(); + + /// A guard for unsafe functions that cannot ever be executed if `T` has invalid + /// bit patterns: This will statically either panic, or do nothing. + #[cfg(not(bootstrap))] + pub fn panic_if_any_invalid(); + /// Gets a reference to a static `Location` indicating where it was called. #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")] pub fn caller_location() -> &'static crate::panic::Location<'static>; diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 9eb151cf528..124eb37fff1 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -495,6 +495,9 @@ pub const fn needs_drop() -> bool { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_zeroed"] pub unsafe fn zeroed() -> T { + #[cfg(not(bootstrap))] + intrinsics::panic_if_zero_invalid::(); + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); intrinsics::init() } @@ -528,6 +531,9 @@ pub unsafe fn zeroed() -> T { #[allow(deprecated)] #[rustc_diagnostic_item = "mem_uninitialized"] pub unsafe fn uninitialized() -> T { + #[cfg(not(bootstrap))] + intrinsics::panic_if_any_invalid::(); + #[cfg(bootstrap)] intrinsics::panic_if_uninhabited::(); intrinsics::uninit() } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e8bf2eb9a12..6b5f540e5b8 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1907,36 +1907,6 @@ impl<'tcx, T: HasTyCtxt<'tcx>> HasTyCtxt<'tcx> for LayoutCx<'tcx, T> { } } -pub trait MaybeResult { - type Error; - - fn from(x: Result) -> Self; - fn to_result(self) -> Result; -} - -impl MaybeResult for T { - type Error = !; - - fn from(x: Result) -> Self { - let Ok(x) = x; - x - } - fn to_result(self) -> Result { - Ok(self) - } -} - -impl MaybeResult for Result { - type Error = E; - - fn from(x: Result) -> Self { - x - } - fn to_result(self) -> Result { - self - } -} - pub type TyLayout<'tcx> = ::rustc_target::abi::TyLayout<'tcx, Ty<'tcx>>; impl<'tcx> LayoutOf for LayoutCx<'tcx, TyCtxt<'tcx>> { diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index a1b54607b80..923e2486ace 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -521,11 +521,36 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } // Emit a panic or a no-op for `panic_if_uninhabited`. - if intrinsic == Some("panic_if_uninhabited") { + // These are intrinsics that compile to panics so that we can get a message + // which mentions the offending type, even from a const context. + #[derive(Debug, PartialEq)] + enum PanicIntrinsic { IfUninhabited, IfZeroInvalid, IfAnyInvalid }; + let panic_intrinsic = intrinsic.and_then(|i| match i { + "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), + "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), + "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), + _ => None + }); + if let Some(intrinsic) = panic_intrinsic { + use PanicIntrinsic::*; let ty = instance.unwrap().substs.type_at(0); let layout = bx.layout_of(ty); - if layout.abi.is_uninhabited() { - let msg_str = format!("Attempted to instantiate uninhabited type {}", ty); + let do_panic = match intrinsic { + IfUninhabited => layout.abi.is_uninhabited(), + IfZeroInvalid => // We unwrap as the error type is `!`. + !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(), + IfAnyInvalid => // We unwrap as the error type is `!`. + !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(), + }; + if do_panic { + let msg_str = if layout.abi.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{}`", ty) + } else if intrinsic == IfZeroInvalid { + format!("attempted to zero-initialize type `{}`, which is invalid", ty) + } else { + format!("attempted to leave type `{}` uninitialized, which is invalid", ty) + }; let msg = bx.const_str(Symbol::intern(&msg_str)); let location = self.get_caller_location(&mut bx, span).immediate(); diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 1dfe97238a3..7020939fa20 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -196,7 +196,7 @@ macro_rules! newtype_index { #[inline] fn index(self) -> usize { - usize::from(self) + self.as_usize() } } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index edd0ba46f75..13a0eb66f32 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -919,6 +919,7 @@ impl<'a, Ty> Deref for TyLayout<'a, Ty> { } } +/// Trait for context types that can compute layouts of things. pub trait LayoutOf { type Ty; type TyLayout; @@ -929,6 +930,39 @@ pub trait LayoutOf { } } +/// The `TyLayout` above will always be a `MaybeResult>`. +/// We can't add the bound due to the lifetime, but this trait is still useful when +/// writing code that's generic over the `LayoutOf` impl. +pub trait MaybeResult { + type Error; + + fn from(x: Result) -> Self; + fn to_result(self) -> Result; +} + +impl MaybeResult for T { + type Error = !; + + fn from(x: Result) -> Self { + let Ok(x) = x; + x + } + fn to_result(self) -> Result { + Ok(self) + } +} + +impl MaybeResult for Result { + type Error = E; + + fn from(x: Result) -> Self { + x + } + fn to_result(self) -> Result { + self + } +} + #[derive(Copy, Clone, PartialEq, Eq)] pub enum PointerKind { /// Most general case, we know no restrictions to tell LLVM. @@ -969,6 +1003,9 @@ impl<'a, Ty> TyLayout<'a, Ty> { { Ty::for_variant(self, cx, variant_index) } + + /// Callers might want to use `C: LayoutOf>` + /// to allow recursion (see `might_permit_zero_init` below for an example). pub fn field(self, cx: &C, i: usize) -> C::TyLayout where Ty: TyLayoutMethods<'a, C>, @@ -976,6 +1013,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { { Ty::field(self, cx, i) } + pub fn pointee_info_at(self, cx: &C, offset: Size) -> Option where Ty: TyLayoutMethods<'a, C>, @@ -999,4 +1037,81 @@ impl<'a, Ty> TyLayout<'a, Ty> { Abi::Aggregate { sized } => sized && self.size.bytes() == 0, } } + + /// Determines if this type permits "raw" initialization by just transmuting some + /// memory into an instance of `T`. + /// `zero` indicates if the memory is zero-initialized, or alternatively + /// left entirely uninitialized. + /// This is conservative: in doubt, it will answer `true`. + pub fn might_permit_raw_init( + self, + cx: &C, + zero: bool, + ) -> Result + where + Self: Copy, + Ty: TyLayoutMethods<'a, C>, + C: LayoutOf> + { + let scalar_allows_raw_init = move |s: &Scalar| -> bool { + let range = &s.valid_range; + if zero { + // The range must contain 0. + range.contains(&0) || + (*range.start() > *range.end()) // wrap-around allows 0 + } else { + // The range must include all values. + *range.start() == range.end().wrapping_add(1) + } + }; + + // Abi is the most informative here. + let res = match &self.abi { + Abi::Uninhabited => false, // definitely UB + Abi::Scalar(s) => scalar_allows_raw_init(s), + Abi::ScalarPair(s1, s2) => + scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), + Abi::Vector { element: s, count } => + *count == 0 || scalar_allows_raw_init(s), + Abi::Aggregate { .. } => { + match self.variants { + Variants::Multiple { .. } => + if zero { + // FIXME: could we identify the variant with discriminant 0, check that? + true + } else { + // FIXME: This needs to have some sort of discriminant, + // which cannot be undef. But for now we are conservative. + true + }, + Variants::Single { .. } => { + // For aggregates, recurse. + match self.fields { + FieldPlacement::Union(..) => true, // An all-0 unit is fine. + FieldPlacement::Array { .. } => + // FIXME: The widely use smallvec 0.6 creates uninit arrays + // with any element type, so let us not (yet) complain about that. + // count == 0 || + // self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? + true, + FieldPlacement::Arbitrary { ref offsets, .. } => { + let mut res = true; + // Check that all fields accept zero-init. + for idx in 0..offsets.len() { + let field = self.field(cx, idx).to_result()?; + if !field.might_permit_raw_init(cx, zero)? { + res = false; + break; + } + } + res + } + } + } + } + } + }; + trace!("might_permit_raw_init({:?}, zero={}) = {}", self.details, zero, res); + Ok(res) + } } diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 71150e74f70..3c397eb444d 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -10,6 +10,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] #![feature(nll)] +#![feature(never_type)] +#![feature(associated_type_bounds)] +#![feature(exhaustive_patterns)] #[macro_use] extern crate log; diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3572eda5c13..321932fb193 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -147,7 +147,10 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ), "rustc_peek" => (1, vec![param(0)], param(0)), "caller_location" => (0, vec![], tcx.caller_location_ty()), - "panic_if_uninhabited" => (1, Vec::new(), tcx.mk_unit()), + "panic_if_uninhabited" | + "panic_if_zero_invalid" | + "panic_if_any_invalid" => + (1, Vec::new(), tcx.mk_unit()), "init" => (1, Vec::new(), param(0)), "uninit" => (1, Vec::new(), param(0)), "forget" => (1, vec![param(0)], tcx.mk_unit()), diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs new file mode 100644 index 00000000000..937f949a7b0 --- /dev/null +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -0,0 +1,113 @@ +// run-pass +// ignore-wasm32-bare compiled with panic=abort by default + +// This test checks panic emitted from `mem::{uninitialized,zeroed}`. + +#![feature(never_type)] +#![allow(deprecated, invalid_value)] + +use std::{mem, panic}; +use std::ptr::NonNull; + +#[allow(dead_code)] +struct Foo { + x: u8, + y: !, +} + +enum Bar {} + +#[allow(dead_code)] +enum OneVariant { Variant(i32) } + +fn test_panic_msg(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { + let err = panic::catch_unwind(op).err(); + assert_eq!( + err.as_ref().and_then(|a| a.downcast_ref::()).map(|s| &**s), + Some(msg) + ); +} + +fn main() { + unsafe { + // Uninitialized types + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `!`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `!`" + ); + test_panic_msg( + || mem::MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `!`" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `Foo`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `Foo`" + ); + test_panic_msg( + || mem::MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `Foo`" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to instantiate uninhabited type `Bar`" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to instantiate uninhabited type `Bar`" + ); + test_panic_msg( + || mem::MaybeUninit::::uninit().assume_init(), + "attempted to instantiate uninhabited type `Bar`" + ); + + // Types that do not like zero-initialziation + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `fn()` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `fn()`, which is invalid" + ); + + test_panic_msg( + || mem::uninitialized::<*const dyn Send>(), + "attempted to leave type `*const dyn std::marker::Send` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::zeroed::<*const dyn Send>(), + "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" + ); + + test_panic_msg( + || mem::uninitialized::<(NonNull, u32, u32)>(), + "attempted to leave type `(std::ptr::NonNull, u32, u32)` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::<(NonNull, u32, u32)>(), + "attempted to zero-initialize type `(std::ptr::NonNull, u32, u32)`, \ + which is invalid" + ); + + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `bool` uninitialized, which is invalid" + ); + + // Some things that should work. + let _val = mem::zeroed::(); + let _val = mem::zeroed::(); + let _val = mem::zeroed::>(); + } +} diff --git a/src/test/ui/never_type/panic-uninitialized-zeroed.rs b/src/test/ui/never_type/panic-uninitialized-zeroed.rs deleted file mode 100644 index e0c30160b9e..00000000000 --- a/src/test/ui/never_type/panic-uninitialized-zeroed.rs +++ /dev/null @@ -1,102 +0,0 @@ -// run-pass -// ignore-wasm32-bare compiled with panic=abort by default -// This test checks that instantiating an uninhabited type via `mem::{uninitialized,zeroed}` results -// in a runtime panic. - -#![feature(never_type)] -#![allow(deprecated, invalid_value)] - -use std::{mem, panic}; - -#[allow(dead_code)] -struct Foo { - x: u8, - y: !, -} - -enum Bar {} - -fn main() { - unsafe { - assert_eq!( - panic::catch_unwind(|| { - mem::uninitialized::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type !" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::zeroed::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type !" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::MaybeUninit::::uninit().assume_init() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type !" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::uninitialized::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Foo" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::zeroed::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Foo" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::MaybeUninit::::uninit().assume_init() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Foo" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::uninitialized::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Bar" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::zeroed::() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Bar" - })), - Some(true) - ); - - assert_eq!( - panic::catch_unwind(|| { - mem::MaybeUninit::::uninit().assume_init() - }).err().and_then(|a| a.downcast_ref::().map(|s| { - s == "Attempted to instantiate uninhabited type Bar" - })), - Some(true) - ); - } -} From 6fd909b2b1dd2789e0f1af79283c6105fa502ca3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Nov 2019 11:07:00 +0100 Subject: [PATCH 0612/1250] reference tracking issue --- src/librustc_target/abi/mod.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 13a0eb66f32..4e4ef469090 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -1077,10 +1077,11 @@ impl<'a, Ty> TyLayout<'a, Ty> { match self.variants { Variants::Multiple { .. } => if zero { - // FIXME: could we identify the variant with discriminant 0, check that? + // FIXME(#66151): + // could we identify the variant with discriminant 0, check that? true } else { - // FIXME: This needs to have some sort of discriminant, + // FIXME(#66151): This needs to have some sort of discriminant, // which cannot be undef. But for now we are conservative. true }, @@ -1089,7 +1090,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { match self.fields { FieldPlacement::Union(..) => true, // An all-0 unit is fine. FieldPlacement::Array { .. } => - // FIXME: The widely use smallvec 0.6 creates uninit arrays + // FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays // with any element type, so let us not (yet) complain about that. // count == 0 || // self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? From d78c4aa62ec0382d85e88b44cce2c087c5357f53 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2019 12:19:44 +0100 Subject: [PATCH 0613/1250] use valid_range_exclusive for correct overflow handling --- src/librustc_target/abi/mod.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 4e4ef469090..c48e7de6b04 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -1051,17 +1051,20 @@ impl<'a, Ty> TyLayout<'a, Ty> { where Self: Copy, Ty: TyLayoutMethods<'a, C>, - C: LayoutOf> + C: LayoutOf> + HasDataLayout { let scalar_allows_raw_init = move |s: &Scalar| -> bool { - let range = &s.valid_range; if zero { + let range = &s.valid_range; // The range must contain 0. range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0 } else { - // The range must include all values. - *range.start() == range.end().wrapping_add(1) + // The range must include all values. `valid_range_exclusive` handles + // the wrap-around using target arithmetic; with wrap-around then the full + // range is one where `start == end`. + let range = s.valid_range_exclusive(cx); + range.start == range.end } }; From df6a3a0ed216a8548130f9b431964531a1bc7633 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 Nov 2019 12:24:26 +0100 Subject: [PATCH 0614/1250] test some more things that should not panic --- .../intrinsics/panic-uninitialized-zeroed.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 937f949a7b0..9c869947bfa 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -6,8 +6,11 @@ #![feature(never_type)] #![allow(deprecated, invalid_value)] -use std::{mem, panic}; -use std::ptr::NonNull; +use std::{ + mem::{self, MaybeUninit}, + panic, + ptr::NonNull, +}; #[allow(dead_code)] struct Foo { @@ -40,7 +43,7 @@ fn main() { "attempted to instantiate uninhabited type `!`" ); test_panic_msg( - || mem::MaybeUninit::::uninit().assume_init(), + || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `!`" ); @@ -53,7 +56,7 @@ fn main() { "attempted to instantiate uninhabited type `Foo`" ); test_panic_msg( - || mem::MaybeUninit::::uninit().assume_init(), + || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Foo`" ); @@ -66,7 +69,7 @@ fn main() { "attempted to instantiate uninhabited type `Bar`" ); test_panic_msg( - || mem::MaybeUninit::::uninit().assume_init(), + || MaybeUninit::::uninit().assume_init(), "attempted to instantiate uninhabited type `Bar`" ); @@ -109,5 +112,11 @@ fn main() { let _val = mem::zeroed::(); let _val = mem::zeroed::(); let _val = mem::zeroed::>(); + let _val = mem::zeroed::>>(); + let _val = mem::uninitialized::>(); + + // We don't panic for these just to be conservative. They are UB as of now (2019-11-09). + let _val = mem::uninitialized::(); + let _val = mem::uninitialized::<*const ()>(); } } From b133d6776fde22e944eb7f266ee165ffcf7cdb09 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 13 Nov 2019 09:00:29 +0100 Subject: [PATCH 0615/1250] make it even more conservative, and note some FIXMEs --- src/librustc_codegen_ssa/mir/block.rs | 2 ++ src/librustc_target/abi/mod.rs | 18 +++++++++++++----- .../intrinsics/panic-uninitialized-zeroed.rs | 2 ++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 923e2486ace..ae3d8442add 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -526,6 +526,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { #[derive(Debug, PartialEq)] enum PanicIntrinsic { IfUninhabited, IfZeroInvalid, IfAnyInvalid }; let panic_intrinsic = intrinsic.and_then(|i| match i { + // FIXME: Move to symbols instead of strings. "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), @@ -555,6 +556,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let location = self.get_caller_location(&mut bx, span).immediate(); // Obtain the panic entry point. + // FIXME: dedup this with `codegen_assert_terminator` above. let def_id = common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); let instance = ty::Instance::mono(bx.tcx(), def_id); diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index c48e7de6b04..71f97ca8583 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -1043,6 +1043,10 @@ impl<'a, Ty> TyLayout<'a, Ty> { /// `zero` indicates if the memory is zero-initialized, or alternatively /// left entirely uninitialized. /// This is conservative: in doubt, it will answer `true`. + /// + /// FIXME: Once we removed all the conservatism, we could alternatively + /// create an all-0/all-undef constant and run the vonst value validator to see if + /// this is a valid value for the given type. pub fn might_permit_raw_init( self, cx: &C, @@ -1095,11 +1099,14 @@ impl<'a, Ty> TyLayout<'a, Ty> { FieldPlacement::Array { .. } => // FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays // with any element type, so let us not (yet) complain about that. - // count == 0 || - // self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? + /* count == 0 || + self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */ true, - FieldPlacement::Arbitrary { ref offsets, .. } => { - let mut res = true; + FieldPlacement::Arbitrary { .. } => { + // FIXME(#66151) cargo depends on sized-chunks 0.3.0 which + // has some illegal zero-initialization, so let us not (yet) + // complain about aggregates either. + /* let mut res = true; // Check that all fields accept zero-init. for idx in 0..offsets.len() { let field = self.field(cx, idx).to_result()?; @@ -1108,7 +1115,8 @@ impl<'a, Ty> TyLayout<'a, Ty> { break; } } - res + res */ + true } } } diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 9c869947bfa..a1b2a1af2c4 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -92,6 +92,7 @@ fn main() { "attempted to zero-initialize type `*const dyn std::marker::Send`, which is invalid" ); + /* FIXME(#66151) we conservatively do not error here yet. test_panic_msg( || mem::uninitialized::<(NonNull, u32, u32)>(), "attempted to leave type `(std::ptr::NonNull, u32, u32)` uninitialized, \ @@ -102,6 +103,7 @@ fn main() { "attempted to zero-initialize type `(std::ptr::NonNull, u32, u32)`, \ which is invalid" ); + */ test_panic_msg( || mem::uninitialized::(), From 6e66f586a0da51fbd4cafa2e1da914cf07c65503 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 16 Feb 2020 22:45:28 +0100 Subject: [PATCH 0616/1250] fmt --- src/librustc_codegen_ssa/mir/block.rs | 16 +++++++----- src/librustc_target/abi/mod.rs | 34 ++++++++++++-------------- src/librustc_typeck/check/intrinsic.rs | 7 +++--- 3 files changed, 28 insertions(+), 29 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index ae3d8442add..7c5a17d43b6 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -524,13 +524,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // These are intrinsics that compile to panics so that we can get a message // which mentions the offending type, even from a const context. #[derive(Debug, PartialEq)] - enum PanicIntrinsic { IfUninhabited, IfZeroInvalid, IfAnyInvalid }; + enum PanicIntrinsic { + IfUninhabited, + IfZeroInvalid, + IfAnyInvalid, + }; let panic_intrinsic = intrinsic.and_then(|i| match i { // FIXME: Move to symbols instead of strings. "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), - _ => None + _ => None, }); if let Some(intrinsic) = panic_intrinsic { use PanicIntrinsic::*; @@ -538,10 +542,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let layout = bx.layout_of(ty); let do_panic = match intrinsic { IfUninhabited => layout.abi.is_uninhabited(), - IfZeroInvalid => // We unwrap as the error type is `!`. - !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(), - IfAnyInvalid => // We unwrap as the error type is `!`. - !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(), + // We unwrap as the error type is `!`. + IfZeroInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(), + // We unwrap as the error type is `!`. + IfAnyInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(), }; if do_panic { let msg_str = if layout.abi.is_uninhabited() { diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 71f97ca8583..c043d87f69f 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -1047,22 +1047,17 @@ impl<'a, Ty> TyLayout<'a, Ty> { /// FIXME: Once we removed all the conservatism, we could alternatively /// create an all-0/all-undef constant and run the vonst value validator to see if /// this is a valid value for the given type. - pub fn might_permit_raw_init( - self, - cx: &C, - zero: bool, - ) -> Result + pub fn might_permit_raw_init(self, cx: &C, zero: bool) -> Result where Self: Copy, Ty: TyLayoutMethods<'a, C>, - C: LayoutOf> + HasDataLayout + C: LayoutOf> + HasDataLayout, { let scalar_allows_raw_init = move |s: &Scalar| -> bool { if zero { let range = &s.valid_range; // The range must contain 0. - range.contains(&0) || - (*range.start() > *range.end()) // wrap-around allows 0 + range.contains(&0) || (*range.start() > *range.end()) // wrap-around allows 0 } else { // The range must include all values. `valid_range_exclusive` handles // the wrap-around using target arithmetic; with wrap-around then the full @@ -1076,13 +1071,11 @@ impl<'a, Ty> TyLayout<'a, Ty> { let res = match &self.abi { Abi::Uninhabited => false, // definitely UB Abi::Scalar(s) => scalar_allows_raw_init(s), - Abi::ScalarPair(s1, s2) => - scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), - Abi::Vector { element: s, count } => - *count == 0 || scalar_allows_raw_init(s), + Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), + Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s), Abi::Aggregate { .. } => { match self.variants { - Variants::Multiple { .. } => + Variants::Multiple { .. } => { if zero { // FIXME(#66151): // could we identify the variant with discriminant 0, check that? @@ -1091,17 +1084,20 @@ impl<'a, Ty> TyLayout<'a, Ty> { // FIXME(#66151): This needs to have some sort of discriminant, // which cannot be undef. But for now we are conservative. true - }, + } + } Variants::Single { .. } => { // For aggregates, recurse. match self.fields { FieldPlacement::Union(..) => true, // An all-0 unit is fine. FieldPlacement::Array { .. } => - // FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays - // with any element type, so let us not (yet) complain about that. - /* count == 0 || - self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */ - true, + // FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays + // with any element type, so let us not (yet) complain about that. + /* count == 0 || + self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */ + { + true + } FieldPlacement::Arbitrary { .. } => { // FIXME(#66151) cargo depends on sized-chunks 0.3.0 which // has some illegal zero-initialization, so let us not (yet) diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 321932fb193..d2a358c3e09 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -147,10 +147,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { ), "rustc_peek" => (1, vec![param(0)], param(0)), "caller_location" => (0, vec![], tcx.caller_location_ty()), - "panic_if_uninhabited" | - "panic_if_zero_invalid" | - "panic_if_any_invalid" => - (1, Vec::new(), tcx.mk_unit()), + "panic_if_uninhabited" | "panic_if_zero_invalid" | "panic_if_any_invalid" => { + (1, Vec::new(), tcx.mk_unit()) + } "init" => (1, Vec::new(), param(0)), "uninit" => (1, Vec::new(), param(0)), "forget" => (1, vec![param(0)], tcx.mk_unit()), From 729f4cd9ae9a619677afaa4c389e000c03e5b22b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 17 Feb 2020 09:21:02 +0100 Subject: [PATCH 0617/1250] we cannot short-circuit just becuase the Abi seems harmless also add tests for ScalarPair enums --- src/librustc_target/abi/mod.rs | 63 ++++--------------- .../intrinsics/panic-uninitialized-zeroed.rs | 48 +++++++++++++- 2 files changed, 59 insertions(+), 52 deletions(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index c043d87f69f..aa9474233a4 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -1045,7 +1045,7 @@ impl<'a, Ty> TyLayout<'a, Ty> { /// This is conservative: in doubt, it will answer `true`. /// /// FIXME: Once we removed all the conservatism, we could alternatively - /// create an all-0/all-undef constant and run the vonst value validator to see if + /// create an all-0/all-undef constant and run the const value validator to see if /// this is a valid value for the given type. pub fn might_permit_raw_init(self, cx: &C, zero: bool) -> Result where @@ -1067,59 +1067,22 @@ impl<'a, Ty> TyLayout<'a, Ty> { } }; - // Abi is the most informative here. - let res = match &self.abi { + // Check the ABI. + let valid = match &self.abi { Abi::Uninhabited => false, // definitely UB Abi::Scalar(s) => scalar_allows_raw_init(s), Abi::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), Abi::Vector { element: s, count } => *count == 0 || scalar_allows_raw_init(s), - Abi::Aggregate { .. } => { - match self.variants { - Variants::Multiple { .. } => { - if zero { - // FIXME(#66151): - // could we identify the variant with discriminant 0, check that? - true - } else { - // FIXME(#66151): This needs to have some sort of discriminant, - // which cannot be undef. But for now we are conservative. - true - } - } - Variants::Single { .. } => { - // For aggregates, recurse. - match self.fields { - FieldPlacement::Union(..) => true, // An all-0 unit is fine. - FieldPlacement::Array { .. } => - // FIXME(#66151): The widely use smallvec 0.6 creates uninit arrays - // with any element type, so let us not (yet) complain about that. - /* count == 0 || - self.field(cx, 0).to_result()?.might_permit_raw_init(cx, zero)? */ - { - true - } - FieldPlacement::Arbitrary { .. } => { - // FIXME(#66151) cargo depends on sized-chunks 0.3.0 which - // has some illegal zero-initialization, so let us not (yet) - // complain about aggregates either. - /* let mut res = true; - // Check that all fields accept zero-init. - for idx in 0..offsets.len() { - let field = self.field(cx, idx).to_result()?; - if !field.might_permit_raw_init(cx, zero)? { - res = false; - break; - } - } - res */ - true - } - } - } - } - } + Abi::Aggregate { .. } => true, // Cannot be excluded *right now*. }; - trace!("might_permit_raw_init({:?}, zero={}) = {}", self.details, zero, res); - Ok(res) + if !valid { + // This is definitely not okay. + trace!("might_permit_raw_init({:?}, zero={}): not valid", self.details, zero); + return Ok(false); + } + + // If we have not found an error yet, we need to recursively descend. + // FIXME(#66151): For now, we are conservative and do not do this. + Ok(true) } } diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index a1b2a1af2c4..be0df0ea254 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -7,9 +7,10 @@ #![allow(deprecated, invalid_value)] use std::{ - mem::{self, MaybeUninit}, + mem::{self, MaybeUninit, ManuallyDrop}, panic, ptr::NonNull, + num, }; #[allow(dead_code)] @@ -23,6 +24,18 @@ enum Bar {} #[allow(dead_code)] enum OneVariant { Variant(i32) } +// An enum with ScalarPair layout +#[allow(dead_code)] +enum LR { + Left(i64), + Right(i64), +} +#[allow(dead_code, non_camel_case_types)] +enum LR_NonZero { + Left(num::NonZeroI64), + Right(num::NonZeroI64), +} + fn test_panic_msg(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { let err = panic::catch_unwind(op).err(); assert_eq!( @@ -33,7 +46,7 @@ fn test_panic_msg(op: impl (FnOnce() -> T) + panic::UnwindSafe, msg: &str) { fn main() { unsafe { - // Uninitialized types + // Uninhabited types test_panic_msg( || mem::uninitialized::(), "attempted to instantiate uninhabited type `!`" @@ -93,6 +106,26 @@ fn main() { ); /* FIXME(#66151) we conservatively do not error here yet. + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `LR_NonZero` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::zeroed::(), + "attempted to zero-initialize type `LR_NonZero`, which is invalid" + ); + + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `std::mem::ManuallyDrop` uninitialized, \ + which is invalid" + ); + test_panic_msg( + || mem::zeroed::>(), + "attempted to zero-initialize type `std::mem::ManuallyDrop`, \ + which is invalid" + ); + test_panic_msg( || mem::uninitialized::<(NonNull, u32, u32)>(), "attempted to leave type `(std::ptr::NonNull, u32, u32)` uninitialized, \ @@ -105,13 +138,24 @@ fn main() { ); */ + // Types that can be zero, but not uninit. test_panic_msg( || mem::uninitialized::(), "attempted to leave type `bool` uninitialized, which is invalid" ); + test_panic_msg( + || mem::uninitialized::(), + "attempted to leave type `LR` uninitialized, which is invalid" + ); + test_panic_msg( + || mem::uninitialized::>(), + "attempted to leave type `std::mem::ManuallyDrop` uninitialized, which is invalid" + ); // Some things that should work. let _val = mem::zeroed::(); + let _val = mem::zeroed::(); + let _val = mem::zeroed::>(); let _val = mem::zeroed::(); let _val = mem::zeroed::>(); let _val = mem::zeroed::>>(); From bfe593e03a0f73ee52ac666be17e963957ef628f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Feb 2020 09:29:51 +0100 Subject: [PATCH 0618/1250] clarify a comment in the test --- src/test/ui/intrinsics/panic-uninitialized-zeroed.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index be0df0ea254..02f8ecaa4ee 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -161,7 +161,9 @@ fn main() { let _val = mem::zeroed::>>(); let _val = mem::uninitialized::>(); - // We don't panic for these just to be conservative. They are UB as of now (2019-11-09). + // These are UB because they have not been officially blessed, but we await the resolution + // of before doing + // anything about that. let _val = mem::uninitialized::(); let _val = mem::uninitialized::<*const ()>(); } From 7c84e451d533f12d3a1a7b35ca66bdd02ecf17fc Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Feb 2020 09:40:40 +0100 Subject: [PATCH 0619/1250] move panic intrinsic codegen to helper function --- src/librustc_codegen_ssa/mir/block.rs | 158 +++++++++++++++----------- 1 file changed, 92 insertions(+), 66 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index 7c5a17d43b6..c8d352cd2dd 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -434,6 +434,89 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { helper.do_call(self, &mut bx, fn_abi, llfn, &args, None, cleanup); } + /// Returns `true` if this is indeed a panic intrinsic and codegen is done. + fn codegen_panic_intrinsic( + &mut self, + helper: &TerminatorCodegenHelper<'tcx>, + bx: &mut Bx, + intrinsic: Option<&str>, + instance: Option>, + span: Span, + destination: &Option<(mir::Place<'tcx>, mir::BasicBlock)>, + cleanup: Option, + ) -> bool { + // Emit a panic or a no-op for `panic_if_uninhabited`. + // These are intrinsics that compile to panics so that we can get a message + // which mentions the offending type, even from a const context. + #[derive(Debug, PartialEq)] + enum PanicIntrinsic { + IfUninhabited, + IfZeroInvalid, + IfAnyInvalid, + }; + let panic_intrinsic = intrinsic.and_then(|i| match i { + // FIXME: Move to symbols instead of strings. + "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), + "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), + "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), + _ => None, + }); + if let Some(intrinsic) = panic_intrinsic { + use PanicIntrinsic::*; + let ty = instance.unwrap().substs.type_at(0); + let layout = bx.layout_of(ty); + let do_panic = match intrinsic { + IfUninhabited => layout.abi.is_uninhabited(), + // We unwrap as the error type is `!`. + IfZeroInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ true).unwrap(), + // We unwrap as the error type is `!`. + IfAnyInvalid => !layout.might_permit_raw_init(bx, /*zero:*/ false).unwrap(), + }; + if do_panic { + let msg_str = if layout.abi.is_uninhabited() { + // Use this error even for the other intrinsics as it is more precise. + format!("attempted to instantiate uninhabited type `{}`", ty) + } else if intrinsic == IfZeroInvalid { + format!("attempted to zero-initialize type `{}`, which is invalid", ty) + } else { + format!("attempted to leave type `{}` uninitialized, which is invalid", ty) + }; + let msg = bx.const_str(Symbol::intern(&msg_str)); + let location = self.get_caller_location(bx, span).immediate(); + + // Obtain the panic entry point. + // FIXME: dedup this with `codegen_assert_terminator` above. + let def_id = + common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); + let instance = ty::Instance::mono(bx.tcx(), def_id); + let fn_abi = FnAbi::of_instance(bx, instance, &[]); + let llfn = bx.get_fn_addr(instance); + + if let Some((_, target)) = destination.as_ref() { + helper.maybe_sideeffect(self.mir, bx, &[*target]); + } + // Codegen the actual panic invoke/call. + helper.do_call( + self, + bx, + fn_abi, + llfn, + &[msg.0, msg.1, location], + destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), + cleanup, + ); + } else { + // a NOP + let target = destination.as_ref().unwrap().1; + helper.maybe_sideeffect(self.mir, bx, &[target]); + helper.funclet_br(self, bx, target) + } + true + } else { + false + } + } + fn codegen_call_terminator( &mut self, helper: TerminatorCodegenHelper<'tcx>, @@ -520,72 +603,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bug!("`miri_start_panic` should never end up in compiled code"); } - // Emit a panic or a no-op for `panic_if_uninhabited`. - // These are intrinsics that compile to panics so that we can get a message - // which mentions the offending type, even from a const context. - #[derive(Debug, PartialEq)] - enum PanicIntrinsic { - IfUninhabited, - IfZeroInvalid, - IfAnyInvalid, - }; - let panic_intrinsic = intrinsic.and_then(|i| match i { - // FIXME: Move to symbols instead of strings. - "panic_if_uninhabited" => Some(PanicIntrinsic::IfUninhabited), - "panic_if_zero_invalid" => Some(PanicIntrinsic::IfZeroInvalid), - "panic_if_any_invalid" => Some(PanicIntrinsic::IfAnyInvalid), - _ => None, - }); - if let Some(intrinsic) = panic_intrinsic { - use PanicIntrinsic::*; - let ty = instance.unwrap().substs.type_at(0); - let layout = bx.layout_of(ty); - let do_panic = match intrinsic { - IfUninhabited => layout.abi.is_uninhabited(), - // We unwrap as the error type is `!`. - IfZeroInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ true).unwrap(), - // We unwrap as the error type is `!`. - IfAnyInvalid => !layout.might_permit_raw_init(&bx, /*zero:*/ false).unwrap(), - }; - if do_panic { - let msg_str = if layout.abi.is_uninhabited() { - // Use this error even for the other intrinsics as it is more precise. - format!("attempted to instantiate uninhabited type `{}`", ty) - } else if intrinsic == IfZeroInvalid { - format!("attempted to zero-initialize type `{}`, which is invalid", ty) - } else { - format!("attempted to leave type `{}` uninitialized, which is invalid", ty) - }; - let msg = bx.const_str(Symbol::intern(&msg_str)); - let location = self.get_caller_location(&mut bx, span).immediate(); - - // Obtain the panic entry point. - // FIXME: dedup this with `codegen_assert_terminator` above. - let def_id = - common::langcall(bx.tcx(), Some(span), "", lang_items::PanicFnLangItem); - let instance = ty::Instance::mono(bx.tcx(), def_id); - let fn_abi = FnAbi::of_instance(&bx, instance, &[]); - let llfn = bx.get_fn_addr(instance); - - if let Some((_, target)) = destination.as_ref() { - helper.maybe_sideeffect(self.mir, &mut bx, &[*target]); - } - // Codegen the actual panic invoke/call. - helper.do_call( - self, - &mut bx, - fn_abi, - llfn, - &[msg.0, msg.1, location], - destination.as_ref().map(|(_, bb)| (ReturnDest::Nothing, *bb)), - cleanup, - ); - } else { - // a NOP - let target = destination.as_ref().unwrap().1; - helper.maybe_sideeffect(self.mir, &mut bx, &[target]); - helper.funclet_br(self, &mut bx, target) - } + if self.codegen_panic_intrinsic( + &helper, + &mut bx, + intrinsic, + instance, + span, + destination, + cleanup, + ) { return; } From a09c33e36205991bb633a848d1e9c7604ae43ce8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Feb 2020 09:41:59 +0100 Subject: [PATCH 0620/1250] move pattern to fn argument --- src/librustc_target/abi/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index aa9474233a4..d8788611878 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -943,8 +943,7 @@ pub trait MaybeResult { impl MaybeResult for T { type Error = !; - fn from(x: Result) -> Self { - let Ok(x) = x; + fn from(Ok(x): Result) -> Self { x } fn to_result(self) -> Result { From 5982e9d3ca679866a0533d69a41224c333a5348a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 29 Feb 2020 10:25:57 +0100 Subject: [PATCH 0621/1250] downgrade some assertions to debug_ again --- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_mir/interpret/place.rs | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 673afc6c06d..1df389d9c8b 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -195,7 +195,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { kind: MemoryKind, ) -> Pointer { let id = self.tcx.alloc_map.lock().reserve(); - assert_ne!( + debug_assert_ne!( Some(kind), M::STATIC_KIND.map(MemoryKind::Machine), "dynamically allocating static memory" diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 8215b4c5aa4..4f96cb69891 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -1130,10 +1130,12 @@ where let layout = self.layout_of(ty)?; // More sanity checks - let (size, align) = self.read_size_and_align_from_vtable(vtable)?; - assert_eq!(size, layout.size); - // only ABI alignment is preserved - assert_eq!(align, layout.align.abi); + if cfg!(debug_assertions) { + let (size, align) = self.read_size_and_align_from_vtable(vtable)?; + assert_eq!(size, layout.size); + // only ABI alignment is preserved + assert_eq!(align, layout.align.abi); + } let mplace = MPlaceTy { mplace: MemPlace { meta: MemPlaceMeta::None, ..*mplace }, layout }; Ok((instance, mplace)) From 56a3da3bd0e2f6b5963913e998c74266cf7cff7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 01:56:37 +0100 Subject: [PATCH 0622/1250] simplify boolean expressions --- src/liballoc/collections/binary_heap.rs | 4 ++-- src/librustc_codegen_llvm/debuginfo/metadata.rs | 2 +- src/librustc_codegen_ssa/mir/debuginfo.rs | 4 ++-- src/librustc_infer/infer/freshen.rs | 6 +++--- src/librustc_infer/infer/mod.rs | 2 +- src/librustc_passes/stability.rs | 2 +- src/librustc_resolve/imports.rs | 4 ++-- src/libstd/net/parser.rs | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs index f38fe997b73..9908a304976 100644 --- a/src/liballoc/collections/binary_heap.rs +++ b/src/liballoc/collections/binary_heap.rs @@ -536,7 +536,7 @@ impl BinaryHeap { while child < end { let right = child + 1; // compare with the greater of the two children - if right < end && !(hole.get(child) > hole.get(right)) { + if right < end && hole.get(child) <= hole.get(right) { child = right; } // if we are already in order, stop. @@ -568,7 +568,7 @@ impl BinaryHeap { while child < end { let right = child + 1; // compare with the greater of the two children - if right < end && !(hole.get(child) > hole.get(right)) { + if right < end && hole.get(child) <= hole.get(right) { child = right; } hole.move_to(child); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index d1f70ad43bd..ab024a02650 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -2135,7 +2135,7 @@ fn set_members_of_composite_type( /// Computes the type parameters for a type, if any, for the given metadata. fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&'ll DIArray> { if let ty::Adt(def, substs) = ty.kind { - if !substs.types().next().is_none() { + if substs.types().next().is_some() { let generics = cx.tcx.generics_of(def.did); let names = get_parameter_names(cx, generics); let template_params: Vec<_> = substs diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs index e5f21013ce3..2dc1405f4e4 100644 --- a/src/librustc_codegen_ssa/mir/debuginfo.rs +++ b/src/librustc_codegen_ssa/mir/debuginfo.rs @@ -48,7 +48,7 @@ pub struct DebugScope { impl DebugScope { pub fn is_valid(&self) -> bool { - !self.scope_metadata.is_none() + self.scope_metadata.is_some() } } @@ -304,7 +304,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) -> Option>>> { let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full; - if !(full_debug_info || !self.cx.sess().fewer_names()) { + if !full_debug_info && self.cx.sess().fewer_names() { return None; } diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index 63dded3b43d..f7141c56199 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -143,9 +143,9 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.needs_infer() - && !t.has_erasable_regions() - && !(t.has_closure_types() && self.infcx.in_progress_tables.is_some()) + if !(t.needs_infer() + || t.has_erasable_regions() + || (t.has_closure_types() && self.infcx.in_progress_tables.is_some())) { return t; } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 26998f0a33c..766de569132 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -1484,7 +1484,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // Even if the type may have no inference variables, during // type-checking closure types are in local tables only. - if !self.in_progress_tables.is_some() || !ty.has_closure_types() { + if self.in_progress_tables.is_none() || !ty.has_closure_types() { if !(param_env, ty).has_local_value() { return ty.is_copy_modulo_regions(self.tcx, param_env, span); } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 99fbac4568e..bab468493df 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -551,7 +551,7 @@ impl Visitor<'tcx> for Checker<'tcx> { .emit(); } else { let param_env = self.tcx.param_env(def_id); - if !can_type_implement_copy(self.tcx, param_env, ty).is_ok() { + if can_type_implement_copy(self.tcx, param_env, ty).is_err() { feature_err( &self.tcx.sess.parse_sess, sym::untagged_unions, diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 55ce51e0ff0..8a07a6fe8c9 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -313,9 +313,9 @@ impl<'a> Resolver<'a> { } } - if !self.is_accessible_from(binding.vis, parent_scope.module) && + if !(self.is_accessible_from(binding.vis, parent_scope.module) || // Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE` - !(self.last_import_segment && binding.is_extern_crate()) + (self.last_import_segment && binding.is_extern_crate())) { self.privacy_errors.push(PrivacyError { ident, diff --git a/src/libstd/net/parser.rs b/src/libstd/net/parser.rs index 868a7e261c4..3f38ee54710 100644 --- a/src/libstd/net/parser.rs +++ b/src/libstd/net/parser.rs @@ -206,7 +206,7 @@ impl<'a> Parser<'a> { } // read `::` if previous code parsed less than 8 groups - if !self.read_given_char(':').is_some() || !self.read_given_char(':').is_some() { + if self.read_given_char(':').is_none() || self.read_given_char(':').is_none() { return None; } From 10b814608b6ef5ccf72ada0da4645e5af039d880 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 29 Feb 2020 11:42:38 +0100 Subject: [PATCH 0623/1250] nightly: bootstrap from 1.42.0-beta.5 (4e1c5f0e9 2020-02-28) This beta snapshot has the llvm miscompilation fix included and is bootstrapped from the stable version that also has it included. --- src/stage0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stage0.txt b/src/stage0.txt index 14bffbadc06..55416b6729a 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: 2020-01-30 +date: 2020-02-29 rustc: beta cargo: beta From 45053d1fa6a79baca1142b99ec9dcda89a61bf16 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 28 Feb 2020 16:06:30 +0100 Subject: [PATCH 0624/1250] Clean up E0374 explanation --- src/librustc_error_codes/error_codes/E0374.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0374.md b/src/librustc_error_codes/error_codes/E0374.md index 0e1a4bf8099..6d7dc88823c 100644 --- a/src/librustc_error_codes/error_codes/E0374.md +++ b/src/librustc_error_codes/error_codes/E0374.md @@ -1,9 +1,5 @@ -A struct without a field containing an unsized type cannot implement -`CoerceUnsized`. An [unsized type][1] is any type that the compiler -doesn't know the length or alignment of at compile time. Any struct -containing an unsized type is also unsized. - -[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait +`CoerceUnsized` was implemented on a struct which does not contain a field with +an unsized type. Example of erroneous code: @@ -20,6 +16,12 @@ impl CoerceUnsized> for Foo where T: CoerceUnsized {} ``` +An [unsized type][1] is any type where the compiler does not know the length or +alignment of at compile time. Any struct containing an unsized type is also +unsized. + +[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait + `CoerceUnsized` is used to coerce one struct containing an unsized type into another struct containing a different unsized type. If the struct doesn't have any fields of unsized types then you don't need explicit From 6fba47f66f12212c7da504702aff7c69a8e15d02 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 29 Feb 2020 12:18:46 +0100 Subject: [PATCH 0625/1250] Clean up E0375 explanation --- src/librustc_error_codes/error_codes/E0375.md | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0375.md b/src/librustc_error_codes/error_codes/E0375.md index 31fcd85cb07..71e53057165 100644 --- a/src/librustc_error_codes/error_codes/E0375.md +++ b/src/librustc_error_codes/error_codes/E0375.md @@ -1,12 +1,7 @@ -A struct with more than one field containing an unsized type cannot implement -`CoerceUnsized`. This only occurs when you are trying to coerce one of the -types in your struct to another type in the struct. In this case we try to -impl `CoerceUnsized` from `T` to `U` which are both types that the struct -takes. An [unsized type][1] is any type that the compiler doesn't know the -length or alignment of at compile time. Any struct containing an unsized type -is also unsized. +`CoerceUnsized` was implemented on a struct which contains more than one field +with an unsized type. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0375 #![feature(coerce_unsized)] @@ -22,6 +17,14 @@ struct Foo { impl CoerceUnsized> for Foo {} ``` +A struct with more than one field containing an unsized type cannot implement +`CoerceUnsized`. This only occurs when you are trying to coerce one of the +types in your struct to another type in the struct. In this case we try to +impl `CoerceUnsized` from `T` to `U` which are both types that the struct +takes. An [unsized type][1] is any type that the compiler doesn't know the +length or alignment of at compile time. Any struct containing an unsized type +is also unsized. + `CoerceUnsized` only allows for coercion from a structure with a single unsized type field to another struct with a single unsized type field. In fact Rust only allows for a struct to have one unsized type in a struct From d0ba4387c2730b0323bcd42170edf8477a799af7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Feb 2020 14:56:15 +0300 Subject: [PATCH 0626/1250] parser: `prev_span` -> `prev_token.span` --- src/librustc_builtin_macros/asm.rs | 12 +-- src/librustc_builtin_macros/assert.rs | 2 +- src/librustc_parse/parser/attr.rs | 6 +- src/librustc_parse/parser/diagnostics.rs | 52 +++++----- src/librustc_parse/parser/expr.rs | 127 ++++++++++++----------- src/librustc_parse/parser/generics.rs | 28 ++--- src/librustc_parse/parser/item.rs | 59 ++++++----- src/librustc_parse/parser/mod.rs | 22 ++-- src/librustc_parse/parser/module.rs | 2 +- src/librustc_parse/parser/pat.rs | 37 ++++--- src/librustc_parse/parser/path.rs | 22 ++-- src/librustc_parse/parser/stmt.rs | 24 ++--- src/librustc_parse/parser/ty.rs | 30 +++--- 13 files changed, 219 insertions(+), 204 deletions(-) diff --git a/src/librustc_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs index 9f98cf253c9..b12734a5c40 100644 --- a/src/librustc_builtin_macros/asm.rs +++ b/src/librustc_builtin_macros/asm.rs @@ -151,7 +151,7 @@ fn parse_inline_asm<'a>( let constraint = parse_asm_str(&mut p)?; - let span = p.prev_span; + let span = p.prev_token.span; p.expect(&token::OpenDelim(token::Paren))?; let expr = p.parse_expr()?; @@ -202,7 +202,7 @@ fn parse_inline_asm<'a>( if constraint.as_str().starts_with('=') { struct_span_err!( cx.parse_sess.span_diagnostic, - p.prev_span, + p.prev_token.span, E0662, "input operand constraint contains '='" ) @@ -210,7 +210,7 @@ fn parse_inline_asm<'a>( } else if constraint.as_str().starts_with('+') { struct_span_err!( cx.parse_sess.span_diagnostic, - p.prev_span, + p.prev_token.span, E0663, "input operand constraint contains '+'" ) @@ -233,11 +233,11 @@ fn parse_inline_asm<'a>( let s = parse_asm_str(&mut p)?; if OPTIONS.iter().any(|&opt| s == opt) { - cx.span_warn(p.prev_span, "expected a clobber, found an option"); + cx.span_warn(p.prev_token.span, "expected a clobber, found an option"); } else if s.as_str().starts_with('{') || s.as_str().ends_with('}') { struct_span_err!( cx.parse_sess.span_diagnostic, - p.prev_span, + p.prev_token.span, E0664, "clobber should not be surrounded by braces" ) @@ -259,7 +259,7 @@ fn parse_inline_asm<'a>( } else if option == sym::intel { dialect = AsmDialect::Intel; } else { - cx.span_warn(p.prev_span, "unrecognized option"); + cx.span_warn(p.prev_token.span, "unrecognized option"); } if p.token == token::Comma { diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs index 3fc86a5469c..3ff4c79fcae 100644 --- a/src/librustc_builtin_macros/assert.rs +++ b/src/librustc_builtin_macros/assert.rs @@ -106,7 +106,7 @@ fn parse_assert<'a>( let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind { let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal"); - let comma_span = parser.prev_span.shrink_to_hi(); + let comma_span = parser.prev_token.span.shrink_to_hi(); err.span_suggestion_short( comma_span, "try adding a comma", diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index 905f6bef58e..ea7500f6732 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -116,7 +116,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Bracket))?; let item = self.parse_attr_item()?; self.expect(&token::CloseDelim(token::Bracket))?; - let hi = self.prev_span; + let hi = self.prev_token.span; let attr_sp = lo.to(hi); @@ -255,7 +255,7 @@ impl<'a> Parser<'a> { while self.token.kind != token::Eof { let lo = self.token.span; let item = self.parse_attr_item()?; - expanded_attrs.push((item, lo.to(self.prev_span))); + expanded_attrs.push((item, lo.to(self.prev_token.span))); if !self.eat(&token::Comma) { break; } @@ -303,7 +303,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; let path = self.parse_path(PathStyle::Mod)?; let kind = self.parse_meta_item_kind()?; - let span = lo.to(self.prev_span); + let span = lo.to(self.prev_token.span); Ok(ast::MetaItem { path, kind, span }) } diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 00f5fb97052..29d8075c643 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -260,24 +260,24 @@ impl<'a> Parser<'a> { }; ( format!("expected one of {}, found {}", expect, actual), - (self.prev_span.shrink_to_hi(), format!("expected one of {}", short_expect)), + (self.prev_token.span.shrink_to_hi(), format!("expected one of {}", short_expect)), ) } else if expected.is_empty() { ( format!("unexpected token: {}", actual), - (self.prev_span, "unexpected token after this".to_string()), + (self.prev_token.span, "unexpected token after this".to_string()), ) } else { ( format!("expected {}, found {}", expect, actual), - (self.prev_span.shrink_to_hi(), format!("expected {}", expect)), + (self.prev_token.span.shrink_to_hi(), format!("expected {}", expect)), ) }; self.last_unexpected_token_span = Some(self.token.span); let mut err = self.struct_span_err(self.token.span, &msg_exp); let sp = if self.token == token::Eof { // This is EOF; don't want to point at the following char, but rather the last token. - self.prev_span + self.prev_token.span } else { label_sp }; @@ -298,7 +298,7 @@ impl<'a> Parser<'a> { } let sm = self.sess.source_map(); - if self.prev_span == DUMMY_SP { + if self.prev_token.span == DUMMY_SP { // Account for macro context where the previous span might not be // available to avoid incorrect output (#54841). err.span_label(self.token.span, label_exp); @@ -577,7 +577,7 @@ impl<'a> Parser<'a> { match inner_op.kind { ExprKind::Binary(op, _, _) if op.node.is_comparison() => { // Respan to include both operators. - let op_span = op.span.to(self.prev_span); + let op_span = op.span.to(self.prev_token.span); let mut err = self.struct_span_err(op_span, "comparison operators cannot be chained"); @@ -632,7 +632,7 @@ impl<'a> Parser<'a> { // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - mk_err_expr(self, inner_op.span.to(self.prev_span)) + mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } Err(mut expr_err) => { expr_err.cancel(); @@ -654,7 +654,7 @@ impl<'a> Parser<'a> { // FIXME: actually check that the two expressions in the binop are // paths and resynthesize new fn call expression instead of using // `ExprKind::Err` placeholder. - mk_err_expr(self, inner_op.span.to(self.prev_span)) + mk_err_expr(self, inner_op.span.to(self.prev_token.span)) } } } else { @@ -723,7 +723,7 @@ impl<'a> Parser<'a> { self.bump(); // `+` let bounds = self.parse_generic_bounds(None)?; - let sum_span = ty.span.to(self.prev_span); + let sum_span = ty.span.to(self.prev_token.span); let mut err = struct_span_err!( self.sess.span_diagnostic, @@ -790,7 +790,7 @@ impl<'a> Parser<'a> { let mut path = ast::Path { segments: Vec::new(), span: DUMMY_SP }; self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?; - path.span = ty_span.to(self.prev_span); + path.span = ty_span.to(self.prev_token.span); let ty_str = self.span_to_snippet(ty_span).unwrap_or_else(|_| pprust::ty_to_string(&ty)); self.struct_span_err(path.span, "missing angle brackets in associated item path") @@ -809,9 +809,9 @@ impl<'a> Parser<'a> { pub(super) fn maybe_consume_incorrect_semicolon(&mut self, items: &[P]) -> bool { if self.eat(&token::Semi) { - let mut err = self.struct_span_err(self.prev_span, "expected item, found `;`"); + let mut err = self.struct_span_err(self.prev_token.span, "expected item, found `;`"); err.span_suggestion_short( - self.prev_span, + self.prev_token.span, "remove this semicolon", String::new(), Applicability::MachineApplicable, @@ -854,10 +854,10 @@ impl<'a> Parser<'a> { } // We don't want to point at the following span after DUMMY_SP. // This happens when the parser finds an empty TokenStream. - _ if self.prev_span == DUMMY_SP => (self.token.span, self.token.span), + _ if self.prev_token.span == DUMMY_SP => (self.token.span, self.token.span), // EOF, don't want to point at the following char, but rather the last token. - (token::Eof, None) => (self.prev_span, self.token.span), - _ => (self.prev_span.shrink_to_hi(), self.token.span), + (token::Eof, None) => (self.prev_token.span, self.token.span), + _ => (self.prev_token.span.shrink_to_hi(), self.token.span), }; let msg = format!( "expected `{}`, found {}", @@ -894,10 +894,10 @@ impl<'a> Parser<'a> { let sm = self.sess.source_map(); let msg = format!("expected `;`, found `{}`", super::token_descr(&self.token)); let appl = Applicability::MachineApplicable; - if self.token.span == DUMMY_SP || self.prev_span == DUMMY_SP { + if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP { // Likely inside a macro, can't provide meaninful suggestions. return self.expect(&token::Semi).map(drop); - } else if !sm.is_multiline(self.prev_span.until(self.token.span)) { + } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) { // The current token is in the same line as the prior token, not recoverable. } else if self.look_ahead(1, |t| { t == &token::CloseDelim(token::Brace) || t.can_begin_expr() && t.kind != token::Colon @@ -910,7 +910,7 @@ impl<'a> Parser<'a> { // let x = 32: // let y = 42; self.bump(); - let sp = self.prev_span; + let sp = self.prev_token.span; self.struct_span_err(sp, &msg) .span_suggestion(sp, "change this to `;`", ";".to_string(), appl) .emit(); @@ -927,7 +927,7 @@ impl<'a> Parser<'a> { // // let x = 32 // let y = 42; - let sp = self.prev_span.shrink_to_hi(); + let sp = self.prev_token.span.shrink_to_hi(); self.struct_span_err(sp, &msg) .span_label(self.token.span, "unexpected token") .span_suggestion_short(sp, "add `;` here", ";".to_string(), appl) @@ -961,7 +961,7 @@ impl<'a> Parser<'a> { self.expect(&token::OpenDelim(token::Paren))?; let expr = self.parse_expr()?; self.expect(&token::CloseDelim(token::Paren))?; - Ok((self.prev_span, expr, false)) + Ok((self.prev_token.span, expr, false)) } fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, P, bool)> { @@ -1036,10 +1036,10 @@ impl<'a> Parser<'a> { .span_to_snippet(pat.span.trim_start(begin_par_sp).unwrap()) .unwrap_or_else(|_| pprust::pat_to_string(&pat)); - self.struct_span_err(self.prev_span, "unexpected closing `)`") + self.struct_span_err(self.prev_token.span, "unexpected closing `)`") .span_label(begin_par_sp, "opening `(`") .span_suggestion( - begin_par_sp.to(self.prev_span), + begin_par_sp.to(self.prev_token.span), "remove parenthesis in `for` loop", format!("{} in {}", pat_str, pprust::expr_to_string(&expr)), // With e.g. `for (x) in y)` this would replace `(x) in y)` @@ -1091,7 +1091,7 @@ impl<'a> Parser<'a> { err.emit(); // Recover from parse error, callers expect the closing delim to be consumed. self.consume_block(delim, ConsumeClosingDelim::Yes); - self.mk_expr(lo.to(self.prev_span), ExprKind::Err, AttrVec::new()) + self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err, AttrVec::new()) } } } @@ -1138,7 +1138,7 @@ impl<'a> Parser<'a> { err.span_label(sp, "unclosed delimiter"); } err.span_suggestion_short( - self.prev_span.shrink_to_hi(), + self.prev_token.span.shrink_to_hi(), &format!("{} may belong here", delim.to_string()), delim.to_string(), Applicability::MaybeIncorrect, @@ -1246,9 +1246,9 @@ impl<'a> Parser<'a> { pub(super) fn check_for_for_in_in_typo(&mut self, in_span: Span) { if self.eat_keyword(kw::In) { // a common typo: `for _ in in bar {}` - self.struct_span_err(self.prev_span, "expected iterable, found keyword `in`") + self.struct_span_err(self.prev_token.span, "expected iterable, found keyword `in`") .span_suggestion_short( - in_span.until(self.prev_span), + in_span.until(self.prev_token.span), "remove the duplicated `in`", String::new(), Applicability::MachineApplicable, diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 71ca8fba0b4..c1158483302 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -166,7 +166,7 @@ impl<'a> Parser<'a> { // Adjust the span for interpolated LHS to point to the `$lhs` token // and not to what it refers to. let lhs_span = match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_span, + TokenKind::Interpolated(..) => self.prev_token.span, _ => lhs.span, }; @@ -523,7 +523,7 @@ impl<'a> Parser<'a> { expr.map(|e| { ( match self.prev_token.kind { - TokenKind::Interpolated(..) => self.prev_span, + TokenKind::Interpolated(..) => self.prev_token.span, _ => e.span, }, e, @@ -614,7 +614,7 @@ impl<'a> Parser<'a> { fn parse_assoc_op_ascribe(&mut self, lhs: P, lhs_span: Span) -> PResult<'a, P> { let maybe_path = self.could_ascription_be_path(&lhs.kind); - self.last_type_ascription = Some((self.prev_span, maybe_path)); + self.last_type_ascription = Some((self.prev_token.span, maybe_path)); let lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; self.sess.gated_spans.gate(sym::type_ascription, lhs.span); Ok(lhs) @@ -636,7 +636,7 @@ impl<'a> Parser<'a> { let found_raw = self.eat_keyword(kw::Raw); assert!(found_raw); let mutability = self.parse_const_or_mut().unwrap(); - self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_span)); + self.sess.gated_spans.gate(sym::raw_ref_op, lo.to(self.prev_token.span)); (ast::BorrowKind::Raw, mutability) } else { // `mut?` @@ -683,7 +683,7 @@ impl<'a> Parser<'a> { loop { if self.eat(&token::Question) { // `expr?` - e = self.mk_expr(lo.to(self.prev_span), ExprKind::Try(e), AttrVec::new()); + e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e), AttrVec::new()); continue; } if self.eat(&token::Dot) { @@ -735,8 +735,8 @@ impl<'a> Parser<'a> { let fstr = sym.as_str(); let msg = format!("unexpected token: `{}`", sym); - let mut err = self.struct_span_err(self.prev_span, &msg); - err.span_label(self.prev_span, "unexpected token"); + let mut err = self.struct_span_err(self.prev_token.span, &msg); + err.span_label(self.prev_token.span, "unexpected token"); if fstr.chars().all(|x| "0123456789.".contains(x)) { let float = match fstr.parse::() { @@ -756,7 +756,7 @@ impl<'a> Parser<'a> { s.s.word(fstr.splitn(2, '.').last().unwrap().to_string()) }); err.span_suggestion( - lo.to(self.prev_span), + lo.to(self.prev_token.span), "try parenthesizing the first index", sugg, Applicability::MachineApplicable, @@ -782,7 +782,7 @@ impl<'a> Parser<'a> { /// Parse a function call expression, `expr(...)`. fn parse_fn_call_expr(&mut self, lo: Span, fun: P) -> P { let seq = self.parse_paren_expr_seq().map(|args| { - self.mk_expr(lo.to(self.prev_span), self.mk_call(fun, args), AttrVec::new()) + self.mk_expr(lo.to(self.prev_token.span), self.mk_call(fun, args), AttrVec::new()) }); self.recover_seq_parse_error(token::Paren, lo, seq) } @@ -792,7 +792,7 @@ impl<'a> Parser<'a> { self.bump(); // `[` let index = self.parse_expr()?; self.expect(&token::CloseDelim(token::Bracket))?; - Ok(self.mk_expr(lo.to(self.prev_span), self.mk_index(base, index), AttrVec::new())) + Ok(self.mk_expr(lo.to(self.prev_token.span), self.mk_index(base, index), AttrVec::new())) } /// Assuming we have just parsed `.`, continue parsing into an expression. @@ -809,7 +809,7 @@ impl<'a> Parser<'a> { let mut args = self.parse_paren_expr_seq()?; args.insert(0, self_arg); - let span = lo.to(self.prev_span); + let span = lo.to(self.prev_token.span); Ok(self.mk_expr(span, ExprKind::MethodCall(segment, args), AttrVec::new())) } else { // Field access `expr.f` @@ -821,7 +821,7 @@ impl<'a> Parser<'a> { .emit(); } - let span = lo.to(self.prev_span); + let span = lo.to(self.prev_token.span); Ok(self.mk_expr(span, ExprKind::Field(self_arg, segment.ident), AttrVec::new())) } } @@ -867,18 +867,18 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(kw::If) { self.parse_if_expr(attrs) } else if self.eat_keyword(kw::For) { - self.parse_for_expr(None, self.prev_span, attrs) + self.parse_for_expr(None, self.prev_token.span, attrs) } else if self.eat_keyword(kw::While) { - self.parse_while_expr(None, self.prev_span, attrs) + self.parse_while_expr(None, self.prev_token.span, attrs) } else if let Some(label) = self.eat_label() { self.parse_labeled_expr(label, attrs) } else if self.eat_keyword(kw::Loop) { - self.parse_loop_expr(None, self.prev_span, attrs) + self.parse_loop_expr(None, self.prev_token.span, attrs) } else if self.eat_keyword(kw::Continue) { let kind = ExprKind::Continue(self.eat_label()); - Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs)) + Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) } else if self.eat_keyword(kw::Match) { - let match_sp = self.prev_span; + let match_sp = self.prev_token.span; self.parse_match_expr(attrs).map_err(|mut err| { err.span_label(match_sp, "while parsing this match expression"); err @@ -921,7 +921,7 @@ impl<'a> Parser<'a> { self.parse_closure_expr(attrs) } } else if self.eat_keyword(kw::Await) { - self.recover_incorrect_await_syntax(lo, self.prev_span, attrs) + self.recover_incorrect_await_syntax(lo, self.prev_token.span, attrs) } else { self.parse_lit_expr(attrs) } @@ -934,7 +934,7 @@ impl<'a> Parser<'a> { let lo = self.token.span; match self.parse_opt_lit() { Some(literal) => { - let expr = self.mk_expr(lo.to(self.prev_span), ExprKind::Lit(literal), attrs); + let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Lit(literal), attrs); self.maybe_recover_from_bad_qpath(expr, true) } None => return Err(self.expected_expression_found()), @@ -960,7 +960,7 @@ impl<'a> Parser<'a> { // `(e,)` is a tuple with only one field, `e`. ExprKind::Tup(es) }; - let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs); + let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); self.maybe_recover_from_bad_qpath(expr, true) } @@ -995,7 +995,7 @@ impl<'a> Parser<'a> { ExprKind::Array(vec![first_expr]) } }; - let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs); + let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); self.maybe_recover_from_bad_qpath(expr, true) } @@ -1011,7 +1011,7 @@ impl<'a> Parser<'a> { args: self.parse_mac_args()?, prior_type_ascription: self.last_type_ascription, }; - (self.prev_span, ExprKind::Mac(mac)) + (self.prev_token.span, ExprKind::Mac(mac)) } else if self.check(&token::OpenDelim(token::Brace)) { if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { return expr; @@ -1055,7 +1055,7 @@ impl<'a> Parser<'a> { self.bump(); // `do` self.bump(); // `catch` - let span_dc = lo.to(self.prev_span); + let span_dc = lo.to(self.prev_token.span); self.struct_span_err(span_dc, "found removed `do catch` syntax") .span_suggestion( span_dc, @@ -1076,15 +1076,15 @@ impl<'a> Parser<'a> { /// Parse `"return" expr?`. fn parse_return_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_span; + let lo = self.prev_token.span; let kind = ExprKind::Ret(self.parse_expr_opt()?); - let expr = self.mk_expr(lo.to(self.prev_span), kind, attrs); + let expr = self.mk_expr(lo.to(self.prev_token.span), kind, attrs); self.maybe_recover_from_bad_qpath(expr, true) } /// Parse `"('label ":")? break expr?`. fn parse_break_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_span; + let lo = self.prev_token.span; let label = self.eat_label(); let kind = if self.token != token::OpenDelim(token::Brace) || !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) @@ -1093,15 +1093,15 @@ impl<'a> Parser<'a> { } else { None }; - let expr = self.mk_expr(lo.to(self.prev_span), ExprKind::Break(label, kind), attrs); + let expr = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Break(label, kind), attrs); self.maybe_recover_from_bad_qpath(expr, true) } /// Parse `"yield" expr?`. fn parse_yield_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_span; + let lo = self.prev_token.span; let kind = ExprKind::Yield(self.parse_expr_opt()?); - let span = lo.to(self.prev_span); + let span = lo.to(self.prev_token.span); self.sess.gated_spans.gate(sym::generators, span); let expr = self.mk_expr(span, kind, attrs); self.maybe_recover_from_bad_qpath(expr, true) @@ -1306,7 +1306,11 @@ impl<'a> Parser<'a> { let expr = self.mk_expr(lit.span, ExprKind::Lit(lit), AttrVec::new()); if minus_present { - Ok(self.mk_expr(lo.to(self.prev_span), self.mk_unary(UnOp::Neg, expr), AttrVec::new())) + Ok(self.mk_expr( + lo.to(self.prev_token.span), + self.mk_unary(UnOp::Neg, expr), + AttrVec::new(), + )) } else { Ok(expr) } @@ -1349,7 +1353,7 @@ impl<'a> Parser<'a> { let capture_clause = self.parse_capture_clause(); let decl = self.parse_fn_block_decl()?; - let decl_hi = self.prev_span; + let decl_hi = self.prev_token.span; let body = match decl.output { FnRetTy::Default(_) => { let restrictions = self.restrictions - Restrictions::STMT_EXPR; @@ -1404,7 +1408,7 @@ impl<'a> Parser<'a> { let ty = if self.eat(&token::Colon) { self.parse_ty()? } else { - self.mk_ty(self.prev_span, TyKind::Infer) + self.mk_ty(self.prev_token.span, TyKind::Infer) }; Ok(Param { attrs: attrs.into(), @@ -1418,7 +1422,7 @@ impl<'a> Parser<'a> { /// Parses an `if` expression (`if` token already eaten). fn parse_if_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_span; + let lo = self.prev_token.span; let cond = self.parse_cond_expr()?; // Verify that the parsed `if` condition makes sense as a condition. If it is a block, then @@ -1437,7 +1441,7 @@ impl<'a> Parser<'a> { })? }; let els = if self.eat_keyword(kw::Else) { Some(self.parse_else_expr()?) } else { None }; - Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::If(cond, thn, els), attrs)) + Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els), attrs)) } fn error_missing_if_cond(&self, lo: Span, span: Span) -> P { @@ -1463,7 +1467,7 @@ impl<'a> Parser<'a> { /// Parses a `let $pat = $expr` pseudo-expression. /// The `let` token has already been eaten. fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P> { - let lo = self.prev_span; + let lo = self.prev_token.span; let pat = self.parse_top_pat(GateOr::No)?; self.expect(&token::Eq)?; let expr = self.with_res(Restrictions::NO_STRUCT_LITERAL, |this| { @@ -1503,7 +1507,7 @@ impl<'a> Parser<'a> { if !self.eat_keyword(kw::In) { self.error_missing_in_for_loop(); } - self.check_for_for_in_in_typo(self.prev_span); + self.check_for_for_in_in_typo(self.prev_token.span); let expr = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; let pat = self.recover_parens_around_for_head(pat, &expr, begin_paren); @@ -1512,11 +1516,11 @@ impl<'a> Parser<'a> { attrs.extend(iattrs); let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); - Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs)) + Ok(self.mk_expr(lo.to(self.prev_token.span), kind, attrs)) } fn error_missing_in_for_loop(&self) { - let in_span = self.prev_span.between(self.token.span); + let in_span = self.prev_token.span.between(self.token.span); self.struct_span_err(in_span, "missing `in` in `for` loop") .span_suggestion_short( in_span, @@ -1538,7 +1542,7 @@ impl<'a> Parser<'a> { let cond = self.parse_cond_expr()?; let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::While(cond, body, opt_label), attrs)) + Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::While(cond, body, opt_label), attrs)) } /// Parses `loop { ... }` (`loop` token already eaten). @@ -1550,7 +1554,7 @@ impl<'a> Parser<'a> { ) -> PResult<'a, P> { let (iattrs, body) = self.parse_inner_attrs_and_block()?; attrs.extend(iattrs); - Ok(self.mk_expr(lo.to(self.prev_span), ExprKind::Loop(body, opt_label), attrs)) + Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::Loop(body, opt_label), attrs)) } fn eat_label(&mut self) -> Option

Version {}

\ \

Back to index

", - crate_name, version + crate_name, + Escape(version), ) } else { String::new() @@ -3974,7 +3975,7 @@ fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer) { "
\

Version {}

\
", - version + Escape(version) ); } } diff --git a/src/test/rustdoc/crate-version-escape.rs b/src/test/rustdoc/crate-version-escape.rs new file mode 100644 index 00000000000..2f91eea339b --- /dev/null +++ b/src/test/rustdoc/crate-version-escape.rs @@ -0,0 +1,6 @@ +// compile-flags: --crate-version= -Z unstable-options + +#![crate_name = "foo"] + +// @has 'foo/index.html' '//div[@class="block version"]/p' 'Version ' +// @has 'foo/all.html' '//div[@class="block version"]/p' 'Version ' From 2746e12948ee4d152f8d8acfb5873f970effe501 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 1 Mar 2020 03:52:45 +0100 Subject: [PATCH 0648/1250] check_binding_alt_eq_ty: improve precision wrt. `if let`. --- src/librustc_typeck/check/pat.rs | 12 ++++++++++-- .../or-patterns-binding-type-mismatch.stderr | 16 ++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index d5cc19f986f..2a8be6a0244 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -559,8 +559,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let var_ty = self.resolve_vars_with_obligations(var_ty); let msg = format!("first introduced with type `{}` here", var_ty); err.span_label(hir.span(var_id), msg); - let in_arm = hir.parent_iter(var_id).any(|(_, n)| matches!(n, hir::Node::Arm(..))); - let pre = if in_arm { "in the same arm, " } else { "" }; + let in_match = hir.parent_iter(var_id).any(|(_, n)| { + matches!( + n, + hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Match(.., hir::MatchSource::Normal), + .. + }) + ) + }); + let pre = if in_match { "in the same arm, " } else { "" }; err.note(&format!("{}a binding must have the same type in all alternatives", pre)); err.emit(); } diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index d5e029d668d..1dabb7c9754 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -101,7 +101,7 @@ LL | if let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2) { | | expected `usize`, found `isize` | first introduced with type `usize` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:38:47 @@ -112,7 +112,7 @@ LL | if let Some(Blah::A(_, x, y) | Blah::B(x, y)) = Some(Blah::A(1, 1, 2)) | | expected `usize`, found `isize` | first introduced with type `usize` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:42:22 @@ -123,7 +123,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | | expected `u16`, found `u8` | first introduced with type `u16` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:42:25 @@ -134,7 +134,7 @@ LL | if let (x, y) | (y, x) = (0u8, 1u16) { | | expected `u8`, found `u16` | first introduced with type `u8` here | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:44 @@ -147,7 +147,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:53 @@ -160,7 +160,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:62 @@ -173,7 +173,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:47:65 @@ -184,7 +184,7 @@ LL | if let Some((x, Some((y, z)))) | Some((y, Some((x, z) | (z, x)))) LL | = Some((0u8, Some((1u16, 2u32)))) | ------------------------------- this expression has type `std::option::Option<(u8, std::option::Option<(u16, u32)>)>` | - = note: in the same arm, a binding must have the same type in all alternatives + = note: a binding must have the same type in all alternatives error[E0308]: mismatched types --> $DIR/or-patterns-binding-type-mismatch.rs:55:39 From 71f92bb8123a1307bb52af63b13637d774c744eb Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Sat, 29 Feb 2020 23:54:13 -0500 Subject: [PATCH 0649/1250] [tidy] update documentation from `make check` to `x.py test` --- src/tools/tidy/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index ec8b14c288a..0b433965051 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -1,8 +1,8 @@ //! Tidy checks source code in this repository. //! //! This program runs all of the various tidy checks for style, cleanliness, -//! etc. This is run by default on `make check` and as part of the auto -//! builders. +//! etc. This is run by default on `./x.py test` and as part of the auto +//! builders. The tidy checks can be executed with `./x.py test src/tools/tidy`. #![deny(warnings)] From f9c8c49c0b04322d5a0714693775a347ff7502a6 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sun, 1 Mar 2020 15:15:29 +0900 Subject: [PATCH 0650/1250] Use `opt_def_id()` over `def_id()` --- src/librustc_save_analysis/lib.rs | 2 +- src/test/ui/attributes/register-attr-tool-import.rs | 2 ++ .../ui/attributes/register-attr-tool-import.stderr | 12 ++++++------ 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index b253559dd5c..93abca4862d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -816,7 +816,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { fn lookup_def_id(&self, ref_id: NodeId) -> Option { match self.get_path_res(ref_id) { Res::PrimTy(_) | Res::SelfTy(..) | Res::Err => None, - def => Some(def.def_id()), + def => def.opt_def_id(), } } diff --git a/src/test/ui/attributes/register-attr-tool-import.rs b/src/test/ui/attributes/register-attr-tool-import.rs index e01dc4dfa49..d3502c71f2d 100644 --- a/src/test/ui/attributes/register-attr-tool-import.rs +++ b/src/test/ui/attributes/register-attr-tool-import.rs @@ -1,4 +1,6 @@ // edition:2018 +// compile-flags: -Zsave-analysis +// ~^ Also regression test for #69588 #![feature(register_attr)] #![feature(register_tool)] diff --git a/src/test/ui/attributes/register-attr-tool-import.stderr b/src/test/ui/attributes/register-attr-tool-import.stderr index 59f5a8620ab..90b7e169a2f 100644 --- a/src/test/ui/attributes/register-attr-tool-import.stderr +++ b/src/test/ui/attributes/register-attr-tool-import.stderr @@ -1,35 +1,35 @@ error: cannot use an explicitly registered attribute through an import - --> $DIR/register-attr-tool-import.rs:12:3 + --> $DIR/register-attr-tool-import.rs:14:3 | LL | #[renamed_attr] | ^^^^^^^^^^^^ | note: the explicitly registered attribute imported here - --> $DIR/register-attr-tool-import.rs:9:5 + --> $DIR/register-attr-tool-import.rs:11:5 | LL | use attr as renamed_attr; // OK | ^^^^^^^^^^^^^^^^^^^^ error: cannot use a tool module through an import - --> $DIR/register-attr-tool-import.rs:13:3 + --> $DIR/register-attr-tool-import.rs:15:3 | LL | #[renamed_tool::attr] | ^^^^^^^^^^^^ | note: the tool module imported here - --> $DIR/register-attr-tool-import.rs:10:5 + --> $DIR/register-attr-tool-import.rs:12:5 | LL | use tool as renamed_tool; // OK | ^^^^^^^^^^^^^^^^^^^^ error: cannot use a tool module through an import - --> $DIR/register-attr-tool-import.rs:13:3 + --> $DIR/register-attr-tool-import.rs:15:3 | LL | #[renamed_tool::attr] | ^^^^^^^^^^^^ | note: the tool module imported here - --> $DIR/register-attr-tool-import.rs:10:5 + --> $DIR/register-attr-tool-import.rs:12:5 | LL | use tool as renamed_tool; // OK | ^^^^^^^^^^^^^^^^^^^^ From 857e34c7a39f3bdab948888d36c2ee614fc73857 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Feb 2020 15:51:08 +0300 Subject: [PATCH 0651/1250] ast: Unmerge structures for associated items and foreign items --- src/librustc_ast/ast.rs | 60 +++++++++++++-------- src/librustc_ast/attr/mod.rs | 2 +- src/librustc_ast/mut_visit.rs | 39 ++++++++------ src/librustc_ast/visit.rs | 44 ++++++++------- src/librustc_ast_lowering/item.rs | 20 +++---- src/librustc_ast_passes/ast_validation.rs | 2 +- src/librustc_ast_passes/feature_gate.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 42 ++++++++------- src/librustc_expand/expand.rs | 7 +-- src/librustc_resolve/build_reduced_graph.rs | 5 +- src/librustc_resolve/def_collector.rs | 4 +- src/librustc_resolve/late.rs | 7 ++- src/librustc_save_analysis/dump_visitor.rs | 9 ++-- src/librustc_save_analysis/lib.rs | 3 +- src/librustc_save_analysis/sig.rs | 1 - 15 files changed, 134 insertions(+), 113 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 62ff4f5183a..a0ea09720b4 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -2441,10 +2441,10 @@ impl Item { } } -impl Item { +impl> Item { pub fn into_item(self) -> Item { let Item { attrs, id, span, vis, ident, kind, tokens } = self; - Item { attrs, id, span, vis, ident, kind: kind.into_item_kind(), tokens } + Item { attrs, id, span, vis, ident, kind: kind.into(), tokens } } } @@ -2624,20 +2624,11 @@ impl ItemKind { } } -pub trait IntoItemKind { - fn into_item_kind(self) -> ItemKind; -} - -// FIXME(Centril): These definitions should be unmerged; -// see https://github.com/rust-lang/rust/pull/69194#discussion_r379899975 -pub type ForeignItem = Item; -pub type ForeignItemKind = AssocItemKind; - /// Represents associated items. /// These include items in `impl` and `trait` definitions. pub type AssocItem = Item; -/// Represents non-free item kinds. +/// Represents associated item kinds. /// /// The term "provided" in the variants below refers to the item having a default /// definition / body. Meanwhile, a "required" item lacks a definition / body. @@ -2646,16 +2637,14 @@ pub type AssocItem = Item; /// means "provided" and conversely `None` means "required". #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum AssocItemKind { - /// A constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. + /// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`. /// If `def` is parsed, then the constant is provided, and otherwise required. Const(Defaultness, P, Option>), - /// A static item (`static FOO: u8`). - Static(P, Mutability, Option>), - /// A function. + /// An associated function. Fn(Defaultness, FnSig, Generics, Option>), - /// A type. + /// An associated type. TyAlias(Defaultness, Generics, GenericBounds, Option>), - /// A macro expanding to items. + /// A macro expanding to associated items. Macro(Mac), } @@ -2663,19 +2652,44 @@ impl AssocItemKind { pub fn defaultness(&self) -> Defaultness { match *self { Self::Const(def, ..) | Self::Fn(def, ..) | Self::TyAlias(def, ..) => def, - Self::Macro(..) | Self::Static(..) => Defaultness::Final, + Self::Macro(..) => Defaultness::Final, } } } -impl IntoItemKind for AssocItemKind { - fn into_item_kind(self) -> ItemKind { - match self { +impl From for ItemKind { + fn from(assoc_item_kind: AssocItemKind) -> ItemKind { + match assoc_item_kind { AssocItemKind::Const(a, b, c) => ItemKind::Const(a, b, c), - AssocItemKind::Static(a, b, c) => ItemKind::Static(a, b, c), AssocItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d), AssocItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d), AssocItemKind::Macro(a) => ItemKind::Mac(a), } } } + +/// An item in `extern` block. +#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum ForeignItemKind { + /// A foreign static item (`static FOO: u8`). + Static(P, Mutability, Option>), + /// A foreign function. + Fn(Defaultness, FnSig, Generics, Option>), + /// A foreign type. + TyAlias(Defaultness, Generics, GenericBounds, Option>), + /// A macro expanding to foreign items. + Macro(Mac), +} + +impl From for ItemKind { + fn from(foreign_item_kind: ForeignItemKind) -> ItemKind { + match foreign_item_kind { + ForeignItemKind::Static(a, b, c) => ItemKind::Static(a, b, c), + ForeignItemKind::Fn(a, b, c, d) => ItemKind::Fn(a, b, c, d), + ForeignItemKind::TyAlias(a, b, c, d) => ItemKind::TyAlias(a, b, c, d), + ForeignItemKind::Macro(a) => ItemKind::Mac(a), + } + } +} + +pub type ForeignItem = Item; diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index bc5c86b02b3..2b50b946580 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -722,6 +722,6 @@ macro_rules! derive_has_attrs { } derive_has_attrs! { - Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::Arm, + Item, Expr, Local, ast::AssocItem, ast::ForeignItem, ast::StructField, ast::Arm, ast::Field, ast::FieldPat, ast::Variant, ast::Param, GenericParam } diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs index b3abd4fc755..09964dd29c3 100644 --- a/src/librustc_ast/mut_visit.rs +++ b/src/librustc_ast/mut_visit.rs @@ -936,25 +936,12 @@ pub fn noop_flat_map_assoc_item( visitor: &mut T, ) -> SmallVec<[P; 1]> { let Item { id, ident, vis, attrs, kind, span, tokens: _ } = item.deref_mut(); - walk_nested_item(visitor, id, span, ident, vis, attrs, kind); - smallvec![item] -} - -pub fn walk_nested_item( - visitor: &mut impl MutVisitor, - id: &mut NodeId, - span: &mut Span, - ident: &mut Ident, - vis: &mut Visibility, - attrs: &mut Vec, - kind: &mut AssocItemKind, -) { visitor.visit_id(id); visitor.visit_ident(ident); visitor.visit_vis(vis); visit_attrs(attrs, visitor); match kind { - AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => { + AssocItemKind::Const(_, ty, expr) => { visitor.visit_ty(ty); visit_opt(expr, |expr| visitor.visit_expr(expr)); } @@ -971,6 +958,7 @@ pub fn walk_nested_item( AssocItemKind::Macro(mac) => visitor.visit_mac(mac), } visitor.visit_span(span); + smallvec![item] } pub fn noop_visit_fn_header(header: &mut FnHeader, vis: &mut T) { @@ -1036,7 +1024,28 @@ pub fn noop_flat_map_foreign_item( visitor: &mut T, ) -> SmallVec<[P; 1]> { let Item { ident, attrs, id, kind, vis, span, tokens: _ } = item.deref_mut(); - walk_nested_item(visitor, id, span, ident, vis, attrs, kind); + visitor.visit_id(id); + visitor.visit_ident(ident); + visitor.visit_vis(vis); + visit_attrs(attrs, visitor); + match kind { + ForeignItemKind::Static(ty, _, expr) => { + visitor.visit_ty(ty); + visit_opt(expr, |expr| visitor.visit_expr(expr)); + } + ForeignItemKind::Fn(_, sig, generics, body) => { + visitor.visit_generics(generics); + visit_fn_sig(sig, visitor); + visit_opt(body, |body| visitor.visit_block(body)); + } + ForeignItemKind::TyAlias(_, generics, bounds, ty) => { + visitor.visit_generics(generics); + visit_bounds(bounds, visitor); + visit_opt(ty, |ty| visitor.visit_ty(ty)); + } + ForeignItemKind::Macro(mac) => visitor.visit_mac(mac), + } + visitor.visit_span(span); smallvec![item] } diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs index 96149ad7947..89e917dc53d 100644 --- a/src/librustc_ast/visit.rs +++ b/src/librustc_ast/visit.rs @@ -526,8 +526,29 @@ pub fn walk_pat<'a, V: Visitor<'a>>(visitor: &mut V, pattern: &'a Pat) { } pub fn walk_foreign_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a ForeignItem) { - let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; - walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Foreign); + let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item; + visitor.visit_vis(vis); + visitor.visit_ident(ident); + walk_list!(visitor, visit_attribute, attrs); + match kind { + ForeignItemKind::Static(ty, _, expr) => { + visitor.visit_ty(ty); + walk_list!(visitor, visit_expr, expr); + } + ForeignItemKind::Fn(_, sig, generics, body) => { + visitor.visit_generics(generics); + let kind = FnKind::Fn(FnCtxt::Foreign, ident, sig, vis, body.as_deref()); + visitor.visit_fn(kind, span, id); + } + ForeignItemKind::TyAlias(_, generics, bounds, ty) => { + visitor.visit_generics(generics); + walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_ty, ty); + } + ForeignItemKind::Macro(mac) => { + visitor.visit_mac(mac); + } + } } pub fn walk_global_asm<'a, V: Visitor<'a>>(_: &mut V, _: &'a GlobalAsm) { @@ -610,31 +631,18 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>, _span: Spa } pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem, ctxt: AssocCtxt) { - let Item { id, span, ident, vis, attrs, kind, tokens: _ } = item; - walk_nested_item(visitor, *id, *span, *ident, vis, attrs, kind, FnCtxt::Assoc(ctxt)); -} - -fn walk_nested_item<'a, V: Visitor<'a>>( - visitor: &mut V, - id: NodeId, - span: Span, - ident: Ident, - vis: &'a Visibility, - attrs: &'a [Attribute], - kind: &'a AssocItemKind, - ctxt: FnCtxt, -) { + let Item { id, span, ident, ref vis, ref attrs, ref kind, tokens: _ } = *item; visitor.visit_vis(vis); visitor.visit_ident(ident); walk_list!(visitor, visit_attribute, attrs); match kind { - AssocItemKind::Const(_, ty, expr) | AssocItemKind::Static(ty, _, expr) => { + AssocItemKind::Const(_, ty, expr) => { visitor.visit_ty(ty); walk_list!(visitor, visit_expr, expr); } AssocItemKind::Fn(_, sig, generics, body) => { visitor.visit_generics(generics); - let kind = FnKind::Fn(ctxt, ident, sig, vis, body.as_deref()); + let kind = FnKind::Fn(FnCtxt::Assoc(ctxt), ident, sig, vis, body.as_deref()); visitor.visit_fn(kind, span, id); } AssocItemKind::TyAlias(_, generics, bounds, ty) => { diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 13148d97a67..46aad99f131 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -675,11 +675,6 @@ impl<'hir> LoweringContext<'_, 'hir> { let ty = self.lower_ty(t, ImplTraitContext::disallowed()); hir::ForeignItemKind::Static(ty, m) } - ForeignItemKind::Const(_, ref t, _) => { - // For recovery purposes. - let ty = self.lower_ty(t, ImplTraitContext::disallowed()); - hir::ForeignItemKind::Static(ty, Mutability::Not) - } ForeignItemKind::TyAlias(..) => hir::ForeignItemKind::Type, ForeignItemKind::Macro(_) => panic!("macro shouldn't exist here"), }, @@ -757,8 +752,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match i.kind { - AssocItemKind::Static(ref ty, _, ref default) // Let's pretend this is a `const`. - | AssocItemKind::Const(_, ref ty, ref default) => { + AssocItemKind::Const(_, ref ty, ref default) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); let body = default.as_ref().map(|x| self.lower_const_body(i.span, Some(x))); (hir::Generics::empty(), hir::TraitItemKind::Const(ty, body)) @@ -800,11 +794,10 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_trait_item_ref(&mut self, i: &AssocItem) -> hir::TraitItemRef { let (kind, has_default) = match &i.kind { - AssocItemKind::Static(_, _, default) // Let's pretend this is a `const` for recovery. - | AssocItemKind::Const(_, _, default) => { - (hir::AssocItemKind::Const, default.is_some()) + AssocItemKind::Const(_, _, default) => (hir::AssocItemKind::Const, default.is_some()), + AssocItemKind::TyAlias(_, _, _, default) => { + (hir::AssocItemKind::Type, default.is_some()) } - AssocItemKind::TyAlias(_, _, _, default) => (hir::AssocItemKind::Type, default.is_some()), AssocItemKind::Fn(_, sig, _, default) => { (hir::AssocItemKind::Method { has_self: sig.decl.has_self() }, default.is_some()) } @@ -824,7 +817,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); let (generics, kind) = match &i.kind { - AssocItemKind::Static(ty, _, expr) | AssocItemKind::Const(_, ty, expr) => { + AssocItemKind::Const(_, ty, expr) => { let ty = self.lower_ty(ty, ImplTraitContext::disallowed()); ( hir::Generics::empty(), @@ -892,8 +885,7 @@ impl<'hir> LoweringContext<'_, 'hir> { vis: self.lower_visibility(&i.vis, Some(i.id)), defaultness: self.lower_defaultness(i.kind.defaultness(), true /* [1] */), kind: match &i.kind { - AssocItemKind::Static(..) // Let's pretend this is a `const` for recovery. - | AssocItemKind::Const(..) => hir::AssocItemKind::Const, + AssocItemKind::Const(..) => hir::AssocItemKind::Const, AssocItemKind::TyAlias(.., ty) => { match ty.as_deref().and_then(|ty| ty.kind.opaque_top_hack()) { None => hir::AssocItemKind::Type, diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 9f04c01bfa8..69d5610e016 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -976,7 +976,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ForeignItemKind::Static(_, _, body) => { self.check_foreign_kind_bodyless(fi.ident, "static", body.as_ref().map(|b| b.span)); } - ForeignItemKind::Const(..) | ForeignItemKind::Macro(..) => {} + ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, fi) diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 05e69d0cfd7..97c88d4f1d9 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -400,7 +400,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { ast::ForeignItemKind::TyAlias(..) => { gate_feature_post!(&self, extern_types, i.span, "extern types are experimental"); } - ast::ForeignItemKind::Macro(..) | ast::ForeignItemKind::Const(..) => {} + ast::ForeignItemKind::Macro(..) => {} } visit::walk_foreign_item(self, i) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index ea8535eabef..16558ccb3c3 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -971,19 +971,7 @@ impl<'a> State<'a> { } crate fn print_foreign_item(&mut self, item: &ast::ForeignItem) { - let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item; - self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis); - } - - fn print_nested_item_kind( - &mut self, - id: ast::NodeId, - span: Span, - ident: ast::Ident, - attrs: &[Attribute], - kind: &ast::AssocItemKind, - vis: &ast::Visibility, - ) { + let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; self.ann.pre(self, AnnNode::SubItem(id)); self.hardbreak_if_not_bol(); self.maybe_print_comment(span.lo()); @@ -992,9 +980,6 @@ impl<'a> State<'a> { ast::ForeignItemKind::Fn(def, sig, gen, body) => { self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs); } - ast::ForeignItemKind::Const(def, ty, body) => { - self.print_item_const(ident, None, ty, body.as_deref(), vis, *def); - } ast::ForeignItemKind::Static(ty, mutbl, body) => { let def = ast::Defaultness::Final; self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def); @@ -1413,8 +1398,29 @@ impl<'a> State<'a> { } crate fn print_assoc_item(&mut self, item: &ast::AssocItem) { - let ast::Item { id, span, ident, attrs, kind, vis, tokens: _ } = item; - self.print_nested_item_kind(*id, *span, *ident, attrs, kind, vis); + let ast::Item { id, span, ident, ref attrs, ref kind, ref vis, tokens: _ } = *item; + self.ann.pre(self, AnnNode::SubItem(id)); + self.hardbreak_if_not_bol(); + self.maybe_print_comment(span.lo()); + self.print_outer_attributes(attrs); + match kind { + ast::AssocItemKind::Fn(def, sig, gen, body) => { + self.print_fn_full(sig, ident, gen, vis, *def, body.as_deref(), attrs); + } + ast::AssocItemKind::Const(def, ty, body) => { + self.print_item_const(ident, None, ty, body.as_deref(), vis, *def); + } + ast::AssocItemKind::TyAlias(def, generics, bounds, ty) => { + self.print_associated_type(ident, generics, bounds, ty.as_deref(), vis, *def); + } + ast::AssocItemKind::Macro(m) => { + self.print_mac(m); + if m.args.need_semicolon() { + self.s.word(";"); + } + } + } + self.ann.post(self, AnnNode::SubItem(id)) } crate fn print_stmt(&mut self, st: &ast::Stmt) { diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index a2c512fda91..b16659725db 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -674,11 +674,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let item_tok = TokenTree::token( token::Interpolated(Lrc::new(match item { Annotatable::Item(item) => token::NtItem(item), - Annotatable::TraitItem(item) - | Annotatable::ImplItem(item) - | Annotatable::ForeignItem(item) => { + Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { token::NtItem(P(item.and_then(ast::AssocItem::into_item))) } + Annotatable::ForeignItem(item) => { + token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) + } Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), Annotatable::Expr(expr) => token::NtExpr(expr), Annotatable::Arm(..) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 86816fd9f3a..43cfe05ac23 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -826,7 +826,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ForeignItemKind::Fn(..) => { (Res::Def(DefKind::Fn, self.r.definitions.local_def_id(item.id)), ValueNS) } - ForeignItemKind::Static(..) | ForeignItemKind::Const(..) => { + ForeignItemKind::Static(..) => { (Res::Def(DefKind::Static, self.r.definitions.local_def_id(item.id)), ValueNS) } ForeignItemKind::TyAlias(..) => { @@ -1251,8 +1251,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { // Add the item to the trait info. let item_def_id = self.r.definitions.local_def_id(item.id); let (res, ns) = match item.kind { - AssocItemKind::Static(..) // Let's pretend it's a `const` for recovery. - | AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), + AssocItemKind::Const(..) => (Res::Def(DefKind::AssocConst, item_def_id), ValueNS), AssocItemKind::Fn(_, ref sig, _, _) => { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 2e687c88941..0d276e68614 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -228,9 +228,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { body.as_deref(), ); } - AssocItemKind::Fn(..) | AssocItemKind::Const(..) | AssocItemKind::Static(..) => { - DefPathData::ValueNs(i.ident.name) - } + AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id), }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index e5aa9c7d896..a3554ea2ee0 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -444,7 +444,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { visit::walk_foreign_item(this, foreign_item); }); } - ForeignItemKind::Const(..) | ForeignItemKind::Static(..) => { + ForeignItemKind::Static(..) => { self.with_item_rib(HasGenericParams::No, |this| { visit::walk_foreign_item(this, foreign_item); }); @@ -838,8 +838,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for item in trait_items { this.with_trait_items(trait_items, |this| { match &item.kind { - AssocItemKind::Static(ty, _, default) - | AssocItemKind::Const(_, ty, default) => { + AssocItemKind::Const(_, ty, default) => { this.visit_ty(ty); // Only impose the restrictions of `ConstRibKind` for an // actual constant expression in a provided default. @@ -1114,7 +1113,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { for item in impl_items { use crate::ResolutionError::*; match &item.kind { - AssocItemKind::Static(..) | AssocItemKind::Const(..) => { + AssocItemKind::Const(..) => { debug!("resolve_implementation AssocItemKind::Const",); // If this is a trait impl, ensure the const // exists in trait diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index e8cd5ea832d..72c962749c8 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -1004,8 +1004,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.process_macro_use(trait_item.span); let vis_span = trait_item.span.shrink_to_lo(); match trait_item.kind { - ast::AssocItemKind::Static(ref ty, _, ref expr) - | ast::AssocItemKind::Const(_, ref ty, ref expr) => { + ast::AssocItemKind::Const(_, ref ty, ref expr) => { self.process_assoc_const( trait_item.id, trait_item.ident, @@ -1075,8 +1074,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { fn process_impl_item(&mut self, impl_item: &'l ast::AssocItem, impl_id: DefId) { self.process_macro_use(impl_item.span); match impl_item.kind { - ast::AssocItemKind::Static(ref ty, _, ref expr) - | ast::AssocItemKind::Const(_, ref ty, ref expr) => { + ast::AssocItemKind::Const(_, ref ty, ref expr) => { self.process_assoc_const( impl_item.id, impl_item.ident, @@ -1537,8 +1535,7 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { self.visit_ty(&ret_ty); } } - ast::ForeignItemKind::Const(_, ref ty, _) - | ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Static(ref ty, _, _) => { if let Some(var_data) = self.save_ctxt.get_extern_item_data(item) { down_cast_data!(var_data, DefData, item.span); self.dumper.dump_def(&access, var_data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index dddee1c9926..d364c45c40d 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -151,8 +151,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { attributes: lower_attributes(item.attrs.clone(), self), })) } - ast::ForeignItemKind::Const(_, ref ty, _) - | ast::ForeignItemKind::Static(ref ty, _, _) => { + ast::ForeignItemKind::Static(ref ty, _, _) => { filter!(self.span_utils, item.ident.span); let id = id_from_node_id(item.id, self); diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 32da62adc3c..a295e1637aa 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -795,7 +795,6 @@ impl Sig for ast::ForeignItem { Ok(Signature { text: text, defs: defs, refs: vec![] }) } - ast::ForeignItemKind::Const(..) => Err("foreign const"), ast::ForeignItemKind::Macro(..) => Err("macro"), } } From 9c885d40fb2b216dee5ebd42c35929ad8b54bf4a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 29 Feb 2020 18:29:44 +0300 Subject: [PATCH 0652/1250] ast: Implement `TryFrom` for associated and foreign items --- src/librustc_ast/ast.rs | 29 ++++++++++++++++++++++ src/librustc_parse/parser/item.rs | 40 +++++++++++++++---------------- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index a0ea09720b4..685b21a1717 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -38,6 +38,7 @@ use rustc_span::source_map::{respan, Spanned}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; +use std::convert::TryFrom; use std::fmt; use std::iter; @@ -2668,6 +2669,20 @@ impl From for ItemKind { } } +impl TryFrom for AssocItemKind { + type Error = ItemKind; + + fn try_from(item_kind: ItemKind) -> Result { + Ok(match item_kind { + ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), + ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), + ItemKind::Mac(a) => AssocItemKind::Macro(a), + _ => return Err(item_kind), + }) + } +} + /// An item in `extern` block. #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub enum ForeignItemKind { @@ -2692,4 +2707,18 @@ impl From for ItemKind { } } +impl TryFrom for ForeignItemKind { + type Error = ItemKind; + + fn try_from(item_kind: ItemKind) -> Result { + Ok(match item_kind { + ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), + ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), + ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), + ItemKind::Mac(a) => ForeignItemKind::Macro(a), + _ => return Err(item_kind), + }) + } +} + pub type ForeignItem = Item; diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index cf07e452acb..08e74034e86 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -24,6 +24,7 @@ use rustc_span::source_map::{self, Span}; use rustc_span::symbol::{kw, sym, Symbol}; use log::debug; +use std::convert::TryFrom; use std::mem; pub(super) type ItemInfo = (Ident, ItemKind); @@ -647,16 +648,16 @@ impl<'a> Parser<'a> { /// Parses associated items. fn parse_assoc_item(&mut self, req_name: ReqName) -> PResult<'a, Option>>> { Ok(self.parse_item_(req_name)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { - let kind = match kind { - ItemKind::Mac(a) => AssocItemKind::Macro(a), - ItemKind::Fn(a, b, c, d) => AssocItemKind::Fn(a, b, c, d), - ItemKind::TyAlias(a, b, c, d) => AssocItemKind::TyAlias(a, b, c, d), - ItemKind::Const(a, b, c) => AssocItemKind::Const(a, b, c), - ItemKind::Static(a, _, b) => { - self.struct_span_err(span, "associated `static` items are not allowed").emit(); - AssocItemKind::Const(Defaultness::Final, a, b) - } - _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), + let kind = match AssocItemKind::try_from(kind) { + Ok(kind) => kind, + Err(kind) => match kind { + ItemKind::Static(a, _, b) => { + self.struct_span_err(span, "associated `static` items are not allowed") + .emit(); + AssocItemKind::Const(Defaultness::Final, a, b) + } + _ => return self.error_bad_item_kind(span, &kind, "`trait`s or `impl`s"), + }, }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) @@ -833,16 +834,15 @@ impl<'a> Parser<'a> { /// Parses a foreign item (one in an `extern { ... }` block). pub fn parse_foreign_item(&mut self) -> PResult<'a, Option>>> { Ok(self.parse_item_(|_| true)?.map(|Item { attrs, id, span, vis, ident, kind, tokens }| { - let kind = match kind { - ItemKind::Mac(a) => ForeignItemKind::Macro(a), - ItemKind::Fn(a, b, c, d) => ForeignItemKind::Fn(a, b, c, d), - ItemKind::TyAlias(a, b, c, d) => ForeignItemKind::TyAlias(a, b, c, d), - ItemKind::Static(a, b, c) => ForeignItemKind::Static(a, b, c), - ItemKind::Const(_, a, b) => { - self.error_on_foreign_const(span, ident); - ForeignItemKind::Static(a, Mutability::Not, b) - } - _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), + let kind = match ForeignItemKind::try_from(kind) { + Ok(kind) => kind, + Err(kind) => match kind { + ItemKind::Const(_, a, b) => { + self.error_on_foreign_const(span, ident); + ForeignItemKind::Static(a, Mutability::Not, b) + } + _ => return self.error_bad_item_kind(span, &kind, "`extern` blocks"), + }, }; Some(P(Item { attrs, id, span, vis, ident, kind, tokens })) })) From dd142b1dc43f0e9a9b860003816b1a91b4e1a52d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 1 Mar 2020 12:03:38 +0100 Subject: [PATCH 0653/1250] Clean up E0376 explanation --- src/librustc_error_codes/error_codes/E0376.md | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0376.md b/src/librustc_error_codes/error_codes/E0376.md index b028aab4583..50de15bd30f 100644 --- a/src/librustc_error_codes/error_codes/E0376.md +++ b/src/librustc_error_codes/error_codes/E0376.md @@ -1,14 +1,6 @@ -The type you are trying to impl `CoerceUnsized` for is not a struct. -`CoerceUnsized` can only be implemented for a struct. Unsized types are -already able to be coerced without an implementation of `CoerceUnsized` -whereas a struct containing an unsized type needs to know the unsized type -field it's containing is able to be coerced. An [unsized type][1] -is any type that the compiler doesn't know the length or alignment of at -compile time. Any struct containing an unsized type is also unsized. - -[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait +`CoerceUnsized` was implemented on something that isn't a struct. -Example of erroneous code: +Erroneous code example: ```compile_fail,E0376 #![feature(coerce_unsized)] @@ -22,6 +14,15 @@ struct Foo { impl CoerceUnsized for Foo {} ``` +`CoerceUnsized` can only be implemented for a struct. Unsized types are +already able to be coerced without an implementation of `CoerceUnsized` +whereas a struct containing an unsized type needs to know the unsized type +field it's containing is able to be coerced. An [unsized type][1] +is any type that the compiler doesn't know the length or alignment of at +compile time. Any struct containing an unsized type is also unsized. + +[1]: https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait + The `CoerceUnsized` trait takes a struct type. Make sure the type you are providing to `CoerceUnsized` is a struct with only the last field containing an unsized type. From 4023e5df7ebc2e50289c9828e374b0bf901a219d Mon Sep 17 00:00:00 2001 From: O01eg Date: Sun, 1 Mar 2020 14:33:52 +0300 Subject: [PATCH 0654/1250] Expose target libdir information via print command. With custom libdir it is required to have an access to library placement. --- src/librustc_driver/lib.rs | 4 ++++ src/librustc_session/config.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 9a94349e5fd..5089a14a34c 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -676,6 +676,10 @@ impl RustcDefaultCalls { println!("{}", targets.join("\n")); } Sysroot => println!("{}", sess.sysroot.display()), + TargetLibdir => println!( + "{}", + sess.target_tlib_path.as_ref().unwrap_or(&sess.host_tlib_path).dir.display() + ), TargetSpec => println!("{}", sess.target.target.to_json().pretty()), FileNames | CrateName => { let input = input.unwrap_or_else(|| { diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index db4412a18a3..60f25871dd9 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -391,6 +391,7 @@ impl ExternEntry { pub enum PrintRequest { FileNames, Sysroot, + TargetLibdir, CrateName, Cfg, TargetList, @@ -1344,6 +1345,7 @@ fn collect_print_requests( "crate-name" => PrintRequest::CrateName, "file-names" => PrintRequest::FileNames, "sysroot" => PrintRequest::Sysroot, + "target-libdir" => PrintRequest::TargetLibdir, "cfg" => PrintRequest::Cfg, "target-list" => PrintRequest::TargetList, "target-cpus" => PrintRequest::TargetCPUs, From 7694a6d6d9a3505a2b0b7b5cc21d501f88b867c3 Mon Sep 17 00:00:00 2001 From: O01eg Date: Sun, 1 Mar 2020 16:14:26 +0300 Subject: [PATCH 0655/1250] Print new --print option in help. --- src/librustc_session/config.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_session/config.rs b/src/librustc_session/config.rs index 60f25871dd9..c273e7fdbf9 100644 --- a/src/librustc_session/config.rs +++ b/src/librustc_session/config.rs @@ -913,7 +913,7 @@ pub fn rustc_short_optgroups() -> Vec { "", "print", "Compiler information to print on stdout", - "[crate-name|file-names|sysroot|cfg|target-list|\ + "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ target-cpus|target-features|relocation-models|\ code-models|tls-models|target-spec-json|native-static-libs]", ), From 87327eb72aa64256b2312a71f3a7e850b205b91b Mon Sep 17 00:00:00 2001 From: Michael Mc Donnell Date: Thu, 27 Feb 2020 06:47:44 -0800 Subject: [PATCH 0656/1250] Remove assert that had been replaced by assert_ne --- src/libcore/tests/hash/sip.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/tests/hash/sip.rs b/src/libcore/tests/hash/sip.rs index 12aa20a0bbd..5c0e114e93c 100644 --- a/src/libcore/tests/hash/sip.rs +++ b/src/libcore/tests/hash/sip.rs @@ -298,7 +298,6 @@ fn test_hash_no_concat_alias() { let t = ("aabb", ""); let u = ("a", "abb"); - assert!(s != t && t != u); assert_ne!(s, t); assert_ne!(t, u); assert_ne!(hash(&s), hash(&t)); From 7b6f5ed9562ad13b68224138992a06463de299c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 1 Mar 2020 10:46:07 -0800 Subject: [PATCH 0657/1250] `delay_span_bug` when codegen cannot select obligation Fix #69602, introduced in #60126 by letting the compiler continue past type checking after encountering errors. --- src/librustc/query/mod.rs | 2 +- src/librustc_infer/traits/codegen/mod.rs | 18 +++++++++------ src/librustc_mir/monomorphize/mod.rs | 2 +- src/librustc_ty/instance.rs | 2 +- ...issue-69602-type-err-during-codegen-ice.rs | 22 +++++++++++++++++++ ...e-69602-type-err-during-codegen-ice.stderr | 19 ++++++++++++++++ 6 files changed, 55 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs create mode 100644 src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b3315cc3701..27d9435ac57 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -650,7 +650,7 @@ rustc_queries! { Codegen { query codegen_fulfill_obligation( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) - ) -> Vtable<'tcx, ()> { + ) -> Option> { no_force cache_on_disk_if { true } desc { |tcx| diff --git a/src/librustc_infer/traits/codegen/mod.rs b/src/librustc_infer/traits/codegen/mod.rs index bd4129a4de7..f499565e919 100644 --- a/src/librustc_infer/traits/codegen/mod.rs +++ b/src/librustc_infer/traits/codegen/mod.rs @@ -19,7 +19,7 @@ use rustc::ty::{self, TyCtxt}; pub fn codegen_fulfill_obligation<'tcx>( ty: TyCtxt<'tcx>, (param_env, trait_ref): (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>), -) -> Vtable<'tcx, ()> { +) -> Option> { // Remove any references to regions; this helps improve caching. let trait_ref = ty.erase_regions(&trait_ref); @@ -47,11 +47,15 @@ pub fn codegen_fulfill_obligation<'tcx>( // leading to an ambiguous result. So report this as an // overflow bug, since I believe this is the only case // where ambiguity can result. - bug!( - "Encountered ambiguity selecting `{:?}` during codegen, \ - presuming due to overflow", - trait_ref - ) + infcx.tcx.sess.delay_span_bug( + rustc_span::DUMMY_SP, + &format!( + "encountered ambiguity selecting `{:?}` during codegen, presuming due to \ + overflow or prior type error", + trait_ref + ), + ); + return None; } Err(e) => { bug!("Encountered error `{:?}` selecting `{:?}` during codegen", e, trait_ref) @@ -71,7 +75,7 @@ pub fn codegen_fulfill_obligation<'tcx>( let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable); info!("Cache miss: {:?} => {:?}", trait_ref, vtable); - vtable + Some(vtable) }) } diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 8bc63bfcfcb..3dff06967e5 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -18,7 +18,7 @@ pub fn custom_coerce_unsize_info<'tcx>( }); match tcx.codegen_fulfill_obligation((ty::ParamEnv::reveal_all(), trait_ref)) { - traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => { + Some(traits::VtableImpl(traits::VtableImplData { impl_def_id, .. })) => { tcx.coerce_unsized_info(impl_def_id).custom_kind.unwrap() } vtable => { diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 484b774add4..c2b2196e74c 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -70,7 +70,7 @@ fn resolve_associated_item<'tcx>( ); let trait_ref = ty::TraitRef::from_method(tcx, trait_id, rcvr_substs); - let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref))); + let vtbl = tcx.codegen_fulfill_obligation((param_env, ty::Binder::bind(trait_ref)))?; // Now that we know which impl is being used, we can dispatch to // the actual function: diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs new file mode 100644 index 00000000000..2c5257ce063 --- /dev/null +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -0,0 +1,22 @@ +trait TraitA { + const VALUE: usize; +} + +struct A; +impl TraitA for A { + const VALUE: usize = 0; +} + +trait TraitB { + type MyA: TraitA; + const VALUE: usize = Self::MyA::VALUE; +} + +struct B; +impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` + type M = A; //~ ERROR type `M` is not a member of trait `TraitB` +} + +fn main() { + let _ = [0; B::VALUE]; +} diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr new file mode 100644 index 00000000000..8ae0f8b804c --- /dev/null +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -0,0 +1,19 @@ +error[E0437]: type `M` is not a member of trait `TraitB` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:17:5 + | +LL | type M = A; + | ^^^^^^^^^^^^^ not a member of trait `TraitB` + +error[E0046]: not all trait items implemented, missing: `MyA` + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:16:1 + | +LL | type MyA: TraitA; + | ----------------- `MyA` from trait +... +LL | impl TraitB for B { + | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0046, E0437. +For more information about an error, try `rustc --explain E0046`. From ae70ab071a3072f688bc09e431153b47f170907f Mon Sep 17 00:00:00 2001 From: DutchGhost Date: Sun, 1 Mar 2020 20:42:35 +0100 Subject: [PATCH 0658/1250] constify mem::forget --- src/libcore/mem/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 9eb151cf528..4ffd0141242 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -109,6 +109,7 @@ pub use crate::intrinsics::transmute; /// [ub]: ../../reference/behavior-considered-undefined.html /// [`ManuallyDrop`]: struct.ManuallyDrop.html #[inline] +#[rustc_const_unstable(feature = "const_forget", issue = "69616")] #[stable(feature = "rust1", since = "1.0.0")] pub fn forget(t: T) { ManuallyDrop::new(t); From eda8d82b95689cb6be0ee4f026c48ccbe6da0b83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 1 Mar 2020 20:03:56 +0100 Subject: [PATCH 0659/1250] use starts_with() instead of chars().next() == Some(x) --- src/librustc_typeck/check/demand.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0c5f3d3e99d..14f7a6b6817 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -526,7 +526,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // we may want to suggest removing a `&`. if !sm.span_to_filename(expr.span).is_real() { if let Ok(code) = sm.span_to_snippet(sp) { - if code.chars().next() == Some('&') { + if code.starts_with('&') { return Some(( sp, "consider removing the borrow", From 03aecda83ad54098266e9e44cc04e0b37c3cf47a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 1 Mar 2020 20:09:14 +0100 Subject: [PATCH 0660/1250] use subdsec_micros() instead of subsec_nanos() / 1000 --- src/libstd/sys/unix/net.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 79b0dc02978..b37675e0a0a 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -280,7 +280,7 @@ impl Socket { }; let mut timeout = libc::timeval { tv_sec: secs, - tv_usec: (dur.subsec_nanos() / 1000) as libc::suseconds_t, + tv_usec: dur.subsec_micros() as libc::suseconds_t, }; if timeout.tv_sec == 0 && timeout.tv_usec == 0 { timeout.tv_usec = 1; From 22339c340615d6c8ad6a05bf4ff339113c19d968 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 1 Mar 2020 20:21:09 +0100 Subject: [PATCH 0661/1250] use for (idx, item) in iter.enumerate() instead of manually counting loop iterations by variables --- src/librustc/ty/layout.rs | 6 ++---- src/librustc_errors/emitter.rs | 5 ++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e10c0241435..641f904ae69 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1382,10 +1382,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Write down the order of our locals that will be promoted to the prefix. { - let mut idx = 0u32; - for local in ineligible_locals.iter() { - assignments[local] = Ineligible(Some(idx)); - idx += 1; + for (idx, local) in ineligible_locals.iter().enumerate() { + assignments[local] = Ineligible(Some(idx as u32)); } } debug!("generator saved local assignments: {:?}", assignments); diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 2d7ff191c77..eb9d4b887ad 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -1574,9 +1574,9 @@ impl EmitterWriter { let line_start = sm.lookup_char_pos(parts[0].span.lo()).line; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); - let mut line_pos = 0; let mut lines = complete.lines(); - for line in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES) { + for (line_pos, line) in lines.by_ref().take(MAX_SUGGESTION_HIGHLIGHT_LINES).enumerate() + { // Print the span column to avoid confusion buffer.puts( row_num, @@ -1587,7 +1587,6 @@ impl EmitterWriter { // print the suggestion draw_col_separator(&mut buffer, row_num, max_line_num_len + 1); buffer.append(row_num, line, Style::NoStyle); - line_pos += 1; row_num += 1; } From 275dac7bfb6cfadd02c12edacbd4fdf529269424 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Sun, 1 Mar 2020 14:15:44 -0600 Subject: [PATCH 0662/1250] doc(librustc_error_codes): add long error explanation for E0719 Progresses #61137 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0719.md | 35 +++++++++++++++++++ .../associated-type-bounds/duplicate.stderr | 1 + src/test/ui/error-codes/E0719.stderr | 1 + 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0719.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 91a7b6c8958..a79fcb978ca 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -395,6 +395,7 @@ E0714: include_str!("./error_codes/E0714.md"), E0715: include_str!("./error_codes/E0715.md"), E0716: include_str!("./error_codes/E0716.md"), E0718: include_str!("./error_codes/E0718.md"), +E0719: include_str!("./error_codes/E0719.md"), E0720: include_str!("./error_codes/E0720.md"), E0723: include_str!("./error_codes/E0723.md"), E0725: include_str!("./error_codes/E0725.md"), @@ -604,7 +605,6 @@ E0747: include_str!("./error_codes/E0747.md"), E0710, // an unknown tool name found in scoped lint E0711, // a feature has been declared with conflicting stability attributes E0717, // rustc_promotable without stability attribute - E0719, // duplicate values for associated type binding // E0721, // `await` keyword E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions diff --git a/src/librustc_error_codes/error_codes/E0719.md b/src/librustc_error_codes/error_codes/E0719.md new file mode 100644 index 00000000000..38bc63550ac --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0719.md @@ -0,0 +1,35 @@ +The value for an associated type has already been specified. + +Erroneous code example: + +```compile_fail,E0719 +#![feature(associated_type_bounds)] + +trait FooTrait {} +trait BarTrait {} + +// error: associated type `Item` in trait `Iterator` is specified twice +struct Foo> { f: T } +``` + +`Item` in trait `Iterator` cannot be specified multiple times for struct `Foo`. +To fix this, create a new trait that is a combination of the desired traits and +specify the associated type with the new trait. + +Corrected example: + +``` +#![feature(associated_type_bounds)] + +trait FooTrait {} +trait BarTrait {} +trait FooBarTrait: FooTrait + BarTrait {} + +struct Foo> { f: T } +``` + +For more information about associated types, see [the book][bk-at]. For more +information on associated type bounds, see [RFC 2289][rfc-2289]. + +[bk-at]: https://doc.rust-lang.org/book/ch19-03-advanced-traits.html#specifying-placeholder-types-in-trait-definitions-with-associated-types +[rfc-2289]: https://rust-lang.github.io/rfcs/2289-associated-type-bounds.html diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index df1151d876c..82b2d32d09d 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -728,3 +728,4 @@ LL | type TADyn3 = dyn Iterator; error: aborting due to 96 previous errors +For more information about this error, try `rustc --explain E0719`. diff --git a/src/test/ui/error-codes/E0719.stderr b/src/test/ui/error-codes/E0719.stderr index a046fbfc3d0..0e4bbf083ba 100644 --- a/src/test/ui/error-codes/E0719.stderr +++ b/src/test/ui/error-codes/E0719.stderr @@ -16,3 +16,4 @@ LL | fn test() -> Box> { error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0719`. From ebc86b441d7122465c355e5f08b36664c6957aa7 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 22 Feb 2020 14:10:17 +0000 Subject: [PATCH 0663/1250] Fix use of `has_infer_types` * Add a new method `has_infer_types_or_consts` that's used instead most of the time, since there's generally no reason to only consider types. * Remove use of `has_closure_types`, because closures are no longer implicitly linked to the `InferCtxt`. --- src/librustc/ty/fold.rs | 6 ++-- src/librustc/ty/layout.rs | 4 +-- src/librustc_infer/infer/freshen.rs | 5 +--- src/librustc_infer/infer/mod.rs | 8 ++---- src/librustc_infer/infer/nll_relate/mod.rs | 2 +- src/librustc_infer/infer/resolve.rs | 4 +-- .../traits/error_reporting/mod.rs | 2 +- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_infer/traits/fulfill.rs | 13 ++------- src/librustc_infer/traits/mod.rs | 2 +- src/librustc_infer/traits/project.rs | 16 +++-------- .../implied_outlives_bounds.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 +-- .../into-iter-no-impls-length-33.stderr | 28 +++++++++---------- 14 files changed, 37 insertions(+), 61 deletions(-) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 3212bc72417..b88001f8783 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -90,6 +90,9 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) } + fn has_infer_types_or_consts(&self) -> bool { + self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_CT_INFER) + } fn has_infer_consts(&self) -> bool { self.has_type_flags(TypeFlags::HAS_CT_INFER) } @@ -114,9 +117,6 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { fn has_re_placeholders(&self) -> bool { self.has_type_flags(TypeFlags::HAS_RE_PLACEHOLDER) } - fn has_closure_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_TY_CLOSURE) - } /// "Free" regions in this context means that it has any region /// that is not (a) erased or (b) late-bound. fn has_free_regions(&self) -> bool { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e10c0241435..28553954b22 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -502,7 +502,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { let univariant = |fields: &[TyLayout<'_>], repr: &ReprOptions, kind| { Ok(tcx.intern_layout(self.univariant_uninterned(ty, fields, repr, kind)?)) }; - debug_assert!(!ty.has_infer_types()); + debug_assert!(!ty.has_infer_types_or_consts()); Ok(match ty.kind { // Basic scalars. @@ -1752,7 +1752,7 @@ impl<'tcx> SizeSkeleton<'tcx> { tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> Result, LayoutError<'tcx>> { - debug_assert!(!ty.has_infer_types()); + debug_assert!(!ty.has_infer_types_or_consts()); // First try computing a static layout. let err = match tcx.layout_of(param_env.and(ty)) { diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index f7141c56199..a454feea36b 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -143,10 +143,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !(t.needs_infer() - || t.has_erasable_regions() - || (t.has_closure_types() && self.infcx.in_progress_tables.is_some())) - { + if !t.needs_infer() && !t.has_erasable_regions() { return t; } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 36572826ae4..6adddf2500c 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -1482,12 +1482,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> bool { let ty = self.resolve_vars_if_possible(&ty); - // Even if the type may have no inference variables, during - // type-checking closure types are in local tables only. - if self.in_progress_tables.is_none() || !ty.has_closure_types() { - if !(param_env, ty).has_local_value() { - return ty.is_copy_modulo_regions(self.tcx, param_env, span); - } + if !(param_env, ty).has_local_value() { + return ty.is_copy_modulo_regions(self.tcx, param_env, span); } let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); diff --git a/src/librustc_infer/infer/nll_relate/mod.rs b/src/librustc_infer/infer/nll_relate/mod.rs index e35b8f9c8ec..50bea300c50 100644 --- a/src/librustc_infer/infer/nll_relate/mod.rs +++ b/src/librustc_infer/infer/nll_relate/mod.rs @@ -340,7 +340,7 @@ where // In NLL, we don't have type inference variables // floating around, so we can do this rather imprecise // variant of the occurs-check. - assert!(!generalized_ty.has_infer_types()); + assert!(!generalized_ty.has_infer_types_or_consts()); } self.infcx.inner.borrow_mut().type_variables.instantiate(vid, generalized_ty); diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index 3510b927d96..e2207d08ee6 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -28,7 +28,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { } fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { - if !t.has_infer_types() && !t.has_infer_consts() { + if !t.has_infer_types_or_consts() { t // micro-optimize -- if there is nothing in this type that this fold affects... } else { let t = self.infcx.shallow_resolve(t); @@ -37,7 +37,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for OpportunisticVarResolver<'a, 'tcx> { } fn fold_const(&mut self, ct: &'tcx Const<'tcx>) -> &'tcx Const<'tcx> { - if !ct.has_infer_consts() { + if !ct.has_infer_types_or_consts() { ct // micro-optimize -- if there is nothing in this const that this fold affects... } else { let ct = self.infcx.shallow_resolve(ct); diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 471f388f0bb..7a84a5f5c72 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -647,7 +647,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } // Try to report a help message - if !trait_ref.has_infer_types() + if !trait_ref.has_infer_types_or_consts() && self.predicate_can_apply(obligation.param_env, trait_ref) { // If a where-clause may be useful, remind the diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index f1206ddf909..ed6cfa51cdf 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -471,7 +471,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { return; } let trait_ref = self.resolve_vars_if_possible(trait_ref); - if trait_ref.has_infer_types() { + if trait_ref.has_infer_types_or_consts() { // Do not ICE while trying to find if a reborrow would succeed on a trait with // unresolved bindings. return; diff --git a/src/librustc_infer/traits/fulfill.rs b/src/librustc_infer/traits/fulfill.rs index 28d3f269180..ac9ff484a02 100644 --- a/src/librustc_infer/traits/fulfill.rs +++ b/src/librustc_infer/traits/fulfill.rs @@ -299,7 +299,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { let obligation = &mut pending_obligation.obligation; - if obligation.predicate.has_infer_types() { + if obligation.predicate.has_infer_types_or_consts() { obligation.predicate = self.selcx.infcx().resolve_vars_if_possible(&obligation.predicate); } @@ -346,16 +346,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> { // This is a bit subtle: for the most part, the // only reason we can fail to make progress on // trait selection is because we don't have enough - // information about the types in the trait. One - // exception is that we sometimes haven't decided - // what kind of closure a closure is. *But*, in - // that case, it turns out, the type of the - // closure will also change, because the closure - // also includes references to its upvars as part - // of its type, and those types are resolved at - // the same time. - // - // FIXME(#32286) logic seems false if no upvars + // information about the types in the trait. pending_obligation.stalled_on = trait_ref_type_vars(self.selcx, data.to_poly_trait_ref()); diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index fcaab093ee2..2815a77882a 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -213,7 +213,7 @@ pub fn type_known_to_meet_bound_modulo_regions<'a, 'tcx>( result ); - if result && (ty.has_infer_types() || ty.has_closure_types()) { + if result && ty.has_infer_types_or_consts() { // Because of inference "guessing", selection can sometimes claim // to succeed while the success requires a guess. To ensure // this function's result remains infallible, we must confirm diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index cbe24320502..34889c6984b 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -490,22 +490,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( match cache_result { Ok(()) => {} Err(ProjectionCacheEntry::Ambiguous) => { - // If we found ambiguity the last time, that generally - // means we will continue to do so until some type in the - // key changes (and we know it hasn't, because we just - // fully resolved it). One exception though is closure - // types, which can transition from having a fixed kind to - // no kind with no visible change in the key. - // - // FIXME(#32286) refactor this so that closure type - // changes + // If we found ambiguity the last time, that means we will continue + // to do so until some type in the key changes (and we know it + // hasn't, because we just fully resolved it). debug!( "opt_normalize_projection_type: \ found cache entry: ambiguous" ); - if !projection_ty.has_closure_types() { - return None; - } + return None; } Err(ProjectionCacheEntry::InProgress) => { // If while normalized A::B, we are asked to normalize diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 69424e3fac7..1b6b8735651 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -84,7 +84,7 @@ fn compute_implied_outlives_bounds<'tcx>( // to avoids duplicate errors that otherwise show up. fulfill_cx.register_predicate_obligations( infcx, - obligations.iter().filter(|o| o.predicate.has_infer_types()).cloned(), + obligations.iter().filter(|o| o.predicate.has_infer_types_or_consts()).cloned(), ); // From the full set of obligations, just filter down to the diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 4c214bd15e8..b7353c6af26 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2900,14 +2900,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { debug!("resolve_vars_with_obligations(ty={:?})", ty); // No Infer()? Nothing needs doing. - if !ty.has_infer_types() && !ty.has_infer_consts() { + if !ty.has_infer_types_or_consts() { debug!("resolve_vars_with_obligations: ty={:?}", ty); return ty; } // If `ty` is a type variable, see whether we already know what it is. ty = self.resolve_vars_if_possible(&ty); - if !ty.has_infer_types() && !ty.has_infer_consts() { + if !ty.has_infer_types_or_consts() { debug!("resolve_vars_with_obligations: ty={:?}", ty); return ty; } diff --git a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr index 4869f483634..b39a160b529 100644 --- a/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/into-iter-no-impls-length-33.stderr @@ -1,8 +1,8 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:12:5 + --> $DIR/into-iter-no-impls-length-33.rs:12:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -19,10 +19,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:18:5 + --> $DIR/into-iter-no-impls-length-33.rs:18:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -39,10 +39,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:24:5 + --> $DIR/into-iter-no-impls-length-33.rs:24:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -59,10 +59,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:30:5 + --> $DIR/into-iter-no-impls-length-33.rs:30:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -79,10 +79,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:36:5 + --> $DIR/into-iter-no-impls-length-33.rs:36:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -99,10 +99,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:42:5 + --> $DIR/into-iter-no-impls-length-33.rs:42:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` @@ -119,10 +119,10 @@ LL | IntoIter::new([0i32; 33]) = note: the return type of a function must have a statically known size error[E0277]: arrays only have std trait implementations for lengths 0..=32 - --> $DIR/into-iter-no-impls-length-33.rs:48:5 + --> $DIR/into-iter-no-impls-length-33.rs:48:19 | LL | IntoIter::new([0i32; 33]) - | ^^^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` + | ^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[i32; 33]` | = note: required by `std::array::IntoIter::::new` From 1617ec4ad2b12b34b22e2d78bb96a27448fce04c Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 22 Feb 2020 15:09:17 +0000 Subject: [PATCH 0664/1250] Clean up TypeFlags * Reorder flags to group similar ones together * Make some flags more granular * Compute `HAS_FREE_LOCAL_NAMES` from the other flags * Remove `HAS_TY_CLOSURE` * Add some more doc comments --- src/librustc/ty/flags.rs | 23 ++---- src/librustc/ty/fold.rs | 6 +- src/librustc/ty/mod.rs | 150 +++++++++++++++++++++++---------------- src/librustc/ty/sty.rs | 7 +- 4 files changed, 99 insertions(+), 87 deletions(-) diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 4546eadc6e6..5243e1fbf57 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -80,13 +80,10 @@ impl FlagComputation { &ty::Error => self.add_flags(TypeFlags::HAS_TY_ERR), &ty::Param(_) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_flags(TypeFlags::HAS_PARAMS); + self.add_flags(TypeFlags::HAS_TY_PARAM); } &ty::Generator(_, ref substs, _) => { - self.add_flags(TypeFlags::HAS_TY_CLOSURE); - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_substs(substs); } @@ -97,8 +94,6 @@ impl FlagComputation { } &ty::Closure(_, ref substs) => { - self.add_flags(TypeFlags::HAS_TY_CLOSURE); - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_substs(substs); } @@ -107,12 +102,10 @@ impl FlagComputation { } &ty::Placeholder(..) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); } &ty::Infer(infer) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right? self.add_flags(TypeFlags::HAS_TY_INFER); match infer { ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {} @@ -128,17 +121,17 @@ impl FlagComputation { } &ty::Projection(ref data) => { - self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); } &ty::UnnormalizedProjection(ref data) => { - self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_TY_PROJECTION); self.add_projection_ty(data); } &ty::Opaque(_, substs) => { - self.add_flags(TypeFlags::HAS_PROJECTION | TypeFlags::HAS_TY_OPAQUE); + self.add_flags(TypeFlags::HAS_TY_OPAQUE); self.add_substs(substs); } @@ -221,10 +214,10 @@ impl FlagComputation { match c.val { ty::ConstKind::Unevaluated(_, substs, _) => { self.add_substs(substs); - self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_flags(TypeFlags::HAS_CT_PROJECTION); } ty::ConstKind::Infer(infer) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES | TypeFlags::HAS_CT_INFER); + self.add_flags(TypeFlags::HAS_CT_INFER); match infer { InferConst::Fresh(_) => {} InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), @@ -232,11 +225,9 @@ impl FlagComputation { } ty::ConstKind::Bound(debruijn, _) => self.add_binder(debruijn), ty::ConstKind::Param(_) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); - self.add_flags(TypeFlags::HAS_PARAMS); + self.add_flags(TypeFlags::HAS_CT_PARAM); } ty::ConstKind::Placeholder(_) => { - self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); } ty::ConstKind::Value(_) => {} diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index b88001f8783..4adca6c7d97 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -85,7 +85,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_TY_ERR) } fn has_param_types(&self) -> bool { - self.has_type_flags(TypeFlags::HAS_PARAMS) + self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM) } fn has_infer_types(&self) -> bool { self.has_type_flags(TypeFlags::HAS_TY_INFER) @@ -100,9 +100,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::KEEP_IN_LOCAL_TCX) } fn needs_infer(&self) -> bool { - self.has_type_flags( - TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER | TypeFlags::HAS_CT_INFER, - ) + self.has_type_flags(TypeFlags::NEEDS_INFER) } fn has_placeholders(&self) -> bool { self.has_type_flags( diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c9e58b6c771..b25fd3c61fd 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -515,79 +515,107 @@ pub struct CReaderCacheKey { pub pos: usize, } -// Flags that we track on types. These flags are propagated upwards -// through the type during type construction, so that we can quickly -// check whether the type has various kinds of types in it without -// recursing over the type itself. bitflags! { + /// Flags that we track on types. These flags are propagated upwards + /// through the type during type construction, so that we can quickly check + /// whether the type has various kinds of types in it without recursing + /// over the type itself. pub struct TypeFlags: u32 { - const HAS_PARAMS = 1 << 0; - 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 << 4; - - /// Does this have any region that "appears free" in the type? - /// Basically anything but `ReLateBound` and `ReErased`. - const HAS_FREE_REGIONS = 1 << 5; - - /// Is an error type reachable? - 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 << 8; + // Does this have parameters? Used to determine whether substitution is + // required. + /// Does this have [Param]? + const HAS_TY_PARAM = 1 << 0; + /// Does this have [ReEarlyBound]? + const HAS_RE_PARAM = 1 << 1; + /// Does this have [ConstKind::Param]? + const HAS_CT_PARAM = 1 << 2; + + const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_RE_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits; + + /// Does this have [Infer]? + const HAS_TY_INFER = 1 << 3; + /// Does this have [ReVar]? + const HAS_RE_INFER = 1 << 4; + /// Does this have [ConstKind::Infer]? + const HAS_CT_INFER = 1 << 5; + + /// Does this have inference variables? Used to determine whether + /// inference is required. + const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits; + + /// Does this have [Placeholder]? + const HAS_TY_PLACEHOLDER = 1 << 6; + /// Does this have [RePlaceholder]? + const HAS_RE_PLACEHOLDER = 1 << 7; + /// Does this have [ConstKind::Placeholder]? + const HAS_CT_PLACEHOLDER = 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 << 9; + const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_RE_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits + | TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits + | TypeFlags::HAS_TY_PLACEHOLDER.bits + | TypeFlags::HAS_RE_PLACEHOLDER.bits + | TypeFlags::HAS_CT_PLACEHOLDER.bits; + + /// Does this have [Projection] or [UnnormalizedProjection]? + const HAS_TY_PROJECTION = 1 << 9; + /// Does this have [Opaque]? + const HAS_TY_OPAQUE = 1 << 10; + /// Does this have [ConstKind::Unevaluated]? + const HAS_CT_PROJECTION = 1 << 11; + + /// Could this type be normalized further? + const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits + | TypeFlags::HAS_TY_OPAQUE.bits + | TypeFlags::HAS_CT_PROJECTION.bits; /// Present if the type belongs in a local type context. - /// Only set for Infer other than Fresh. - 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 << 11; + /// Set for placeholders and inference variables that are not "Fresh". + const KEEP_IN_LOCAL_TCX = 1 << 12; - /// Does this have any `ReErased` regions? - const HAS_RE_ERASED = 1 << 12; + /// Is an error type reachable? + const HAS_TY_ERR = 1 << 13; - const HAS_TY_PLACEHOLDER = 1 << 13; + /// Does this have any region that "appears free" in the type? + /// Basically anything but [ReLateBound] and [ReErased]. + const HAS_FREE_REGIONS = 1 << 14; - const HAS_CT_INFER = 1 << 14; - const HAS_CT_PLACEHOLDER = 1 << 15; - /// Does this have any [Opaque] types. - const HAS_TY_OPAQUE = 1 << 16; + /// Does this have any [ReLateBound] regions? Used to check + /// if a global bound is safe to evaluate. + const HAS_RE_LATE_BOUND = 1 << 15; - const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | - TypeFlags::HAS_RE_EARLY_BOUND.bits; + /// Does this have any [ReErased] regions? + const HAS_RE_ERASED = 1 << 16; /// 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_TY_INFER.bits | - TypeFlags::HAS_RE_INFER.bits | - TypeFlags::HAS_RE_PLACEHOLDER.bits | - TypeFlags::HAS_RE_EARLY_BOUND.bits | - TypeFlags::HAS_FREE_REGIONS.bits | - TypeFlags::HAS_TY_ERR.bits | - TypeFlags::HAS_PROJECTION.bits | - TypeFlags::HAS_TY_CLOSURE.bits | - TypeFlags::HAS_FREE_LOCAL_NAMES.bits | - TypeFlags::KEEP_IN_LOCAL_TCX.bits | - TypeFlags::HAS_RE_LATE_BOUND.bits | - TypeFlags::HAS_RE_ERASED.bits | - TypeFlags::HAS_TY_PLACEHOLDER.bits | - TypeFlags::HAS_CT_INFER.bits | - TypeFlags::HAS_CT_PLACEHOLDER.bits | - TypeFlags::HAS_TY_OPAQUE.bits; + const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_RE_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits + | TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits + | TypeFlags::HAS_TY_PLACEHOLDER.bits + | TypeFlags::HAS_RE_PLACEHOLDER.bits + | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_TY_PROJECTION.bits + | TypeFlags::HAS_TY_OPAQUE.bits + | TypeFlags::HAS_CT_PROJECTION.bits + | TypeFlags::KEEP_IN_LOCAL_TCX.bits + | TypeFlags::HAS_TY_ERR.bits + | TypeFlags::HAS_FREE_REGIONS.bits + | TypeFlags::HAS_RE_LATE_BOUND.bits + | TypeFlags::HAS_RE_ERASED.bits; } } @@ -1816,10 +1844,10 @@ impl<'tcx> ParamEnv<'tcx> { Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, Reveal::All => { - if value.has_placeholders() || value.needs_infer() || value.has_param_types() { - ParamEnvAnd { param_env: self, value } - } else { + if value.is_global() { ParamEnvAnd { param_env: self.without_caller_bounds(), value } + } else { + ParamEnvAnd { param_env: self, value } } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index fcf23b9023b..9f60c9cdbcc 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1768,7 +1768,7 @@ impl RegionKind { } ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; - flags = flags | TypeFlags::HAS_RE_EARLY_BOUND; + flags = flags | TypeFlags::HAS_RE_PARAM; } ty::ReEmpty(_) | ty::ReStatic | ty::ReFree { .. } | ty::ReScope { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; @@ -1781,11 +1781,6 @@ impl RegionKind { } } - match *self { - ty::ReStatic | ty::ReEmpty(_) | ty::ReErased | ty::ReLateBound(..) => (), - _ => flags = flags | TypeFlags::HAS_FREE_LOCAL_NAMES, - } - debug!("type_flags({:?}) = {:?}", self, flags); flags From 176fe3f8ac79e58e35793e6a92c75eed3c8e5b91 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 27 Feb 2020 04:10:42 +0100 Subject: [PATCH 0665/1250] encode `;` stmt w/o expr as `StmtKind::Empty` --- src/librustc_ast/ast.rs | 2 + src/librustc_ast/attr/mod.rs | 7 +- src/librustc_ast/mut_visit.rs | 1 + src/librustc_ast/visit.rs | 5 +- src/librustc_ast_lowering/lib.rs | 1 + src/librustc_ast_pretty/pprust.rs | 20 ++---- src/librustc_lint/builtin.rs | 5 +- src/librustc_lint/lib.rs | 6 +- src/librustc_lint/redundant_semicolon.rs | 65 ++++++++----------- src/librustc_parse/parser/stmt.rs | 27 ++------ src/test/ui/block-expr-precedence.stderr | 2 +- src/test/ui/consts/const_let_eq.rs | 1 + src/test/ui/consts/const_let_eq_float.rs | 1 + .../redundant-semi-proc-macro.rs | 2 +- .../redundant-semi-proc-macro.stderr | 6 +- src/test/ui/parser/attr-dangling-in-fn.stderr | 6 +- .../ui/parser/attr-stmt-expr-attr-bad.stderr | 8 +-- src/test/ui/parser/doc-before-semi.rs | 2 - src/test/ui/parser/doc-before-semi.stderr | 8 --- 19 files changed, 73 insertions(+), 102 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 62ff4f5183a..88564647d61 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -913,6 +913,8 @@ pub enum StmtKind { Expr(P), /// Expr with a trailing semi-colon. Semi(P), + /// Just a trailing semi-colon. + Empty, /// Macro. Mac(P<(Mac, MacStmtStyle, AttrVec)>), } diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index bc5c86b02b3..53515cee281 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -674,8 +674,8 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match *self { StmtKind::Local(ref local) => local.attrs(), - StmtKind::Item(..) => &[], StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.attrs(), + StmtKind::Empty | StmtKind::Item(..) => &[], StmtKind::Mac(ref mac) => { let (_, _, ref attrs) = **mac; attrs.attrs() @@ -686,9 +686,8 @@ impl HasAttrs for StmtKind { fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec)) { match self { StmtKind::Local(local) => local.visit_attrs(f), - StmtKind::Item(..) => {} - StmtKind::Expr(expr) => expr.visit_attrs(f), - StmtKind::Semi(expr) => expr.visit_attrs(f), + StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), + StmtKind::Empty | StmtKind::Item(..) => {} StmtKind::Mac(mac) => { let (_mac, _style, attrs) = mac.deref_mut(); attrs.visit_attrs(f); diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs index b3abd4fc755..a9b06f602f6 100644 --- a/src/librustc_ast/mut_visit.rs +++ b/src/librustc_ast/mut_visit.rs @@ -1265,6 +1265,7 @@ pub fn noop_flat_map_stmt_kind( StmtKind::Item(item) => vis.flat_map_item(item).into_iter().map(StmtKind::Item).collect(), StmtKind::Expr(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Expr).collect(), StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(), + StmtKind::Empty => smallvec![StmtKind::Empty], StmtKind::Mac(mut mac) => { let (mac_, _semi, attrs) = mac.deref_mut(); vis.visit_mac(mac_); diff --git a/src/librustc_ast/visit.rs b/src/librustc_ast/visit.rs index 96149ad7947..c92a4db6dee 100644 --- a/src/librustc_ast/visit.rs +++ b/src/librustc_ast/visit.rs @@ -669,9 +669,8 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) { match statement.kind { StmtKind::Local(ref local) => visitor.visit_local(local), StmtKind::Item(ref item) => visitor.visit_item(item), - StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { - visitor.visit_expr(expression) - } + StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr), + StmtKind::Empty => {} StmtKind::Mac(ref mac) => { let (ref mac, _, ref attrs) = **mac; visitor.visit_mac(mac); diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 0f7ed9f72f8..df71b05ac2c 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -2281,6 +2281,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } StmtKind::Expr(ref e) => hir::StmtKind::Expr(self.lower_expr(e)), StmtKind::Semi(ref e) => hir::StmtKind::Semi(self.lower_expr(e)), + StmtKind::Empty => return smallvec![], StmtKind::Mac(..) => panic!("shouldn't exist here"), }; smallvec![hir::Stmt { hir_id: self.lower_node_id(s.id), kind, span: s.span }] diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index ea8535eabef..f95c154bb3b 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1446,19 +1446,13 @@ impl<'a> State<'a> { } } ast::StmtKind::Semi(ref expr) => { - match expr.kind { - // Filter out empty `Tup` exprs created for the `redundant_semicolon` - // lint, as they shouldn't be visible and interact poorly - // with proc macros. - ast::ExprKind::Tup(ref exprs) if exprs.is_empty() && expr.attrs.is_empty() => { - () - } - _ => { - self.space_if_not_bol(); - self.print_expr_outer_attr_style(expr, false); - self.s.word(";"); - } - } + self.space_if_not_bol(); + self.print_expr_outer_attr_style(expr, false); + self.s.word(";"); + } + ast::StmtKind::Empty => { + self.space_if_not_bol(); + self.s.word(";"); } ast::StmtKind::Mac(ref mac) => { let (ref mac, style, ref attrs) = **mac; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3eecd2a54e3..e1680015bea 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -775,7 +775,10 @@ impl EarlyLintPass for UnusedDocComment { ast::StmtKind::Local(..) => "statements", ast::StmtKind::Item(..) => "inner items", // expressions will be reported by `check_expr`. - ast::StmtKind::Semi(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Mac(..) => return, + ast::StmtKind::Empty + | ast::StmtKind::Semi(_) + | ast::StmtKind::Expr(_) + | ast::StmtKind::Mac(_) => return, }; warn_if_doc(cx, stmt.span, kind, stmt.kind.attrs()); diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 895c42a84d8..825ac04bc09 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -113,7 +113,7 @@ macro_rules! early_lint_passes { WhileTrue: WhileTrue, NonAsciiIdents: NonAsciiIdents, IncompleteFeatures: IncompleteFeatures, - RedundantSemicolon: RedundantSemicolon, + RedundantSemicolons: RedundantSemicolons, UnusedDocComment: UnusedDocComment, ] ); @@ -274,7 +274,8 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { UNUSED_EXTERN_CRATES, UNUSED_FEATURES, UNUSED_LABELS, - UNUSED_PARENS + UNUSED_PARENS, + REDUNDANT_SEMICOLONS ); add_lint_group!( @@ -307,6 +308,7 @@ fn register_builtins(store: &mut LintStore, no_interleave_lints: bool) { store.register_renamed("unused_doc_comment", "unused_doc_comments"); store.register_renamed("async_idents", "keyword_idents"); store.register_renamed("exceeding_bitshifts", "arithmetic_overflow"); + store.register_renamed("redundant_semicolon", "redundant_semicolons"); store.register_removed("unknown_features", "replaced by an error"); store.register_removed("unsigned_negation", "replaced by negate_unsigned feature gate"); store.register_removed("negate_unsigned", "cast a signed value instead"); diff --git a/src/librustc_lint/redundant_semicolon.rs b/src/librustc_lint/redundant_semicolon.rs index 0b66fd92430..0f807cd497e 100644 --- a/src/librustc_lint/redundant_semicolon.rs +++ b/src/librustc_lint/redundant_semicolon.rs @@ -1,50 +1,41 @@ use crate::{EarlyContext, EarlyLintPass, LintContext}; -use rustc_ast::ast::{ExprKind, Stmt, StmtKind}; +use rustc_ast::ast::{Block, StmtKind}; use rustc_errors::Applicability; +use rustc_span::Span; declare_lint! { - pub REDUNDANT_SEMICOLON, + pub REDUNDANT_SEMICOLONS, Warn, "detects unnecessary trailing semicolons" } -declare_lint_pass!(RedundantSemicolon => [REDUNDANT_SEMICOLON]); +declare_lint_pass!(RedundantSemicolons => [REDUNDANT_SEMICOLONS]); -impl EarlyLintPass for RedundantSemicolon { - fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &Stmt) { - if let StmtKind::Semi(expr) = &stmt.kind { - if let ExprKind::Tup(ref v) = &expr.kind { - 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" - }; - cx.struct_span_lint(REDUNDANT_SEMICOLON, stmt.span, |lint| { - let mut err = lint.build(&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(); - }); - } - } - } +impl EarlyLintPass for RedundantSemicolons { + fn check_block(&mut self, cx: &EarlyContext<'_>, block: &Block) { + let mut seq = None; + for stmt in block.stmts.iter() { + match (&stmt.kind, &mut seq) { + (StmtKind::Empty, None) => seq = Some((stmt.span, false)), + (StmtKind::Empty, Some(seq)) => *seq = (seq.0.to(stmt.span), true), + (_, seq) => maybe_lint_redundant_semis(cx, seq), } } + maybe_lint_redundant_semis(cx, &mut seq); + } +} + +fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, bool)>) { + if let Some((span, multiple)) = seq.take() { + cx.struct_span_lint(REDUNDANT_SEMICOLONS, span, |lint| { + let (msg, rem) = if multiple { + ("unnecessary trailing semicolons", "remove these semicolons") + } else { + ("unnecessary trailing semicolon", "remove this semicolon") + }; + lint.build(msg) + .span_suggestion(span, rem, String::new(), Applicability::MaybeIncorrect) + .emit(); + }); } } diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index e38a7f2f1c2..3864ec3aaa1 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -59,23 +59,10 @@ impl<'a> Parser<'a> { } else if let Some(item) = self.parse_stmt_item(attrs.clone())? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) - } else if self.token == token::Semi { + } else if self.eat(&token::Semi) { // Do not attempt to parse an expression if we're done here. self.error_outer_attrs(&attrs); - self.bump(); - 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. - let kind = StmtKind::Semi(self.mk_expr( - lo.to(last_semi), - ExprKind::Tup(Vec::new()), - AttrVec::new(), - )); - self.mk_stmt(lo.to(last_semi), kind) + self.mk_stmt(lo, StmtKind::Empty) } else if self.token != token::CloseDelim(token::Brace) { // Remainder are line-expr stmts. let e = self.parse_expr_res(Restrictions::STMT_EXPR, Some(attrs.into()))?; @@ -144,12 +131,11 @@ impl<'a> Parser<'a> { /// Error on outer attributes in this context. /// Also error if the previous token was a doc comment. fn error_outer_attrs(&self, attrs: &[Attribute]) { - if !attrs.is_empty() { - if matches!(self.prev_token.kind, TokenKind::DocComment(..)) { - self.span_fatal_err(self.prev_token.span, Error::UselessDocComment).emit(); + if let [.., last] = attrs { + if last.is_doc_comment() { + self.span_fatal_err(last.span, Error::UselessDocComment).emit(); } else if attrs.iter().any(|a| a.style == AttrStyle::Outer) { - self.struct_span_err(self.token.span, "expected statement after outer attribute") - .emit(); + self.struct_span_err(last.span, "expected statement after outer attribute").emit(); } } } @@ -401,6 +387,7 @@ impl<'a> Parser<'a> { self.expect_semi()?; eat_semi = false; } + StmtKind::Empty => eat_semi = false, _ => {} } diff --git a/src/test/ui/block-expr-precedence.stderr b/src/test/ui/block-expr-precedence.stderr index 1307b5d6ddd..decee1f2f16 100644 --- a/src/test/ui/block-expr-precedence.stderr +++ b/src/test/ui/block-expr-precedence.stderr @@ -4,5 +4,5 @@ warning: unnecessary trailing semicolons LL | if (true) { 12; };;; -num; | ^^ help: remove these semicolons | - = note: `#[warn(redundant_semicolon)]` on by default + = note: `#[warn(redundant_semicolons)]` on by default diff --git a/src/test/ui/consts/const_let_eq.rs b/src/test/ui/consts/const_let_eq.rs index a2364c392f2..818819f9ff6 100644 --- a/src/test/ui/consts/const_let_eq.rs +++ b/src/test/ui/consts/const_let_eq.rs @@ -5,6 +5,7 @@ struct Bar { x: T } struct W(u32); struct A { a: u32 } +#[allow(redundant_semicolons)] const fn basics((a,): (u32,)) -> u32 { // Deferred assignment: let b: u32; diff --git a/src/test/ui/consts/const_let_eq_float.rs b/src/test/ui/consts/const_let_eq_float.rs index 0c927a0484d..bc0ef26eb2f 100644 --- a/src/test/ui/consts/const_let_eq_float.rs +++ b/src/test/ui/consts/const_let_eq_float.rs @@ -7,6 +7,7 @@ struct Bar { x: T } struct W(f32); struct A { a: f32 } +#[allow(redundant_semicolons)] const fn basics((a,): (f32,)) -> f32 { // Deferred assignment: let b: f32; diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs index f207b235735..08a5c6c2b63 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.rs @@ -1,6 +1,6 @@ // aux-build:redundant-semi-proc-macro-def.rs -#![deny(redundant_semicolon)] +#![deny(redundant_semicolons)] extern crate redundant_semi_proc_macro; use redundant_semi_proc_macro::should_preserve_spans; diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index 8c5ee58dc12..a79fba9bf3f 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(197..199) }, Ident { ident: "span_preservation", span: #0 bytes(200..217) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(217..219) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(227..230) }, Ident { ident: "tst", span: #0 bytes(231..234) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(235..236) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(237), hi: BytePos(240), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(240..241) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(241..242) }, Ident { ident: "match", span: #0 bytes(288..293) }, Ident { ident: "tst", span: #0 bytes(294..297) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(482), hi: BytePos(485), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(486..488) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(486..488) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(489..491) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(491..492) }, Ident { ident: "_", span: #0 bytes(501..502) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(503..505) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(503..505) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(506..508) }], span: #0 bytes(298..514) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(514..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(516..517) }], span: #0 bytes(221..561) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(238), hi: BytePos(241), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(483), hi: BytePos(486), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | @@ -8,8 +8,8 @@ LL | let tst = 123;; note: the lint level is defined here --> $DIR/redundant-semi-proc-macro.rs:3:9 | -LL | #![deny(redundant_semicolon)] - | ^^^^^^^^^^^^^^^^^^^ +LL | #![deny(redundant_semicolons)] + | ^^^^^^^^^^^^^^^^^^^^ error: unnecessary trailing semicolons --> $DIR/redundant-semi-proc-macro.rs:16:7 diff --git a/src/test/ui/parser/attr-dangling-in-fn.stderr b/src/test/ui/parser/attr-dangling-in-fn.stderr index 71488d2e5c3..b1bb3ab3b17 100644 --- a/src/test/ui/parser/attr-dangling-in-fn.stderr +++ b/src/test/ui/parser/attr-dangling-in-fn.stderr @@ -1,8 +1,8 @@ error: expected statement after outer attribute - --> $DIR/attr-dangling-in-fn.rs:5:1 + --> $DIR/attr-dangling-in-fn.rs:4:3 | -LL | } - | ^ +LL | #[foo = "bar"] + | ^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index 4775b9b7bc0..b03db85422d 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -411,16 +411,16 @@ LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } | ^ expected one of `.`, `;`, `?`, or an operator error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:114:44 + --> $DIR/attr-stmt-expr-attr-bad.rs:114:37 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } - | ^ + | ^^^^^^^ error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:116:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:116:37 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } - | ^ + | ^^^^^^^ error: aborting due to 57 previous errors diff --git a/src/test/ui/parser/doc-before-semi.rs b/src/test/ui/parser/doc-before-semi.rs index c3f478fe420..405a7e1e2a3 100644 --- a/src/test/ui/parser/doc-before-semi.rs +++ b/src/test/ui/parser/doc-before-semi.rs @@ -3,6 +3,4 @@ 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 b9ac30b09b2..e6bade18d0a 100644 --- a/src/test/ui/parser/doc-before-semi.stderr +++ b/src/test/ui/parser/doc-before-semi.stderr @@ -6,14 +6,6 @@ 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`. From 6bfa48a0aefc5f292d5c13c250e25813ba215e96 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 1 Mar 2020 23:56:03 +0100 Subject: [PATCH 0666/1250] Rename `syntax` in librustc_ast/README.md --- src/librustc_ast/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_ast/README.md b/src/librustc_ast/README.md index daa252ef455..d62e5a5ece0 100644 --- a/src/librustc_ast/README.md +++ b/src/librustc_ast/README.md @@ -1,4 +1,4 @@ -The `syntax` crate contains those things concerned purely with syntax +The `rustc_ast` crate contains those things concerned purely with syntax – that is, the AST ("abstract syntax tree"), parser, pretty-printer, lexer, macro expander, and utilities for traversing ASTs. From df20036848b7e3607b988cdee18c861964423f65 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 2 Mar 2020 00:07:23 +0100 Subject: [PATCH 0667/1250] stash API: remove panic to fix ICE. --- src/librustc_errors/lib.rs | 18 ++----- .../issue-69396-const-no-type-in-macro.rs | 17 ++++++ .../issue-69396-const-no-type-in-macro.stderr | 53 +++++++++++++++++++ 3 files changed, 74 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/issues/issue-69396-const-no-type-in-macro.rs create mode 100644 src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 1a0fe343521..161b2c717e7 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -444,22 +444,12 @@ impl Handler { } /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing. - /// If the diagnostic with this `(span, key)` already exists, this will result in an ICE. pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) { let mut inner = self.inner.borrow_mut(); - if let Some(mut old_diag) = inner.stashed_diagnostics.insert((span, key), diag) { - // We are removing a previously stashed diagnostic which should not happen. - old_diag.level = Bug; - old_diag.note(&format!( - "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})", - file!(), - line!(), - span, - key - )); - inner.emit_diag_at_span(old_diag, span); - panic!(ExplicitBug); - } + // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic + // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key. + // See the PR for a discussion. + inner.stashed_diagnostics.insert((span, key), diag); } /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key. diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs new file mode 100644 index 00000000000..69fc0c1cbb9 --- /dev/null +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.rs @@ -0,0 +1,17 @@ +macro_rules! suite { + ( $( $fn:ident; )* ) => { + $( + const A = "A".$fn(); + //~^ ERROR the name `A` is defined multiple times + //~| ERROR missing type for `const` item + //~| ERROR the type placeholder `_` is not allowed within types + )* + } +} + +suite! { + len; + is_empty; +} + +fn main() {} diff --git a/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr new file mode 100644 index 00000000000..1af5368d2b6 --- /dev/null +++ b/src/test/ui/issues/issue-69396-const-no-type-in-macro.stderr @@ -0,0 +1,53 @@ +error[E0428]: the name `A` is defined multiple times + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:13 + | +LL | const A = "A".$fn(); + | ^^^^^^^^^^^^^^^^^^^^ + | | + | `A` redefined here + | previous definition of the value `A` here +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: `A` must be defined only once in the value namespace of this module + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: missing type for `const` item + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 + | +LL | const A = "A".$fn(); + | ^ help: provide a type for the item: `A: usize` +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/issue-69396-const-no-type-in-macro.rs:4:19 + | +LL | const A = "A".$fn(); + | ^ + | | + | not allowed in type signatures + | help: replace `_` with the correct type: `bool` +... +LL | / suite! { +LL | | len; +LL | | is_empty; +LL | | } + | |_- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0121, E0428. +For more information about an error, try `rustc --explain E0121`. From 22d840e501d52310dfc1ef95792ed211e3673e62 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 1 Mar 2020 15:46:38 -0800 Subject: [PATCH 0668/1250] Toolstate: Don't block beta week on already broken tools. --- src/bootstrap/toolstate.rs | 196 +++++++++++++++++++++++++------------ 1 file changed, 133 insertions(+), 63 deletions(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index bb012a38855..5c39f5d5bc3 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -6,7 +6,7 @@ use std::env; use std::fmt; use std::fs; use std::io::{Seek, SeekFrom}; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use std::process::Command; use std::time; @@ -24,7 +24,7 @@ const OS: Option<&str> = None; type ToolstateData = HashMap, ToolState>; -#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, Deserialize, Serialize, PartialEq, Eq, PartialOrd)] #[serde(rename_all = "kebab-case")] /// Whether a tool can be compiled, tested or neither pub enum ToolState { @@ -143,10 +143,31 @@ pub struct ToolStateCheck; impl Step for ToolStateCheck { type Output = (); - /// Runs the `linkchecker` tool as compiled in `stage` by the `host` compiler. + /// Checks tool state status. /// - /// This tool in `src/tools` will verify the validity of all our links in the - /// documentation to ensure we don't have a bunch of dead ones. + /// This is intended to be used in the `checktools.sh` script. To use + /// this, set `save-toolstates` in `config.toml` so that tool status will + /// be saved to a JSON file. Then, run `x.py test --no-fail-fast` for all + /// of the tools to populate the JSON file. After that is done, this + /// command can be run to check for any status failures, and exits with an + /// error if there are any. + /// + /// This also handles publishing the results to the `history` directory of + /// the toolstate repo https://github.com/rust-lang-nursery/rust-toolstate + /// if the env var `TOOLSTATE_PUBLISH` is set. Note that there is a + /// *separate* step of updating the `latest.json` file and creating GitHub + /// issues and comments in `src/ci/publish_toolstate.sh`, which is only + /// performed on master. (The shell/python code is intended to be migrated + /// here eventually.) + /// + /// The rules for failure are: + /// * If the PR modifies a tool, the status must be test-pass. + /// NOTE: There is intent to change this, see + /// https://github.com/rust-lang/rust/issues/65000. + /// * All "stable" tools must be test-pass on the stable or beta branches. + /// * During beta promotion week, a PR is not allowed to "regress" a + /// stable tool. That is, the status is not allowed to get worse + /// (test-pass to test-fail or build-fail). fn run(self, builder: &Builder<'_>) { if builder.config.dry_run { return; @@ -171,6 +192,8 @@ impl Step for ToolStateCheck { } check_changed_files(&toolstates); + checkout_toolstate_repo(); + let old_toolstate = read_old_toolstate(); for (tool, _) in STABLE_TOOLS.iter() { let state = toolstates[*tool]; @@ -180,11 +203,24 @@ impl Step for ToolStateCheck { did_error = true; eprintln!("error: Tool `{}` should be test-pass but is {}", tool, state); } else if in_beta_week { - did_error = true; - eprintln!( - "error: Tool `{}` should be test-pass but is {} during beta week.", - tool, state - ); + let old_state = old_toolstate + .iter() + .find(|ts| ts.tool == *tool) + .expect("latest.json missing tool") + .state(); + if state < old_state { + did_error = true; + eprintln!( + "error: Tool `{}` has regressed from {} to {} during beta week.", + tool, old_state, state + ); + } else { + eprintln!( + "warning: Tool `{}` is not test-pass (is `{}`), \ + this should be fixed before beta is branched.", + tool, state + ); + } } } } @@ -247,6 +283,70 @@ impl Builder<'_> { } } +fn toolstate_repo() -> String { + env::var("TOOLSTATE_REPO") + .unwrap_or_else(|_| "https://github.com/rust-lang-nursery/rust-toolstate.git".to_string()) +} + +/// Directory where the toolstate repo is checked out. +const TOOLSTATE_DIR: &str = "rust-toolstate"; + +/// Checks out the toolstate repo into `TOOLSTATE_DIR`. +fn checkout_toolstate_repo() { + if let Ok(token) = env::var("TOOLSTATE_REPO_ACCESS_TOKEN") { + prepare_toolstate_config(&token); + } + if Path::new(TOOLSTATE_DIR).exists() { + eprintln!("Cleaning old toolstate directory..."); + t!(fs::remove_dir_all(TOOLSTATE_DIR)); + } + + let status = Command::new("git") + .arg("clone") + .arg("--depth=1") + .arg(toolstate_repo()) + .arg(TOOLSTATE_DIR) + .status(); + let success = match status { + Ok(s) => s.success(), + Err(_) => false, + }; + if !success { + panic!("git clone unsuccessful (status: {:?})", status); + } +} + +/// Sets up config and authentication for modifying the toolstate repo. +fn prepare_toolstate_config(token: &str) { + fn git_config(key: &str, value: &str) { + let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status(); + let success = match status { + Ok(s) => s.success(), + Err(_) => false, + }; + if !success { + panic!("git config key={} value={} successful (status: {:?})", key, value, status); + } + } + + // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date + // as well. + git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com"); + git_config("user.name", "Rust Toolstate Update"); + git_config("credential.helper", "store"); + + let credential = format!("https://{}:x-oauth-basic@github.com\n", token,); + let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials"); + t!(fs::write(&git_credential_path, credential)); +} + +/// Reads the latest toolstate from the toolstate repo. +fn read_old_toolstate() -> Vec { + let latest_path = Path::new(TOOLSTATE_DIR).join("_data").join("latest.json"); + let old_toolstate = t!(fs::read(latest_path)); + t!(serde_json::from_slice(&old_toolstate)) +} + /// This function `commit_toolstate_change` provides functionality for pushing a change /// to the `rust-toolstate` repository. /// @@ -274,45 +374,7 @@ impl Builder<'_> { /// * See /// if a private email by GitHub is wanted. fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) { - fn git_config(key: &str, value: &str) { - let status = Command::new("git").arg("config").arg("--global").arg(key).arg(value).status(); - let success = match status { - Ok(s) => s.success(), - Err(_) => false, - }; - if !success { - panic!("git config key={} value={} successful (status: {:?})", key, value, status); - } - } - - // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date - // as well. - git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com"); - git_config("user.name", "Rust Toolstate Update"); - git_config("credential.helper", "store"); - - let credential = format!( - "https://{}:x-oauth-basic@github.com\n", - t!(env::var("TOOLSTATE_REPO_ACCESS_TOKEN")), - ); - let git_credential_path = PathBuf::from(t!(env::var("HOME"))).join(".git-credentials"); - t!(fs::write(&git_credential_path, credential)); - - let status = Command::new("git") - .arg("clone") - .arg("--depth=1") - .arg(t!(env::var("TOOLSTATE_REPO"))) - .status(); - let success = match status { - Ok(s) => s.success(), - Err(_) => false, - }; - if !success { - panic!("git clone successful (status: {:?})", status); - } - - let old_toolstate = t!(fs::read("rust-toolstate/_data/latest.json")); - let old_toolstate: Vec = t!(serde_json::from_slice(&old_toolstate)); + let old_toolstate = read_old_toolstate(); let message = format!("({} CI update)", OS.expect("linux/windows only")); let mut success = false; @@ -322,7 +384,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool // `git commit` failing means nothing to commit. let status = t!(Command::new("git") - .current_dir("rust-toolstate") + .current_dir(TOOLSTATE_DIR) .arg("commit") .arg("-a") .arg("-m") @@ -334,7 +396,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool } let status = t!(Command::new("git") - .current_dir("rust-toolstate") + .current_dir(TOOLSTATE_DIR) .arg("push") .arg("origin") .arg("master") @@ -347,14 +409,14 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool eprintln!("Sleeping for 3 seconds before retrying push"); std::thread::sleep(std::time::Duration::from_secs(3)); let status = t!(Command::new("git") - .current_dir("rust-toolstate") + .current_dir(TOOLSTATE_DIR) .arg("fetch") .arg("origin") .arg("master") .status()); assert!(status.success()); let status = t!(Command::new("git") - .current_dir("rust-toolstate") + .current_dir(TOOLSTATE_DIR) .arg("reset") .arg("--hard") .arg("origin/master") @@ -375,18 +437,12 @@ fn change_toolstate( let mut regressed = false; for repo_state in old_toolstate { let tool = &repo_state.tool; - let state = if cfg!(target_os = "linux") { - &repo_state.linux - } else if cfg!(windows) { - &repo_state.windows - } else { - unimplemented!() - }; + let state = repo_state.state(); let new_state = current_toolstate[tool.as_str()]; - if new_state != *state { + if new_state != state { eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state); - if (new_state as u8) < (*state as u8) { + if new_state < state { if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) { regressed = true; } @@ -403,7 +459,9 @@ fn change_toolstate( let toolstate_serialized = t!(serde_json::to_string(¤t_toolstate)); - let history_path = format!("rust-toolstate/history/{}.tsv", OS.expect("linux/windows only")); + let history_path = Path::new(TOOLSTATE_DIR) + .join("history") + .join(format!("{}.tsv", OS.expect("linux/windows only"))); let mut file = t!(fs::read_to_string(&history_path)); let end_of_first_line = file.find('\n').unwrap(); file.insert_str(end_of_first_line, &format!("\n{}\t{}", commit.trim(), toolstate_serialized)); @@ -418,3 +476,15 @@ struct RepoState { commit: String, datetime: String, } + +impl RepoState { + fn state(&self) -> ToolState { + if cfg!(target_os = "linux") { + self.linux + } else if cfg!(windows) { + self.windows + } else { + unimplemented!() + } + } +} From 85cbabba63e472a349fcee45c31fe19e956a1610 Mon Sep 17 00:00:00 2001 From: Steven Allen Date: Sun, 1 Mar 2020 14:56:42 -0800 Subject: [PATCH 0669/1250] Implement nth, last, and count for iter::Copied --- src/libcore/iter/adapters/mod.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 3b8edc2ad61..dcc1fb13bbc 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -173,6 +173,18 @@ impl<'a, I, T: 'a> Iterator for Copied { self.it.fold(init, copy_fold(f)) } + + fn nth(&mut self, n: usize) -> Option { + self.it.nth(n).copied() + } + + fn last(self) -> Option { + self.it.last().copied() + } + + fn count(self) -> usize { + self.it.count() + } } #[stable(feature = "iter_copied", since = "1.36.0")] From 99a595e406077375824a1316d4d669ad1f0a15f8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 2 Mar 2020 11:47:49 +1100 Subject: [PATCH 0670/1250] Fix a leak in `DiagnosticBuilder::into_diagnostic`. Fixes #69600. --- src/librustc_errors/diagnostic_builder.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 39f585231ee..008d2e92418 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -136,12 +136,11 @@ impl<'a> DiagnosticBuilder<'a> { let handler = self.0.handler; - // We need to use `ptr::read` because `DiagnosticBuilder` implements `Drop`. - let diagnostic; - unsafe { - diagnostic = std::ptr::read(&self.0.diagnostic); - std::mem::forget(self); - }; + // We must use `Level::Cancelled` for `dummy` to avoid an ICE about an + // unused diagnostic. + let dummy = Diagnostic::new(Level::Cancelled, ""); + let diagnostic = std::mem::replace(&mut self.0.diagnostic, dummy); + // Logging here is useful to help track down where in logs an error was // actually emitted. debug!("buffer: diagnostic={:?}", diagnostic); From cbf52b16758dd17fd60b5b73feb803d1ffc1654b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 10:13:11 +0100 Subject: [PATCH 0671/1250] remove non-sysroot sources from rust-src component --- src/bootstrap/dist.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 76478abd0de..8215211ea1c 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -1002,8 +1002,6 @@ impl Step for Src { "src/tools/rustc-std-workspace-core", "src/tools/rustc-std-workspace-alloc", "src/tools/rustc-std-workspace-std", - "src/librustc", - "src/librustc_ast", ]; copy_src_dirs(builder, &std_src_dirs[..], &[], &dst_src); From a30b0a61b86c9742449837a2f5b669a7974fef5e Mon Sep 17 00:00:00 2001 From: DutchGhost Date: Mon, 2 Mar 2020 11:00:20 +0100 Subject: [PATCH 0672/1250] actually mark the function const --- src/libcore/mem/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 4ffd0141242..1120d6d4bc5 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -111,7 +111,7 @@ pub use crate::intrinsics::transmute; #[inline] #[rustc_const_unstable(feature = "const_forget", issue = "69616")] #[stable(feature = "rust1", since = "1.0.0")] -pub fn forget(t: T) { +pub const fn forget(t: T) { ManuallyDrop::new(t); } From 4643b12f782fd4307a5ab1bc6809515cb053fbf1 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Mon, 2 Mar 2020 12:04:09 +0100 Subject: [PATCH 0673/1250] Update my mailmap entry --- .mailmap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index e5aad52ef4b..ea8ef0eebf9 100644 --- a/.mailmap +++ b/.mailmap @@ -5,7 +5,6 @@ # email addresses. # -Aaron Power Erin Power Aaron Todd Abhishek Chanda Abhishek Chanda Adolfo Ochagavía @@ -84,6 +83,8 @@ Eric Holk Eric Holmes Eric Reed Erick Tryzelaar +Erin Power +Erin Power Esteban Küber Esteban Küber Esteban Küber From d45ce5aed63fb58385705016dfaff1832a58d7c8 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 26 Dec 2019 10:02:21 -0500 Subject: [PATCH 0674/1250] Inline catching panics into std::catch_unwind This allows LLVM to inline the happy path, such that catching unwinding is zero-cost when no panic occurs. This also allows us to match the code generated by C++ try/catch. --- src/libpanic_abort/lib.rs | 13 ++----- src/libpanic_unwind/dummy.rs | 4 +- src/libpanic_unwind/emcc.rs | 4 +- src/libpanic_unwind/gcc.rs | 5 +-- src/libpanic_unwind/hermit.rs | 4 +- src/libpanic_unwind/lib.rs | 33 ++++------------- src/libpanic_unwind/seh.rs | 4 +- src/libstd/panicking.rs | 70 ++++++++++++++++++++++------------- 8 files changed, 60 insertions(+), 77 deletions(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index db7c250e211..ebc57860b9d 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -17,18 +17,11 @@ #![feature(panic_runtime)] #![feature(staged_api)] #![feature(rustc_attrs)] +#![feature(raw)] -// Rust's "try" function, but if we're aborting on panics we just call the -// function as there's nothing else we need to do here. #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - _data_ptr: *mut usize, - _vtable_ptr: *mut usize, -) -> u32 { - f(data); - 0 +pub unsafe extern "C" fn __rust_cleanup(_: *mut u8) -> core::raw::TraitObject { + unreachable!() } // "Leak" the payload and shim to the relevant abort on the platform in diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs index 86756326387..30593d3b88a 100644 --- a/src/libpanic_unwind/dummy.rs +++ b/src/libpanic_unwind/dummy.rs @@ -6,9 +6,7 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; -pub fn payload() -> *mut u8 { - core::ptr::null_mut() -} +pub type Payload = *mut u8; pub unsafe fn cleanup(_ptr: *mut u8) -> Box { intrinsics::abort() diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 9161d49959c..873135414bd 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -48,9 +48,7 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; -pub fn payload() -> *mut u8 { - ptr::null_mut() -} +pub type Payload = *mut u8; struct Exception { // This needs to be an Option because the object's lifetime follows C++ diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 591ff9d7fdc..dd84a814f48 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -48,7 +48,6 @@ use alloc::boxed::Box; use core::any::Any; -use core::ptr; use crate::dwarf::eh::{self, EHAction, EHContext}; use libc::{c_int, uintptr_t}; @@ -83,9 +82,7 @@ pub unsafe fn panic(data: Box) -> u32 { } } -pub fn payload() -> *mut u8 { - ptr::null_mut() -} +pub type Payload = *mut u8; pub unsafe fn cleanup(ptr: *mut u8) -> Box { let exception = Box::from_raw(ptr as *mut Exception); diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs index 2f53df2861d..8ffb4bcd3df 100644 --- a/src/libpanic_unwind/hermit.rs +++ b/src/libpanic_unwind/hermit.rs @@ -6,9 +6,7 @@ use alloc::boxed::Box; use core::any::Any; use core::ptr; -pub fn payload() -> *mut u8 { - ptr::null_mut() -} +pub type Payload = *mut u8; pub unsafe fn cleanup(_ptr: *mut u8) -> Box { extern "C" { diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 6383ae39fb6..60ddf70cea5 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -22,20 +22,20 @@ #![feature(libc)] #![feature(nll)] #![feature(panic_unwind)] -#![feature(raw)] #![feature(staged_api)] #![feature(std_internals)] #![feature(unwind_attributes)] #![feature(abi_thiscall)] +#![feature(rustc_attrs)] +#![feature(raw)] #![panic_runtime] #![feature(panic_runtime)] use alloc::boxed::Box; -use core::intrinsics; -use core::mem; use core::panic::BoxMeUp; -use core::raw; +// If adding to this list, you should also look at libstd::panicking's identical +// list of Payload types and likely add to there as well. cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] @@ -69,28 +69,11 @@ extern "C" { mod dwarf; -// Entry point for catching an exception, implemented using the `try` intrinsic -// in the compiler. -// -// The interaction between the `payload` function and the compiler is pretty -// hairy and tightly coupled, for more information see the compiler's -// implementation of this. #[no_mangle] -pub unsafe extern "C" fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - data_ptr: *mut usize, - vtable_ptr: *mut usize, -) -> u32 { - let mut payload = imp::payload(); - if intrinsics::r#try(f, data, &mut payload as *mut _ as *mut _) == 0 { - 0 - } else { - let obj = mem::transmute::<_, raw::TraitObject>(imp::cleanup(payload)); - *data_ptr = obj.data as usize; - *vtable_ptr = obj.vtable as usize; - 1 - } +pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> core::raw::TraitObject { + let payload = payload as *mut imp::Payload; + let payload = *(payload); + core::mem::transmute(imp::cleanup(payload)) } // Entry point for raising an exception, just delegates to the platform-specific diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 6f507e85e74..6f464c1ab68 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -308,9 +308,7 @@ pub unsafe fn panic(data: Box) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -pub fn payload() -> [u64; 2] { - [0; 2] -} +pub type Payload = [u64; 2]; pub unsafe fn cleanup(payload: [u64; 2]) -> Box { mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ }) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 8b12aaaa7e2..f71849fae34 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,9 +12,8 @@ use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem::{self, ManuallyDrop}; +use crate::mem::{self, ManuallyDrop, MaybeUninit}; use crate::process; -use crate::raw; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; use crate::sys_common::backtrace::{self, RustBacktrace}; @@ -29,6 +28,31 @@ use crate::io::set_panic; #[cfg(test)] use realstd::io::set_panic; +// This must be kept in sync with the implementations in libpanic_unwind. +// +// This is *not* checked in anyway; the compiler does not allow us to use a +// type/macro/anything from panic_unwind, since we're then linking in the +// panic_unwind runtime even during -Cpanic=abort. +// +// Essentially this must be the type of `imp::Payload` in libpanic_unwind. +cfg_if::cfg_if! { + if #[cfg(not(feature = "panic_unwind"))] { + type Payload = (); + } else if #[cfg(target_os = "emscripten")] { + type Payload = *mut u8; + } else if #[cfg(target_arch = "wasm32")] { + type Payload = *mut u8; + } else if #[cfg(target_os = "hermit")] { + type Payload = *mut u8; + } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { + type Payload = *mut u8; + } else if #[cfg(target_env = "msvc")] { + type Payload = [u64; 2]; + } else { + type Payload = *mut u8; + } +} + // Binary interface to the panic runtime that the standard library depends on. // // The standard library is tagged with `#![needs_panic_runtime]` (introduced in @@ -41,12 +65,9 @@ use realstd::io::set_panic; // hook up these functions, but it is not this day! #[allow(improper_ctypes)] extern "C" { - fn __rust_maybe_catch_panic( - f: fn(*mut u8), - data: *mut u8, - data_ptr: *mut usize, - vtable_ptr: *mut usize, - ) -> u32; + /// The payload ptr here is actually the same as the payload ptr for the try + /// intrinsic (i.e., is really `*mut [u64; 2]` or `*mut *mut u8`). + fn __rust_panic_cleanup(payload: *mut u8) -> core::raw::TraitObject; /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. /// It cannot be `Box` because the other end of this call does not depend @@ -250,9 +271,9 @@ pub unsafe fn r#try R>(f: F) -> Result> } // We do some sketchy operations with ownership here for the sake of - // performance. We can only pass pointers down to - // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all - // the ownership tracking here manually using a union. + // performance. We can only pass pointers down to `do_call` (can't pass + // objects by value), so we do all the ownership tracking here manually + // using a union. // // We go through a transition where: // @@ -263,7 +284,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // * If the closure successfully returns, we write the return value into the // data's return slot. Note that `ptr::write` is used as it's overwriting // uninitialized data. - // * Finally, when we come back out of the `__rust_maybe_catch_panic` we're + // * Finally, when we come back out of the `try` intrinsic we're // in one of two states: // // 1. The closure didn't panic, in which case the return value was @@ -274,27 +295,24 @@ pub unsafe fn r#try R>(f: F) -> Result> // // Once we stack all that together we should have the "most efficient' // method of calling a catch panic whilst juggling ownership. - let mut any_data = 0; - let mut any_vtable = 0; let mut data = Data { f: ManuallyDrop::new(f) }; - let r = __rust_maybe_catch_panic( - do_call::, - &mut data as *mut _ as *mut u8, - &mut any_data, - &mut any_vtable, - ); + let mut payload: MaybeUninit = MaybeUninit::uninit(); - return if r == 0 { + let data_ptr = &mut data as *mut _ as *mut u8; + let payload_ptr = payload.as_mut_ptr() as *mut _; + return if intrinsics::r#try(do_call::, data_ptr, payload_ptr) == 0 { Ok(ManuallyDrop::into_inner(data.r)) } else { - update_panic_count(-1); - Err(mem::transmute(raw::TraitObject { - data: any_data as *mut _, - vtable: any_vtable as *mut _, - })) + Err(cleanup(payload.assume_init())) }; + unsafe fn cleanup(mut payload: Payload) -> Box { + let obj = crate::mem::transmute(__rust_panic_cleanup(&mut payload as *mut _ as *mut u8)); + update_panic_count(-1); + obj + } + fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; From 1920f817caf65e5ffb95628b15cedb8aa54a8ae8 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 26 Dec 2019 10:03:41 -0500 Subject: [PATCH 0675/1250] Avoid over-aligning the return value in the -Cpanic=abort case --- src/librustc_codegen_llvm/intrinsic.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index 1ae9d2a6841..fa89c630345 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -858,8 +858,10 @@ fn try_intrinsic( ) { if bx.sess().no_landing_pads() { bx.call(func, &[data], None); - let ptr_align = bx.tcx().data_layout.pointer_align.abi; - bx.store(bx.const_null(bx.type_i8p()), dest, ptr_align); + // Return 0 unconditionally from the intrinsic call; + // we can never unwind. + let ret_align = bx.tcx().data_layout.i32_align.abi; + bx.store(bx.const_i32(0), dest, ret_align); } else if wants_msvc_seh(bx.sess()) { codegen_msvc_try(bx, func, data, local_ptr, dest); } else { From 919c5fe6b9e052eb243e0e7ceb99d2e6986b4115 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 26 Dec 2019 10:37:48 -0500 Subject: [PATCH 0676/1250] Test catch_unwind vanishing We execpt the try intrinsic to be a direct call if in -Cpanic=abort mode, and that catch_unwind optimizes out if calling a function that does not unwind. --- src/test/codegen/catch-unwind.rs | 19 +++++++++++++++++++ src/test/codegen/try-panic-abort.rs | 17 +++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/test/codegen/catch-unwind.rs create mode 100644 src/test/codegen/try-panic-abort.rs diff --git a/src/test/codegen/catch-unwind.rs b/src/test/codegen/catch-unwind.rs new file mode 100644 index 00000000000..3c9bc35d1c8 --- /dev/null +++ b/src/test/codegen/catch-unwind.rs @@ -0,0 +1,19 @@ +// compile-flags: -O + +#![crate_type = "lib"] + +extern "C" { + fn bar(); +} + +// CHECK-LABEL: @foo +#[no_mangle] +pub unsafe fn foo() -> i32 { + // CHECK: call void @bar + // CHECK: ret i32 0 + std::panic::catch_unwind(|| { + bar(); + 0 + }) + .unwrap() +} diff --git a/src/test/codegen/try-panic-abort.rs b/src/test/codegen/try-panic-abort.rs new file mode 100644 index 00000000000..9bc89a32157 --- /dev/null +++ b/src/test/codegen/try-panic-abort.rs @@ -0,0 +1,17 @@ +// compile-flags: -C panic=abort -O + +#![crate_type = "lib"] +#![feature(unwind_attributes, core_intrinsics)] + +extern "C" { + #[unwind(allow)] + fn bar(data: *mut u8); +} + +// CHECK-LABEL: @foo +#[no_mangle] +pub unsafe fn foo() -> i32 { + // CHECK: call void @bar + // CHECK: ret i32 0 + std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, 0 as *mut u8) +} From dd6c3b7c3900f58f5b97a6cec379328e855287ed Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 26 Dec 2019 10:49:16 -0500 Subject: [PATCH 0677/1250] Ignore PAL lint for std::panicking --- src/tools/tidy/src/pal.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index f11394bd95f..5e20cb0f04b 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -59,6 +59,8 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libstd/sys_common/mod.rs", "src/libstd/sys_common/net.rs", "src/libstd/sys_common/backtrace.rs", + // panic_unwind shims + "src/libstd/panicking.rs", "src/libterm", // Not sure how to make this crate portable, but test crate needs it. "src/libtest", // Probably should defer to unstable `std::sys` APIs. "src/libstd/sync/mpsc", // some tests are only run on non-emscripten From bdcc02360f34fe773c38f8ae86111fb831f8ec9e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 26 Dec 2019 10:54:24 -0500 Subject: [PATCH 0678/1250] Mark cleanup cold --- src/libstd/panicking.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index f71849fae34..3dd1f09e076 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -307,6 +307,11 @@ pub unsafe fn r#try R>(f: F) -> Result> Err(cleanup(payload.assume_init())) }; + // We consider unwinding to be rare, so mark this function as cold. However, + // do not mark it no-inline -- that decision is best to leave to the + // optimizer (in most cases this function is not inlined even as a normal, + // non-cold function, though, as of the writing of this comment). + #[cold] unsafe fn cleanup(mut payload: Payload) -> Box { let obj = crate::mem::transmute(__rust_panic_cleanup(&mut payload as *mut _ as *mut u8)); update_panic_count(-1); From 5b682354f2c8bf2c825b6229a6a125435f2053dd Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 26 Dec 2019 19:37:14 +0100 Subject: [PATCH 0679/1250] Fix some minor issues --- src/libpanic_abort/lib.rs | 5 +++-- src/libpanic_unwind/lib.rs | 5 +++-- src/libstd/panicking.rs | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index ebc57860b9d..fe9196ef231 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -17,10 +17,11 @@ #![feature(panic_runtime)] #![feature(staged_api)] #![feature(rustc_attrs)] -#![feature(raw)] + +use core::any::Any; #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_cleanup(_: *mut u8) -> core::raw::TraitObject { +pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { unreachable!() } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 60ddf70cea5..ad82f22510c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -32,6 +32,7 @@ #![feature(panic_runtime)] use alloc::boxed::Box; +use core::any::Any; use core::panic::BoxMeUp; // If adding to this list, you should also look at libstd::panicking's identical @@ -70,10 +71,10 @@ extern "C" { mod dwarf; #[no_mangle] -pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> core::raw::TraitObject { +pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { let payload = payload as *mut imp::Payload; let payload = *(payload); - core::mem::transmute(imp::cleanup(payload)) + Box::into_raw(imp::cleanup(payload)) } // Entry point for raising an exception, just delegates to the platform-specific diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 3dd1f09e076..b02cedd5da5 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -67,7 +67,7 @@ cfg_if::cfg_if! { extern "C" { /// The payload ptr here is actually the same as the payload ptr for the try /// intrinsic (i.e., is really `*mut [u64; 2]` or `*mut *mut u8`). - fn __rust_panic_cleanup(payload: *mut u8) -> core::raw::TraitObject; + fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. /// It cannot be `Box` because the other end of this call does not depend @@ -313,7 +313,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // non-cold function, though, as of the writing of this comment). #[cold] unsafe fn cleanup(mut payload: Payload) -> Box { - let obj = crate::mem::transmute(__rust_panic_cleanup(&mut payload as *mut _ as *mut u8)); + let obj = Box::from_raw(__rust_panic_cleanup(&mut payload as *mut _ as *mut u8)); update_panic_count(-1); obj } From 35349abeb33893e9d683e507f819c16063e4797e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 29 Dec 2019 12:07:44 +0100 Subject: [PATCH 0680/1250] Ignore broken no-landing-pads test --- src/test/ui/no-landing-pads.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/no-landing-pads.rs b/src/test/ui/no-landing-pads.rs index d9d53210612..44af25f7f8f 100644 --- a/src/test/ui/no-landing-pads.rs +++ b/src/test/ui/no-landing-pads.rs @@ -1,6 +1,7 @@ // run-pass // compile-flags: -Z no-landing-pads -C codegen-units=1 // ignore-emscripten no threads support +// ignore-test fails because catch_unwind doesn't work with no-landing-pads use std::thread; From 01d04944cefc61cd684e3554e48068926a5f30ab Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 7 Jan 2020 16:41:59 +0100 Subject: [PATCH 0681/1250] Apply review feedback --- Cargo.lock | 1 + src/libpanic_abort/Cargo.toml | 1 + src/libpanic_abort/lib.rs | 5 ++++- src/libpanic_unwind/dummy.rs | 2 -- src/libpanic_unwind/emcc.rs | 2 -- src/libpanic_unwind/gcc.rs | 2 -- src/libpanic_unwind/hermit.rs | 2 -- src/libpanic_unwind/lib.rs | 12 +++++++----- src/libpanic_unwind/payload.rs | 21 +++++++++++++++++++++ src/libpanic_unwind/seh.rs | 2 -- src/libstd/panicking.rs | 34 ++++++---------------------------- src/test/ui/no-landing-pads.rs | 24 ------------------------ 12 files changed, 40 insertions(+), 68 deletions(-) create mode 100644 src/libpanic_unwind/payload.rs delete mode 100644 src/test/ui/no-landing-pads.rs diff --git a/Cargo.lock b/Cargo.lock index f639095fae7..08c0462a1dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2308,6 +2308,7 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ + "cfg-if", "compiler_builtins", "core", "libc", diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml index 2bee0b716c7..8ebd95047ac 100644 --- a/src/libpanic_abort/Cargo.toml +++ b/src/libpanic_abort/Cargo.toml @@ -14,3 +14,4 @@ doc = false core = { path = "../libcore" } libc = { version = "0.2", default-features = false } compiler_builtins = "0.1.0" +cfg-if = "0.1.8" diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index fe9196ef231..6ea818ecef8 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -20,8 +20,11 @@ use core::any::Any; +// We need the definition of TryPayload for __rust_panic_cleanup. +include!("../libpanic_unwind/payload.rs"); + #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { +pub unsafe extern "C" fn __rust_panic_cleanup(_: TryPayload) -> *mut (dyn Any + Send + 'static) { unreachable!() } diff --git a/src/libpanic_unwind/dummy.rs b/src/libpanic_unwind/dummy.rs index 30593d3b88a..4667ede2baa 100644 --- a/src/libpanic_unwind/dummy.rs +++ b/src/libpanic_unwind/dummy.rs @@ -6,8 +6,6 @@ use alloc::boxed::Box; use core::any::Any; use core::intrinsics; -pub type Payload = *mut u8; - pub unsafe fn cleanup(_ptr: *mut u8) -> Box { intrinsics::abort() } diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 873135414bd..e541ec30025 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -48,8 +48,6 @@ static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { name: b"rust_panic\0".as_ptr(), }; -pub type Payload = *mut u8; - struct Exception { // This needs to be an Option because the object's lifetime follows C++ // semantics: when catch_unwind moves the Box out of the exception it must diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index dd84a814f48..20ae5edaa2a 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -82,8 +82,6 @@ pub unsafe fn panic(data: Box) -> u32 { } } -pub type Payload = *mut u8; - pub unsafe fn cleanup(ptr: *mut u8) -> Box { let exception = Box::from_raw(ptr as *mut Exception); exception.cause diff --git a/src/libpanic_unwind/hermit.rs b/src/libpanic_unwind/hermit.rs index 8ffb4bcd3df..6bded4dd499 100644 --- a/src/libpanic_unwind/hermit.rs +++ b/src/libpanic_unwind/hermit.rs @@ -6,8 +6,6 @@ use alloc::boxed::Box; use core::any::Any; use core::ptr; -pub type Payload = *mut u8; - pub unsafe fn cleanup(_ptr: *mut u8) -> Box { extern "C" { pub fn __rust_abort() -> !; diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index ad82f22510c..87d24841d04 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -35,8 +35,8 @@ use alloc::boxed::Box; use core::any::Any; use core::panic::BoxMeUp; -// If adding to this list, you should also look at libstd::panicking's identical -// list of Payload types and likely add to there as well. +// If adding to this list, you should also look at the list of TryPayload types +// defined in payload.rs and likely add to there as well. cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] @@ -62,6 +62,8 @@ cfg_if::cfg_if! { } } +include!("payload.rs"); + extern "C" { /// Handler in libstd called when a panic object is dropped outside of /// `catch_unwind`. @@ -71,9 +73,9 @@ extern "C" { mod dwarf; #[no_mangle] -pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { - let payload = payload as *mut imp::Payload; - let payload = *(payload); +pub unsafe extern "C" fn __rust_panic_cleanup( + payload: TryPayload, +) -> *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } diff --git a/src/libpanic_unwind/payload.rs b/src/libpanic_unwind/payload.rs new file mode 100644 index 00000000000..1234db7da0f --- /dev/null +++ b/src/libpanic_unwind/payload.rs @@ -0,0 +1,21 @@ +// Type definition for the payload argument of the try intrinsic. +// +// This must be kept in sync with the implementations of the try intrinsic. +// +// This file is included by both panic runtimes and libstd. It is part of the +// panic runtime ABI. +cfg_if::cfg_if! { + if #[cfg(target_os = "emscripten")] { + type TryPayload = *mut u8; + } else if #[cfg(target_arch = "wasm32")] { + type TryPayload = *mut u8; + } else if #[cfg(target_os = "hermit")] { + type TryPayload = *mut u8; + } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { + type TryPayload = *mut u8; + } else if #[cfg(target_env = "msvc")] { + type TryPayload = [u64; 2]; + } else { + type TryPayload = *mut u8; + } +} diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 6f464c1ab68..da5ee5369e0 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -308,8 +308,6 @@ pub unsafe fn panic(data: Box) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -pub type Payload = [u64; 2]; - pub unsafe fn cleanup(payload: [u64; 2]) -> Box { mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ }) } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index b02cedd5da5..38cb4418dd0 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -28,30 +28,8 @@ use crate::io::set_panic; #[cfg(test)] use realstd::io::set_panic; -// This must be kept in sync with the implementations in libpanic_unwind. -// -// This is *not* checked in anyway; the compiler does not allow us to use a -// type/macro/anything from panic_unwind, since we're then linking in the -// panic_unwind runtime even during -Cpanic=abort. -// -// Essentially this must be the type of `imp::Payload` in libpanic_unwind. -cfg_if::cfg_if! { - if #[cfg(not(feature = "panic_unwind"))] { - type Payload = (); - } else if #[cfg(target_os = "emscripten")] { - type Payload = *mut u8; - } else if #[cfg(target_arch = "wasm32")] { - type Payload = *mut u8; - } else if #[cfg(target_os = "hermit")] { - type Payload = *mut u8; - } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { - type Payload = *mut u8; - } else if #[cfg(target_env = "msvc")] { - type Payload = [u64; 2]; - } else { - type Payload = *mut u8; - } -} +// Include the definition of UnwindPayload from libpanic_unwind. +include!("../libpanic_unwind/payload.rs"); // Binary interface to the panic runtime that the standard library depends on. // @@ -67,7 +45,7 @@ cfg_if::cfg_if! { extern "C" { /// The payload ptr here is actually the same as the payload ptr for the try /// intrinsic (i.e., is really `*mut [u64; 2]` or `*mut *mut u8`). - fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); + fn __rust_panic_cleanup(payload: TryPayload) -> *mut (dyn Any + Send + 'static); /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. /// It cannot be `Box` because the other end of this call does not depend @@ -297,7 +275,7 @@ pub unsafe fn r#try R>(f: F) -> Result> // method of calling a catch panic whilst juggling ownership. let mut data = Data { f: ManuallyDrop::new(f) }; - let mut payload: MaybeUninit = MaybeUninit::uninit(); + let mut payload: MaybeUninit = MaybeUninit::uninit(); let data_ptr = &mut data as *mut _ as *mut u8; let payload_ptr = payload.as_mut_ptr() as *mut _; @@ -312,8 +290,8 @@ pub unsafe fn r#try R>(f: F) -> Result> // optimizer (in most cases this function is not inlined even as a normal, // non-cold function, though, as of the writing of this comment). #[cold] - unsafe fn cleanup(mut payload: Payload) -> Box { - let obj = Box::from_raw(__rust_panic_cleanup(&mut payload as *mut _ as *mut u8)); + unsafe fn cleanup(payload: TryPayload) -> Box { + let obj = Box::from_raw(__rust_panic_cleanup(payload)); update_panic_count(-1); obj } diff --git a/src/test/ui/no-landing-pads.rs b/src/test/ui/no-landing-pads.rs deleted file mode 100644 index 44af25f7f8f..00000000000 --- a/src/test/ui/no-landing-pads.rs +++ /dev/null @@ -1,24 +0,0 @@ -// run-pass -// compile-flags: -Z no-landing-pads -C codegen-units=1 -// ignore-emscripten no threads support -// ignore-test fails because catch_unwind doesn't work with no-landing-pads - -use std::thread; - -static mut HIT: bool = false; - -struct A; - -impl Drop for A { - fn drop(&mut self) { - unsafe { HIT = true; } - } -} - -fn main() { - thread::spawn(move|| -> () { - let _a = A; - panic!(); - }).join().unwrap_err(); - assert!(unsafe { !HIT }); -} From 61b67d0c199e4f93d227d7303fab0270ec1a68d0 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 13 Jan 2020 00:55:36 +0000 Subject: [PATCH 0682/1250] Fix cross-DLL panics under MSVC --- .../src/language-features/lang-items.md | 1 - src/libpanic_unwind/seh.rs | 13 ++++---- src/librustc_codegen_llvm/intrinsic.rs | 30 +++++++++++++++---- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 6f096e582f5..b6e61e7050c 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -248,7 +248,6 @@ the source code. - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC) - - `eh_catch_typeinfo`: `libpanic_unwind/seh.rs` (SEH) - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - `panic`: `libcore/panicking.rs` - `panic_bounds_check`: `libcore/panicking.rs` diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index da5ee5369e0..f599f9815a6 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -167,6 +167,9 @@ pub struct _TypeDescriptor { // Note that we intentionally ignore name mangling rules here: we don't want C++ // to be able to catch Rust panics by simply declaring a `struct rust_panic`. +// +// When modifying, make sure that the type name string exactly matches +// the one used in src/librustc_codegen_llvm/intrinsic.rs. const TYPE_NAME: [u8; 11] = *b"rust_panic\0"; static mut THROW_INFO: _ThrowInfo = _ThrowInfo { @@ -199,12 +202,12 @@ extern "C" { static TYPE_INFO_VTABLE: *const u8; } -// We use #[lang = "eh_catch_typeinfo"] here as this is the type descriptor which -// we'll use in LLVM's `catchpad` instruction which ends up also being passed as -// an argument to the C++ personality function. +// This type descriptor is only used when throwing an exception. The catch part +// is handled by the try intrinsic, which generates its own TypeDescriptor. // -// Again, I'm not entirely sure what this is describing, it just seems to work. -#[cfg_attr(not(test), lang = "eh_catch_typeinfo")] +// This is fine since the MSVC runtime uses string comparison on the type name +// to match TypeDescriptors rather than pointer equality. +#[cfg_attr(bootstrap, lang = "eh_catch_typeinfo")] static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { pVFTable: unsafe { &TYPE_INFO_VTABLE } as *const _ as *const _, spare: core::ptr::null_mut(), diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index fa89c630345..fa7e7e6e4a2 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -954,6 +954,31 @@ fn codegen_msvc_try( let cs = catchswitch.catch_switch(None, None, 1); catchswitch.add_handler(cs, catchpad.llbb()); + // We can't use the TypeDescriptor defined in libpanic_unwind because it + // might be in another DLL and the SEH encoding only supports specifying + // a TypeDescriptor from the current module. + // + // However this isn't an issue since the MSVC runtime uses string + // comparison on the type name to match TypeDescriptors rather than + // pointer equality. + // + // So instead we generate a new TypeDescriptor in each module that uses + // `try` and let the linker merge duplicate definitions in the same + // module. + // + // When modifying, make sure that the type_name string exactly matches + // the one used in src/libpanic_unwind/seh.rs. + let type_info_vtable = bx.declare_global("??_7type_info@@6B@", bx.type_i8p()); + let type_name = bx.const_bytes(b"rust_panic\0"); + let type_info = + bx.const_struct(&[type_info_vtable, bx.const_null(bx.type_i8p()), type_name], false); + let tydesc = bx.declare_global("__rust_panic_type_info", bx.val_ty(type_info)); + unsafe { + llvm::LLVMRustSetLinkage(tydesc, llvm::Linkage::LinkOnceODRLinkage); + llvm::SetUniqueComdat(bx.llmod, tydesc); + llvm::LLVMSetInitializer(tydesc, type_info); + } + // The flag value of 8 indicates that we are catching the exception by // reference instead of by value. We can't use catch by value because // that requires copying the exception object, which we don't support @@ -961,12 +986,7 @@ fn codegen_msvc_try( // // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang let flags = bx.const_i32(8); - let tydesc = match bx.tcx().lang_items().eh_catch_typeinfo() { - Some(did) => bx.get_static(did), - None => bug!("eh_catch_typeinfo not defined, but needed for SEH unwinding"), - }; let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]); - let i64_align = bx.tcx().data_layout.i64_align.abi; let payload_ptr = catchpad.load(slot, ptr_align); let payload = catchpad.load(payload_ptr, i64_align); From d73813ae62a2d7327f1e657f999ea7636c7a402d Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 14 Jan 2020 17:42:47 +0000 Subject: [PATCH 0683/1250] Apply CPU attributes to __rust_try --- src/librustc_codegen_llvm/intrinsic.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index fa7e7e6e4a2..baaa2a5cf45 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1106,6 +1106,8 @@ fn gen_fn<'ll, 'tcx>( )); let fn_abi = FnAbi::of_fn_ptr(cx, rust_fn_sig, &[]); let llfn = cx.declare_fn(name, &fn_abi); + cx.set_frame_pointer_elimination(llfn); + cx.apply_target_cpu_attr(llfn); // FIXME(eddyb) find a nicer way to do this. unsafe { llvm::LLVMRustSetLinkage(llfn, llvm::Linkage::InternalLinkage) }; let bx = Builder::new_block(cx, llfn, "entry-block"); From 21affdd00d52fba6388f1858a52c253b3f83a90d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 1 Mar 2020 20:56:30 +0100 Subject: [PATCH 0684/1250] use values() or keys() respectively when iterating only over keys or values of maps. --- src/librustc/traits/structural_impls.rs | 2 +- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_hir/hir.rs | 6 +++--- src/librustc_infer/infer/lexical_region_resolve/mod.rs | 2 +- src/librustc_infer/infer/region_constraints/leak_check.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 48ed29f2bb3..2fcb70c489d 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -234,7 +234,7 @@ impl BoundNamesCollector { start = false; write!(fmt, "{}", r)?; } - for (_, t) in &self.types { + for t in self.types.values() { if !start { write!(fmt, ", ")?; } diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 6e2b3ec5fd2..3724a83a949 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -188,7 +188,7 @@ fn parse_args<'a>( let mut err = ecx .struct_span_err(e.span, "positional arguments cannot follow named arguments"); err.span_label(e.span, "positional arguments must be before named arguments"); - for (_, pos) in &names { + for pos in names.values() { err.span_label(args[*pos].span, "named argument"); } err.emit(); diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 1a74b50b57e..f948e22e84b 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -679,15 +679,15 @@ impl Crate<'_> { where V: itemlikevisit::ItemLikeVisitor<'hir>, { - for (_, item) in &self.items { + for item in self.items.values() { visitor.visit_item(item); } - for (_, trait_item) in &self.trait_items { + for trait_item in self.trait_items.values() { visitor.visit_trait_item(trait_item); } - for (_, impl_item) in &self.impl_items { + for impl_item in self.impl_items.values() { visitor.visit_impl_item(impl_item); } } diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index fc9f3bb0767..b7278ecd5e4 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -751,7 +751,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { let dummy_source = graph.add_node(()); let dummy_sink = graph.add_node(()); - for (constraint, _) in &self.data.constraints { + for constraint in self.data.constraints.keys() { match *constraint { Constraint::VarSubVar(a_id, b_id) => { graph.add_edge( diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index 74ffdc7a4f0..bbd4f3b3550 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -34,7 +34,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { assert!(self.in_snapshot()); // Go through each placeholder that we created. - for (_, &placeholder_region) in placeholder_map { + for &placeholder_region in placeholder_map.values() { // Find the universe this placeholder inhabits. let placeholder = match placeholder_region { ty::RePlaceholder(p) => p, diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 463452e45ce..193b6d75935 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -347,7 +347,7 @@ fn krate(tcx: TyCtxt<'_>) -> NamedRegionMap { lifetime_uses: &mut Default::default(), missing_named_lifetime_spots: vec![], }; - for (_, item) in &krate.items { + for item in krate.items.values() { visitor.visit_item(item); } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bef14d3f4a3..199b476cb9a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1652,7 +1652,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } for (projection_bound, _) in &bounds.projection_bounds { - for (_, def_ids) in &mut associated_types { + for def_ids in associated_types.values_mut() { def_ids.remove(&projection_bound.projection_def_id()); } } From ba49ed01f0abd2c18313611ad43424ca827c1498 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Mar 2020 13:10:24 +0100 Subject: [PATCH 0685/1250] clean up E0378 explanation --- src/librustc_error_codes/error_codes/E0378.md | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0378.md b/src/librustc_error_codes/error_codes/E0378.md index 311483c8900..7f4374738de 100644 --- a/src/librustc_error_codes/error_codes/E0378.md +++ b/src/librustc_error_codes/error_codes/E0378.md @@ -1,10 +1,28 @@ +The `DispatchFromDyn` trait was implemented on something which is not a pointer +or a newtype wrapper around a pointer. + +Erroneous code example: + +```compile-fail,E0378 +#![feature(dispatch_from_dyn)] +use std::ops::DispatchFromDyn; + +struct WrapperExtraField { + ptr: T, + extra_stuff: i32, +} + +impl DispatchFromDyn> for WrapperExtraField +where + T: DispatchFromDyn, +{} +``` + The `DispatchFromDyn` trait currently can only be implemented for builtin pointer types and structs that are newtype wrappers around them — that is, the struct must have only one field (except for`PhantomData`), and that field must itself implement `DispatchFromDyn`. -Examples: - ``` #![feature(dispatch_from_dyn, unsize)] use std::{ @@ -20,6 +38,8 @@ where {} ``` +Another example: + ``` #![feature(dispatch_from_dyn)] use std::{ @@ -37,21 +57,3 @@ where T: DispatchFromDyn, {} ``` - -Example of illegal `DispatchFromDyn` implementation -(illegal because of extra field) - -```compile-fail,E0378 -#![feature(dispatch_from_dyn)] -use std::ops::DispatchFromDyn; - -struct WrapperExtraField { - ptr: T, - extra_stuff: i32, -} - -impl DispatchFromDyn> for WrapperExtraField -where - T: DispatchFromDyn, -{} -``` From 8858d71d28d68a0063f3ccab1fbf378d69afc78b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:12:09 +0100 Subject: [PATCH 0686/1250] Put back output-format option for show-coverage --- src/librustdoc/config.rs | 59 +++++++++++++++++++++++++---- src/librustdoc/core.rs | 2 + src/librustdoc/html/render.rs | 3 +- src/librustdoc/html/render/cache.rs | 1 + 4 files changed, 56 insertions(+), 9 deletions(-) diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 33b3e800374..99a55f3c682 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,5 +1,6 @@ use std::collections::BTreeMap; use std::ffi::OsStr; +use std::convert::TryFrom; use std::fmt; use std::path::PathBuf; @@ -24,6 +25,33 @@ use crate::opts; use crate::passes::{self, Condition, DefaultPassOption}; use crate::theme; +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum OutputFormat { + Json, + HTML, +} + +impl OutputFormat { + pub fn is_json(&self) -> bool { + match *self { + OutputFormat::Json => true, + _ => false, + } + } +} + +impl TryFrom<&str> for OutputFormat { + type Error = String; + + fn try_from(value: &str) -> Result { + match value { + "json" => Ok(OutputFormat::Json), + "html" => Ok(OutputFormat::HTML), + _ => Err(format!("unknown output format `{}`", value)), + } + } +} + /// Configuration options for rustdoc. #[derive(Clone)] pub struct Options { @@ -115,6 +143,8 @@ pub struct Options { pub crate_version: Option, /// Collected options specific to outputting final pages. pub render_options: RenderOptions, + /// Output format rendering (used only for "show-coverage" option for the moment) + pub output_format: Option, } impl fmt::Debug for Options { @@ -425,14 +455,6 @@ impl Options { } } - match matches.opt_str("w").as_ref().map(|s| &**s) { - Some("html") | None => {} - Some(s) => { - diag.struct_err(&format!("unknown output format: {}", s)).emit(); - return Err(1); - } - } - let index_page = matches.opt_str("index-page").map(|s| PathBuf::from(&s)); if let Some(ref index_page) = index_page { if !index_page.is_file() { @@ -469,6 +491,23 @@ impl Options { } }; + let output_format = match matches.opt_str("output-format") { + Some(s) => match OutputFormat::try_from(s.as_str()) { + Ok(o) => { + if o.is_json() && !show_coverage { + diag.struct_err("json output format isn't supported for doc generation") + .emit(); + return Err(1); + } + Some(o) + } + Err(e) => { + diag.struct_err(&e).emit(); + return Err(1); + } + } + None => None, + }; let crate_name = matches.opt_str("crate-name"); let proc_macro_crate = crate_types.contains(&CrateType::ProcMacro); let playground_url = matches.opt_str("playground-url"); @@ -553,6 +592,7 @@ impl Options { generate_search_filter, generate_redirect_pages, }, + output_format, }) } @@ -568,6 +608,9 @@ fn check_deprecated_options(matches: &getopts::Matches, diag: &rustc_errors::Han for flag in deprecated_flags.iter() { if matches.opt_present(flag) { + if *flag == "output-format" && matches.opt_present("show-coverage") { + continue; + } let mut err = diag.struct_warn(&format!("the '{}' flag is considered deprecated", flag)); err.warn( diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 8bc34e949f1..b9ae3d53afc 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -228,6 +228,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt mut manual_passes, display_warnings, render_options, + output_format, .. } = options; @@ -385,6 +386,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut renderinfo = RenderInfo::default(); renderinfo.access_levels = access_levels; + renderinfo.output_format = output_format; let mut ctxt = DocContext { tcx, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4dd2a6562a4..016054c688d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -60,7 +60,7 @@ use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy}; -use crate::config::RenderOptions; +use crate::config::{OutputFormat, RenderOptions}; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; use crate::html::escape::Escape; @@ -270,6 +270,7 @@ pub struct RenderInfo { pub deref_trait_did: Option, pub deref_mut_trait_did: Option, pub owned_box_did: Option, + pub output_format: Option, } // Helper structs for rendering items/sidebars and carrying along contextual diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index a0a35e4ce4b..4198369eca8 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -139,6 +139,7 @@ impl Cache { deref_trait_did, deref_mut_trait_did, owned_box_did, + .. } = renderinfo; let external_paths = From 10492c392af127074d13593ae0dd5067286e8e15 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:12:29 +0100 Subject: [PATCH 0687/1250] Add support for json output in show-coverage option --- .../passes/calculate_doc_coverage.rs | 67 ++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index d4a7f3313a4..0ca5a956bdb 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -1,4 +1,5 @@ use crate::clean; +use crate::config::OutputFormat; use crate::core::DocContext; use crate::fold::{self, DocFolder}; use crate::passes::Pass; @@ -6,6 +7,7 @@ use crate::passes::Pass; use rustc_ast::attr; use rustc_span::symbol::sym; use rustc_span::FileName; +use serialize::json::{ToJson, Json}; use std::collections::BTreeMap; use std::ops; @@ -16,8 +18,8 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass { description: "counts the number of items with and without documentation", }; -fn calculate_doc_coverage(krate: clean::Crate, _: &DocContext<'_>) -> clean::Crate { - let mut calc = CoverageCalculator::default(); +fn calculate_doc_coverage( krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { + let mut calc = CoverageCalculator::new(ctx.renderinfo.borrow().output_format); let krate = calc.fold_crate(krate); calc.print_results(); @@ -64,13 +66,72 @@ impl ops::AddAssign for ItemCount { } } -#[derive(Default)] struct CoverageCalculator { items: BTreeMap, + output_format: Option, +} + +fn limit_filename_len(filename: String) -> String { + // if a filename is too long, shorten it so we don't blow out the table + // FIXME(misdreavus): this needs to count graphemes, and probably also track + // double-wide characters... + if filename.len() > 35 { + "...".to_string() + &filename[filename.len() - 32..] + } else { + filename + } +} + +impl ToJson for CoverageCalculator { + fn to_json(&self) -> Json { + let mut total = ItemCount::default(); + let mut entries = BTreeMap::default(); + + entries.insert("files".to_owned(), Json::Array(self.items + .iter() + .filter_map(|(file, &count)| { + count.percentage().map(|percent| { + (limit_filename_len(file.to_string()), count, percent) + }) + }) + .map(|(name, count, percentage)| { + let mut fields = BTreeMap::default(); + + fields.insert("documented".to_owned(), Json::U64(count.with_docs)); + fields.insert("total".to_owned(), Json::U64(count.total)); + fields.insert("percentage".to_owned(), Json::F64(percentage)); + + total += count; + + let mut obj = BTreeMap::default(); + obj.insert(name, Json::Object(fields)); + + Json::Object(obj) + }) + .collect::>())); + let mut fields = BTreeMap::default(); + fields.insert("documented".to_owned(), Json::U64(total.with_docs)); + fields.insert("total".to_owned(), Json::U64(total.total)); + fields.insert("percentage".to_owned(), Json::F64(total.percentage().unwrap_or(0.0))); + + entries.insert("total".to_owned(), Json::Object(fields)); + Json::Object(entries) + } } impl CoverageCalculator { + fn new(output_format: Option) -> CoverageCalculator { + CoverageCalculator { + items: Default::default(), + output_format, + } + } + fn print_results(&self) { + if self.output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { + println!("{}", self.to_json().pretty()); + return; + } let mut total = ItemCount::default(); fn print_table_line() { From 15babed8b7936e03ed4cd57afd5c91c44dc4f0be Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 16 Nov 2019 16:23:27 +0100 Subject: [PATCH 0688/1250] add tests for rustdoc output-format json --- src/test/rustdoc-ui/coverage/json.rs | 27 ++++++++++++++++++++ src/test/rustdoc-ui/coverage/json.stdout | 7 +++++ src/test/rustdoc/output-format-fail-check.rs | 5 ++++ 3 files changed, 39 insertions(+) create mode 100644 src/test/rustdoc-ui/coverage/json.rs create mode 100644 src/test/rustdoc-ui/coverage/json.stdout create mode 100644 src/test/rustdoc/output-format-fail-check.rs diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs new file mode 100644 index 00000000000..8b80244f825 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -0,0 +1,27 @@ +// build-pass +// compile-flags:-Z unstable-options --show-coverage + +pub mod foo { + /// Hello! + pub struct Foo; + /// Bar + pub enum Bar { A } +} + +/// X +pub struct X; + +/// Bar +pub mod bar { + /// bar + pub struct Bar; + /// X + pub enum X { Y } +} + +/// yolo +pub enum Yolo { X } + +pub struct Xo { + x: T, +} diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout new file mode 100644 index 00000000000..be56a8c0ffa --- /dev/null +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -0,0 +1,7 @@ ++-------------------------------------+------------+------------+------------+ +| File | Documented | Total | Percentage | ++-------------------------------------+------------+------------+------------+ +| ...test/rustdoc-ui/coverage/json.rs | 7 | 13 | 53.8% | ++-------------------------------------+------------+------------+------------+ +| Total | 7 | 13 | 53.8% | ++-------------------------------------+------------+------------+------------+ diff --git a/src/test/rustdoc/output-format-fail-check.rs b/src/test/rustdoc/output-format-fail-check.rs new file mode 100644 index 00000000000..a78811078be --- /dev/null +++ b/src/test/rustdoc/output-format-fail-check.rs @@ -0,0 +1,5 @@ +// compile-flags:-Z unstable-options --output-format +// should-fail + +/// toudoum! +pub struct SomeStruct; From f1070b152546827e599cdee1f64c55faaf8bf082 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Feb 2020 13:53:27 +0100 Subject: [PATCH 0689/1250] Replace ToJson with serde --- src/librustdoc/config.rs | 16 ++-- .../passes/calculate_doc_coverage.rs | 90 ++++++------------- src/test/rustdoc-ui/coverage/html.rs | 4 + src/test/rustdoc-ui/coverage/html.stderr | 2 + src/test/rustdoc-ui/coverage/json.rs | 2 +- src/test/rustdoc-ui/coverage/json.stdout | 8 +- .../coverage}/output-format-fail-check.rs | 1 - .../coverage/output-format-fail-check.stderr | 6 ++ 8 files changed, 51 insertions(+), 78 deletions(-) create mode 100644 src/test/rustdoc-ui/coverage/html.rs create mode 100644 src/test/rustdoc-ui/coverage/html.stderr rename src/test/{rustdoc => rustdoc-ui/coverage}/output-format-fail-check.rs (85%) create mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.stderr diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 99a55f3c682..58c8a7d82bf 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -1,6 +1,6 @@ use std::collections::BTreeMap; -use std::ffi::OsStr; use std::convert::TryFrom; +use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; @@ -28,12 +28,12 @@ use crate::theme; #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum OutputFormat { Json, - HTML, + Html, } impl OutputFormat { pub fn is_json(&self) -> bool { - match *self { + match self { OutputFormat::Json => true, _ => false, } @@ -46,7 +46,7 @@ impl TryFrom<&str> for OutputFormat { fn try_from(value: &str) -> Result { match value { "json" => Ok(OutputFormat::Json), - "html" => Ok(OutputFormat::HTML), + "html" => Ok(OutputFormat::Html), _ => Err(format!("unknown output format `{}`", value)), } } @@ -498,6 +498,12 @@ impl Options { diag.struct_err("json output format isn't supported for doc generation") .emit(); return Err(1); + } else if !o.is_json() && show_coverage { + diag.struct_err( + "html output format isn't supported for the --show-coverage option", + ) + .emit(); + return Err(1); } Some(o) } @@ -505,7 +511,7 @@ impl Options { diag.struct_err(&e).emit(); return Err(1); } - } + }, None => None, }; let crate_name = matches.opt_str("crate-name"); diff --git a/src/librustdoc/passes/calculate_doc_coverage.rs b/src/librustdoc/passes/calculate_doc_coverage.rs index 0ca5a956bdb..f48224512ba 100644 --- a/src/librustdoc/passes/calculate_doc_coverage.rs +++ b/src/librustdoc/passes/calculate_doc_coverage.rs @@ -7,7 +7,8 @@ use crate::passes::Pass; use rustc_ast::attr; use rustc_span::symbol::sym; use rustc_span::FileName; -use serialize::json::{ToJson, Json}; +use serde::Serialize; +use serde_json; use std::collections::BTreeMap; use std::ops; @@ -18,16 +19,16 @@ pub const CALCULATE_DOC_COVERAGE: Pass = Pass { description: "counts the number of items with and without documentation", }; -fn calculate_doc_coverage( krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { - let mut calc = CoverageCalculator::new(ctx.renderinfo.borrow().output_format); +fn calculate_doc_coverage(krate: clean::Crate, ctx: &DocContext<'_>) -> clean::Crate { + let mut calc = CoverageCalculator::new(); let krate = calc.fold_crate(krate); - calc.print_results(); + calc.print_results(ctx.renderinfo.borrow().output_format); krate } -#[derive(Default, Copy, Clone)] +#[derive(Default, Copy, Clone, Serialize)] struct ItemCount { total: u64, with_docs: u64, @@ -68,68 +69,37 @@ impl ops::AddAssign for ItemCount { struct CoverageCalculator { items: BTreeMap, - output_format: Option, } fn limit_filename_len(filename: String) -> String { - // if a filename is too long, shorten it so we don't blow out the table - // FIXME(misdreavus): this needs to count graphemes, and probably also track - // double-wide characters... - if filename.len() > 35 { - "...".to_string() + &filename[filename.len() - 32..] + let nb_chars = filename.chars().count(); + if nb_chars > 35 { + "...".to_string() + + &filename[filename.char_indices().nth(nb_chars - 32).map(|x| x.0).unwrap_or(0)..] } else { filename } } -impl ToJson for CoverageCalculator { - fn to_json(&self) -> Json { - let mut total = ItemCount::default(); - let mut entries = BTreeMap::default(); - - entries.insert("files".to_owned(), Json::Array(self.items - .iter() - .filter_map(|(file, &count)| { - count.percentage().map(|percent| { - (limit_filename_len(file.to_string()), count, percent) - }) - }) - .map(|(name, count, percentage)| { - let mut fields = BTreeMap::default(); - - fields.insert("documented".to_owned(), Json::U64(count.with_docs)); - fields.insert("total".to_owned(), Json::U64(count.total)); - fields.insert("percentage".to_owned(), Json::F64(percentage)); - - total += count; - - let mut obj = BTreeMap::default(); - obj.insert(name, Json::Object(fields)); - - Json::Object(obj) - }) - .collect::>())); - let mut fields = BTreeMap::default(); - fields.insert("documented".to_owned(), Json::U64(total.with_docs)); - fields.insert("total".to_owned(), Json::U64(total.total)); - fields.insert("percentage".to_owned(), Json::F64(total.percentage().unwrap_or(0.0))); - - entries.insert("total".to_owned(), Json::Object(fields)); - Json::Object(entries) +impl CoverageCalculator { + fn new() -> CoverageCalculator { + CoverageCalculator { items: Default::default() } } -} -impl CoverageCalculator { - fn new(output_format: Option) -> CoverageCalculator { - CoverageCalculator { - items: Default::default(), - output_format, - } + fn to_json(&self) -> String { + serde_json::to_string( + &self + .items + .iter() + .map(|(k, v)| (k.to_string(), v)) + .collect::>(), + ) + .expect("failed to convert JSON data to string") } - fn print_results(&self) { - if self.output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { - println!("{}", self.to_json().pretty()); + fn print_results(&self, output_format: Option) { + if output_format.map(|o| o.is_json()).unwrap_or_else(|| false) { + println!("{}", self.to_json()); return; } let mut total = ItemCount::default(); @@ -154,15 +124,7 @@ impl CoverageCalculator { for (file, &count) in &self.items { if let Some(percentage) = count.percentage() { - let mut name = file.to_string(); - // if a filename is too long, shorten it so we don't blow out the table - // FIXME(misdreavus): this needs to count graphemes, and probably also track - // double-wide characters... - if name.len() > 35 { - name = "...".to_string() + &name[name.len() - 32..]; - } - - print_table_record(&name, count, percentage); + print_table_record(&limit_filename_len(file.to_string()), count, percentage); total += count; } diff --git a/src/test/rustdoc-ui/coverage/html.rs b/src/test/rustdoc-ui/coverage/html.rs new file mode 100644 index 00000000000..181cb4c5061 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/html.rs @@ -0,0 +1,4 @@ +// compile-flags:-Z unstable-options --output-format html --show-coverage + +/// Foo +pub struct Xo; diff --git a/src/test/rustdoc-ui/coverage/html.stderr b/src/test/rustdoc-ui/coverage/html.stderr new file mode 100644 index 00000000000..adca375d4bc --- /dev/null +++ b/src/test/rustdoc-ui/coverage/html.stderr @@ -0,0 +1,2 @@ +error: html output format isn't supported for the --show-coverage option + diff --git a/src/test/rustdoc-ui/coverage/json.rs b/src/test/rustdoc-ui/coverage/json.rs index 8b80244f825..b1220b32e91 100644 --- a/src/test/rustdoc-ui/coverage/json.rs +++ b/src/test/rustdoc-ui/coverage/json.rs @@ -1,5 +1,5 @@ // build-pass -// compile-flags:-Z unstable-options --show-coverage +// compile-flags:-Z unstable-options --output-format json --show-coverage pub mod foo { /// Hello! diff --git a/src/test/rustdoc-ui/coverage/json.stdout b/src/test/rustdoc-ui/coverage/json.stdout index be56a8c0ffa..63b22a7d94b 100644 --- a/src/test/rustdoc-ui/coverage/json.stdout +++ b/src/test/rustdoc-ui/coverage/json.stdout @@ -1,7 +1 @@ -+-------------------------------------+------------+------------+------------+ -| File | Documented | Total | Percentage | -+-------------------------------------+------------+------------+------------+ -| ...test/rustdoc-ui/coverage/json.rs | 7 | 13 | 53.8% | -+-------------------------------------+------------+------------+------------+ -| Total | 7 | 13 | 53.8% | -+-------------------------------------+------------+------------+------------+ +{"$DIR/json.rs":{"total":13,"with_docs":7}} diff --git a/src/test/rustdoc/output-format-fail-check.rs b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs similarity index 85% rename from src/test/rustdoc/output-format-fail-check.rs rename to src/test/rustdoc-ui/coverage/output-format-fail-check.rs index a78811078be..30b525df763 100644 --- a/src/test/rustdoc/output-format-fail-check.rs +++ b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs @@ -1,5 +1,4 @@ // compile-flags:-Z unstable-options --output-format -// should-fail /// toudoum! pub struct SomeStruct; diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr new file mode 100644 index 00000000000..9e9aa0e0501 --- /dev/null +++ b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr @@ -0,0 +1,6 @@ +warning: the 'output-format' flag is considered deprecated + | + = warning: see issue #44136 for more information + +error: too many file operands + From 1c01646e6f1ed540fa1be66f3389181ad5644778 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 27 Feb 2020 17:20:32 +0100 Subject: [PATCH 0690/1250] Extend json detection in runtest --- src/tools/compiletest/src/runtest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ac808b1f14e..86621e8812b 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -3204,7 +3204,9 @@ impl<'test> TestCx<'test> { let json = cflags.contains("--error-format json") || cflags.contains("--error-format pretty-json") || cflags.contains("--error-format=json") - || cflags.contains("--error-format=pretty-json"); + || cflags.contains("--error-format=pretty-json") + || cflags.contains("--output-format json") + || cflags.contains("--output-format=json"); let mut normalized = output.to_string(); From b6466273ba3d019433a8665fb337bfedeaf209ef Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 2 Mar 2020 13:20:32 +0100 Subject: [PATCH 0691/1250] remove output-format test --- src/test/rustdoc-ui/coverage/output-format-fail-check.rs | 4 ---- .../rustdoc-ui/coverage/output-format-fail-check.stderr | 6 ------ 2 files changed, 10 deletions(-) delete mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.rs delete mode 100644 src/test/rustdoc-ui/coverage/output-format-fail-check.stderr diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.rs b/src/test/rustdoc-ui/coverage/output-format-fail-check.rs deleted file mode 100644 index 30b525df763..00000000000 --- a/src/test/rustdoc-ui/coverage/output-format-fail-check.rs +++ /dev/null @@ -1,4 +0,0 @@ -// compile-flags:-Z unstable-options --output-format - -/// toudoum! -pub struct SomeStruct; diff --git a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr b/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr deleted file mode 100644 index 9e9aa0e0501..00000000000 --- a/src/test/rustdoc-ui/coverage/output-format-fail-check.stderr +++ /dev/null @@ -1,6 +0,0 @@ -warning: the 'output-format' flag is considered deprecated - | - = warning: see issue #44136 for more information - -error: too many file operands - From 0ec14089a9b62b9e3cda6e84f6ac598ea3778933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 00:09:17 +0100 Subject: [PATCH 0692/1250] Don't convert Results to Options just for matching. --- src/librustc_resolve/imports.rs | 4 ++-- src/libstd/net/addr.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 1d502e52de4..73bc038ea15 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1252,7 +1252,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // this may resolve to either a value or a type, but for documentation // purposes it's good enough to just favor one over the other. self.r.per_ns(|this, ns| { - if let Some(binding) = source_bindings[ns].get().ok() { + if let Ok(binding) = source_bindings[ns].get() { this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); } }); @@ -1293,7 +1293,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None }; self.r.per_ns(|this, ns| { - if let Some(binding) = source_bindings[ns].get().ok() { + if let Ok(binding) = source_bindings[ns].get() { if binding.res() == Res::Err { return; } diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index a59d7f0263b..57cba6b1f7a 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -901,7 +901,7 @@ impl ToSocketAddrs for str { type Iter = vec::IntoIter; fn to_socket_addrs(&self) -> io::Result> { // try to parse as a regular SocketAddr first - if let Some(addr) = self.parse().ok() { + if let Ok(addr) = self.parse() { return Ok(vec![addr].into_iter()); } From fdc14cb0b0b47d1a1e1eadf7431b5fcd11568599 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 1 Mar 2020 16:06:36 -0800 Subject: [PATCH 0693/1250] Toolstate: don't duplicate nightly tool list. --- src/bootstrap/toolstate.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 5c39f5d5bc3..7cffc472930 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -443,7 +443,7 @@ fn change_toolstate( if new_state != state { eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state); if new_state < state { - if !["rustc-guide", "miri", "embedded-book"].contains(&tool.as_str()) { + if !NIGHTLY_TOOLS.iter().any(|(name, _path)| name == tool) { regressed = true; } } From 851e9d64baa8d54a2960a3e5946143cb24b772b5 Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Mon, 2 Mar 2020 20:08:21 +0100 Subject: [PATCH 0694/1250] s/merged_block_count/statements_to_merge/g --- src/librustc_mir/transform/simplify.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 1534b9bdcea..7aa1052d4b2 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -128,12 +128,12 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { changed |= inner_changed; } - let merged_block_count = + let statements_to_merge = merged_blocks.iter().map(|&i| self.basic_blocks[i].statements.len()).sum(); - if merged_block_count > 0 { + if statements_to_merge > 0 { let mut statements = std::mem::take(&mut self.basic_blocks[bb].statements); - statements.reserve(merged_block_count); + statements.reserve(statements_to_merge); for &from in &merged_blocks { statements.append(&mut self.basic_blocks[from].statements); } From 011fa9107f405149d006a4208ffb8503214e82ce Mon Sep 17 00:00:00 2001 From: Dodo Date: Mon, 2 Mar 2020 21:05:14 +0100 Subject: [PATCH 0695/1250] const forget tests --- src/libcore/tests/lib.rs | 1 + src/libcore/tests/mem.rs | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 991458db5b7..cc341c93980 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -40,6 +40,7 @@ #![feature(never_type)] #![feature(unwrap_infallible)] #![feature(leading_trailing_ones)] +#![feature(const_forget)] extern crate test; diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 59588d97787..4841be5fc71 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -129,3 +129,21 @@ fn test_discriminant_send_sync() { is_send_sync::>(); is_send_sync::>(); } + +#[test] +fn test_const_forget() { + const fn test_const_forget(x: T) { + forget(x); + } + + // Writing this function signature without const-forget + // triggers compiler errors: + // 1) That we use a non-const fn inside a const fn + // 2) without the forget, it complains about the destructor of Box + const fn const_forget_box(mut x: Box) { + forget(x); + } + + const _: () = test_const_forget(0i32); + const _: () = test_const_forget(Vec::>>::new()); +} \ No newline at end of file From 15264e95f26f90c8e02ad3785d94c1bb4e4bec32 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sun, 1 Mar 2020 17:11:57 -0800 Subject: [PATCH 0696/1250] Update cargo, clippy --- Cargo.lock | 12 ++++++------ src/tools/cargo | 2 +- src/tools/clippy | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f639095fae7..1676b5b1275 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1254,9 +1254,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77519ef7c5beee314d0804d4534f01e0f9e8d9acdee2b7a48627e590b27e0ec4" +checksum = "26e07ef27260a78f7e8d218ebac2c72f2c4db50493741b190b6e8eade1da7c68" dependencies = [ "bitflags", "libc", @@ -1269,9 +1269,9 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2559abb1d87d27668d31bd868a000f0e2e0065d10e78961b62da95d7a7f1cc7" +checksum = "af1754ec4170e7dcaf9bb43743bb16eddb8d827b2e0291deb6f220a6e16fe46a" dependencies = [ "curl", "git2", @@ -1789,9 +1789,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.10.0" +version = "0.11.0+0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9ec6bca50549d34a392611dde775123086acbd994e3fff64954777ce2dc2e51" +checksum = "4d5d1459353d397a029fb18862166338de938e6be976606bd056cf8f1a912ecf" dependencies = [ "cc", "libc", diff --git a/src/tools/cargo b/src/tools/cargo index e57bd02999c..bda50510d1d 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit e57bd02999c9f40d52116e0beca7d1dccb0643de +Subproject commit bda50510d1daf6e9c53ad6ccf603da6e0fa8103f diff --git a/src/tools/clippy b/src/tools/clippy index fc5d0cc583c..8b7f7e66726 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit fc5d0cc583cb1cd35d58fdb7f3e0cfa12dccd6c0 +Subproject commit 8b7f7e667268921c278af94ae30a61e87a22b22b From 5f4af546d4fd19dd1238aaf2fd1026237b39916f Mon Sep 17 00:00:00 2001 From: Dodo Date: Mon, 2 Mar 2020 21:40:35 +0100 Subject: [PATCH 0697/1250] An enter as last character pleases tidy it seems --- src/libcore/tests/mem.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 4841be5fc71..9ed2323e287 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -146,4 +146,4 @@ fn test_const_forget() { const _: () = test_const_forget(0i32); const _: () = test_const_forget(Vec::>>::new()); -} \ No newline at end of file +} From 0c82a5c1d35c84859ed2f88194858adae831d06d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Mon, 2 Mar 2020 21:42:55 +0100 Subject: [PATCH 0698/1250] Apply suggestions from code review --- src/libcore/iter/traits/exact_size.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/traits/exact_size.rs b/src/libcore/iter/traits/exact_size.rs index 946c3f85824..ad87d09588e 100644 --- a/src/libcore/iter/traits/exact_size.rs +++ b/src/libcore/iter/traits/exact_size.rs @@ -69,9 +69,10 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub trait ExactSizeIterator: Iterator { - /// Returns the exact length of the iterator, which is the number of times - /// the iterator will return `Some(T)` before returning `None`. + /// Returns the exact length of the iterator. /// + /// The implementation ensures that the iterator will return exactly `len()` + /// more times a `Some(T)` value, before returning `None`. /// This method has a default implementation, so you usually should not /// implement it directly. However, if you can provide a more efficient /// implementation, you can do so. See the [trait-level] docs for an From a674e1c88c632c237d7e56fbb6972b46c39a1fb0 Mon Sep 17 00:00:00 2001 From: Dodo Date: Mon, 2 Mar 2020 23:43:50 +0100 Subject: [PATCH 0699/1250] remove unused mut, restructure the test --- src/libcore/tests/mem.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/libcore/tests/mem.rs b/src/libcore/tests/mem.rs index 9ed2323e287..8337ab10341 100644 --- a/src/libcore/tests/mem.rs +++ b/src/libcore/tests/mem.rs @@ -132,18 +132,18 @@ fn test_discriminant_send_sync() { #[test] fn test_const_forget() { - const fn test_const_forget(x: T) { - forget(x); - } + const _: () = forget(0i32); + const _: () = forget(Vec::>>::new()); // Writing this function signature without const-forget // triggers compiler errors: // 1) That we use a non-const fn inside a const fn // 2) without the forget, it complains about the destructor of Box - const fn const_forget_box(mut x: Box) { + const fn const_forget_box(x: Box) { forget(x); } - const _: () = test_const_forget(0i32); - const _: () = test_const_forget(Vec::>>::new()); + // Call the forget_box at runtime, + // as we can't const-construct a box yet. + const_forget_box(Box::new(0i32)); } From d8e3557dbae23283f81d7bc45200413dd93ced4a Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Tue, 3 Mar 2020 00:08:24 +0100 Subject: [PATCH 0700/1250] Remove `usable_size` APIs --- src/liballoc/alloc.rs | 14 +- src/liballoc/alloc/tests.rs | 2 +- src/liballoc/boxed.rs | 4 +- src/liballoc/raw_vec.rs | 21 +- src/liballoc/raw_vec/tests.rs | 2 +- src/liballoc/rc.rs | 2 +- src/liballoc/sync.rs | 2 +- src/liballoc/tests/heap.rs | 2 +- src/libcore/alloc.rs | 304 ++++++-------------- src/libstd/alloc.rs | 16 +- src/test/ui/allocator/custom.rs | 4 +- src/test/ui/allocator/xcrate-use.rs | 4 +- src/test/ui/realloc-16687.rs | 12 +- src/test/ui/regions/regions-mock-codegen.rs | 14 +- 14 files changed, 134 insertions(+), 269 deletions(-) diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index f41404bf8ca..73e8121868a 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -165,8 +165,8 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(alloc(layout)).ok_or(AllocErr) + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } #[inline] @@ -180,13 +180,13 @@ unsafe impl AllocRef for Global { ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result, AllocErr> { - NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + ) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr).map(|p| (p, new_size)) } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr) + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } } @@ -201,7 +201,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } else { let layout = Layout::from_size_align_unchecked(size, align); match Global.alloc(layout) { - Ok(ptr) => ptr.as_ptr(), + Ok((ptr, _)) => ptr.as_ptr(), Err(_) => handle_alloc_error(layout), } } diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs index c902971638b..55944398e16 100644 --- a/src/liballoc/alloc/tests.rs +++ b/src/liballoc/alloc/tests.rs @@ -8,7 +8,7 @@ use test::Bencher; fn allocate_zeroed() { unsafe { let layout = Layout::from_size_align(1024, 1).unwrap(); - let ptr = + let (ptr, _) = Global.alloc_zeroed(layout.clone()).unwrap_or_else(|_| handle_alloc_error(layout)); let mut i = ptr.cast::().as_ptr(); diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3ac4bd82a3a..4729f0290cf 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -200,7 +200,7 @@ impl Box { let ptr = if layout.size() == 0 { NonNull::dangling() } else { - Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() + Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast() }; Box::from_raw(ptr.as_ptr()) } @@ -270,7 +270,7 @@ impl Box<[T]> { let ptr = if layout.size() == 0 { NonNull::dangling() } else { - Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).cast() + Global.alloc(layout).unwrap_or_else(|_| alloc::handle_alloc_error(layout)).0.cast() }; Box::from_raw(slice::from_raw_parts_mut(ptr.as_ptr(), len)) } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 144654946a2..345834d7daa 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -72,7 +72,7 @@ impl RawVec { RawVec::allocate_in(capacity, true, a) } - fn allocate_in(capacity: usize, zeroed: bool, mut a: A) -> Self { + fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self { unsafe { let elem_size = mem::size_of::(); @@ -87,7 +87,10 @@ impl RawVec { let layout = Layout::from_size_align(alloc_size, align).unwrap(); let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) }; match result { - Ok(ptr) => ptr.cast(), + Ok((ptr, size)) => { + capacity = size / elem_size; + ptr.cast() + } Err(_) => handle_alloc_error(layout), } }; @@ -280,7 +283,7 @@ impl RawVec { // 0, getting to here necessarily means the `RawVec` is overfull. assert!(elem_size != 0, "capacity overflow"); - let (new_cap, ptr) = match self.current_layout() { + let (ptr, new_cap) = match self.current_layout() { Some(cur) => { // Since we guarantee that we never allocate more than // `isize::MAX` bytes, `elem_size * self.cap <= isize::MAX` as @@ -297,7 +300,7 @@ impl RawVec { alloc_guard(new_size).unwrap_or_else(|_| capacity_overflow()); let ptr_res = self.a.realloc(NonNull::from(self.ptr).cast(), cur, new_size); match ptr_res { - Ok(ptr) => (new_cap, ptr), + Ok((ptr, new_size)) => (ptr, new_size / elem_size), Err(_) => handle_alloc_error(Layout::from_size_align_unchecked( new_size, cur.align(), @@ -310,7 +313,7 @@ impl RawVec { let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 }; let layout = Layout::array::(new_cap).unwrap(); match self.a.alloc(layout) { - Ok(ptr) => (new_cap, ptr), + Ok((ptr, new_size)) => (ptr, new_size / elem_size), Err(_) => handle_alloc_error(layout), } } @@ -598,7 +601,7 @@ impl RawVec { let align = mem::align_of::(); let old_layout = Layout::from_size_align_unchecked(old_size, align); match self.a.realloc(NonNull::from(self.ptr).cast(), old_layout, new_size) { - Ok(p) => self.ptr = p.cast().into(), + Ok((ptr, _)) => self.ptr = ptr.cast().into(), Err(_) => { handle_alloc_error(Layout::from_size_align_unchecked(new_size, align)) } @@ -631,6 +634,8 @@ impl RawVec { fallibility: Fallibility, strategy: ReserveStrategy, ) -> Result<(), TryReserveError> { + let elem_size = mem::size_of::(); + unsafe { // 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. @@ -662,7 +667,7 @@ impl RawVec { None => self.a.alloc(new_layout), }; - let ptr = match (res, fallibility) { + let (ptr, new_cap) = match (res, fallibility) { (Err(AllocErr), Infallible) => handle_alloc_error(new_layout), (Err(AllocErr), Fallible) => { return Err(TryReserveError::AllocError { @@ -670,7 +675,7 @@ impl RawVec { non_exhaustive: (), }); } - (Ok(ptr), _) => ptr, + (Ok((ptr, new_size)), _) => (ptr, new_size / elem_size), }; self.ptr = ptr.cast().into(); diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 63087501f0e..860058debe1 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -20,7 +20,7 @@ fn allocator_param() { fuel: usize, } unsafe impl AllocRef for BoundedAlloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { let size = layout.size(); if size > self.fuel { return Err(AllocErr); diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9dc5447397f..901cc70a4d8 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -923,7 +923,7 @@ impl Rc { let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); // Allocate for the layout. - let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the RcBox let inner = mem_to_rcbox(mem.as_ptr()); diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index fd285242d5b..fced5e680ea 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -784,7 +784,7 @@ impl Arc { // reference (see #54908). let layout = Layout::new::>().extend(value_layout).unwrap().0.pad_to_align(); - let mem = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (mem, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); // Initialize the ArcInner let inner = mem_to_arcinner(mem.as_ptr()); diff --git a/src/liballoc/tests/heap.rs b/src/liballoc/tests/heap.rs index 7fcfcf9b294..d159126f426 100644 --- a/src/liballoc/tests/heap.rs +++ b/src/liballoc/tests/heap.rs @@ -20,7 +20,7 @@ fn check_overalign_requests(mut allocator: T) { unsafe { let pointers: Vec<_> = (0..iterations) .map(|_| { - allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap() + allocator.alloc(Layout::from_size_align(size, align).unwrap()).unwrap().0 }) .collect(); for &ptr in &pointers { diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 71f7f971eab..f3a2b73f2b8 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -11,12 +11,6 @@ use crate::num::NonZeroUsize; use crate::ptr::{self, NonNull}; use crate::usize; -/// Represents the combination of a starting address and -/// a total capacity of the returned block. -#[unstable(feature = "allocator_api", issue = "32838")] -#[derive(Debug)] -pub struct Excess(pub NonNull, pub usize); - const fn size_align() -> (usize, usize) { (mem::size_of::(), mem::align_of::()) } @@ -593,13 +587,12 @@ pub unsafe trait GlobalAlloc { /// /// * the starting address for that memory block was previously /// returned by a previous call to an allocation method (`alloc`, -/// `alloc_zeroed`, `alloc_excess`) or reallocation method -/// (`realloc`, `realloc_excess`), and +/// `alloc_zeroed`) or reallocation method (`realloc`), and /// /// * the memory block has not been subsequently deallocated, where /// blocks are deallocated either by being passed to a deallocation -/// method (`dealloc`, `dealloc_one`, `dealloc_array`) or by being -/// passed to a reallocation method (see above) that returns `Ok`. +/// method (`dealloc`) or by being passed to a reallocation method +/// (see above) that returns `Ok`. /// /// A note regarding zero-sized types and zero-sized layouts: many /// methods in the `AllocRef` trait state that allocation requests @@ -625,11 +618,9 @@ pub unsafe trait GlobalAlloc { /// /// 2. The block's size must fall in the range `[use_min, use_max]`, where: /// -/// * `use_min` is `self.usable_size(layout).0`, and +/// * `use_min` is `layout.size()`, and /// -/// * `use_max` is the capacity that was (or would have been) -/// returned when (if) the block was allocated via a call to -/// `alloc_excess` or `realloc_excess`. +/// * `use_max` is the capacity that was returned. /// /// Note that: /// @@ -643,6 +634,9 @@ pub unsafe trait GlobalAlloc { /// currently allocated via an allocator `a`, then it is legal to /// use that layout to deallocate it, i.e., `a.dealloc(ptr, k);`. /// +/// * if an allocator does not support overallocating, it is fine to +/// simply return `layout.size()` as the allocated size. +/// /// # Safety /// /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and @@ -671,8 +665,9 @@ pub unsafe trait AllocRef { // However in jemalloc for example, // `mallocx(0)` is documented as undefined behavior.) - /// Returns a pointer meeting the size and alignment guarantees of - /// `layout`. + /// On success, returns a pointer meeting the size and alignment + /// guarantees of `layout` and the actual size of the allocated block, + /// which must be greater than or equal to `layout.size()`. /// /// If this method returns an `Ok(addr)`, then the `addr` returned /// will be non-null address pointing to a block of storage @@ -709,7 +704,7 @@ pub unsafe trait AllocRef { /// rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr>; + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr>; /// Deallocate the memory referenced by `ptr`. /// @@ -728,38 +723,31 @@ pub unsafe trait AllocRef { /// to allocate that block of memory. unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout); - // == ALLOCATOR-SPECIFIC QUANTITIES AND LIMITS == - // usable_size - - /// Returns bounds on the guaranteed usable size of a successful - /// allocation created with the specified `layout`. - /// - /// In particular, if one has a memory block allocated via a given - /// allocator `a` and layout `k` where `a.usable_size(k)` returns - /// `(l, u)`, then one can pass that block to `a.dealloc()` with a - /// layout in the size range [l, u]. - /// - /// (All implementors of `usable_size` must ensure that - /// `l <= k.size() <= u`) - /// - /// Both the lower- and upper-bounds (`l` and `u` respectively) - /// are provided, because an allocator based on size classes could - /// misbehave if one attempts to deallocate a block without - /// providing a correct value for its size (i.e., one within the - /// range `[l, u]`). - /// - /// Clients who wish to make use of excess capacity are encouraged - /// to use the `alloc_excess` and `realloc_excess` instead, as - /// this method is constrained to report conservative values that - /// serve as valid bounds for *all possible* allocation method - /// calls. - /// - /// However, for clients that do not wish to track the capacity - /// returned by `alloc_excess` locally, this method is likely to - /// produce useful results. - #[inline] - fn usable_size(&self, layout: &Layout) -> (usize, usize) { - (layout.size(), layout.size()) + /// Behaves like `alloc`, but also ensures that the contents + /// are set to zero before being returned. + /// + /// # Safety + /// + /// This function is unsafe for the same reasons that `alloc` is. + /// + /// # Errors + /// + /// Returning `Err` indicates that either memory is exhausted or + /// `layout` does not meet allocator's size or alignment + /// constraints, just as in `alloc`. + /// + /// Clients wishing to abort computation in response to an + /// allocation error are encouraged to call the [`handle_alloc_error`] function, + /// rather than directly invoking `panic!` or similar. + /// + /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + let size = layout.size(); + let result = self.alloc(layout); + if let Ok((p, _)) = result { + ptr::write_bytes(p.as_ptr(), 0, size); + } + result } // == METHODS FOR MEMORY REUSE == @@ -767,9 +755,10 @@ pub unsafe trait AllocRef { /// Returns a pointer suitable for holding data described by /// a new layout with `layout`’s alignment and a size given - /// by `new_size`. To - /// accomplish this, this may extend or shrink the allocation - /// referenced by `ptr` to fit the new layout. + /// by `new_size` and the actual size of the allocated block. + /// The latter is greater than or equal to `layout.size()`. + /// To accomplish this, the allocator may extend or shrink + /// the allocation referenced by `ptr` to fit the new layout. /// /// If this returns `Ok`, then ownership of the memory block /// referenced by `ptr` has been transferred to this @@ -824,23 +813,25 @@ pub unsafe trait AllocRef { ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result, AllocErr> { + ) -> Result<(NonNull, usize), AllocErr> { let old_size = layout.size(); - if new_size >= old_size { - if let Ok(()) = self.grow_in_place(ptr, layout, new_size) { - return Ok(ptr); + if new_size > old_size { + if let Ok(size) = self.grow_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } } else if new_size < old_size { - if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { - return Ok(ptr); + if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } + } else { + return Ok((ptr, new_size)); } // otherwise, fall back on alloc + copy + dealloc. let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); let result = self.alloc(new_layout); - if let Ok(new_ptr) = result { + if let Ok((new_ptr, _)) = result { ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); self.dealloc(ptr, layout); } @@ -877,174 +868,40 @@ pub unsafe trait AllocRef { ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result, AllocErr> { + ) -> Result<(NonNull, usize), AllocErr> { let old_size = layout.size(); - if new_size >= old_size { - if let Ok(()) = self.grow_in_place_zeroed(ptr, layout, new_size) { - return Ok(ptr); + if new_size > old_size { + if let Ok(size) = self.grow_in_place_zeroed(ptr, layout, new_size) { + return Ok((ptr, size)); } } else if new_size < old_size { - if let Ok(()) = self.shrink_in_place(ptr, layout, new_size) { - return Ok(ptr); + if let Ok(size) = self.shrink_in_place(ptr, layout, new_size) { + return Ok((ptr, size)); } + } else { + return Ok((ptr, new_size)); } // otherwise, fall back on alloc + copy + dealloc. let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); let result = self.alloc_zeroed(new_layout); - if let Ok(new_ptr) = result { + if let Ok((new_ptr, _)) = result { ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_ptr(), cmp::min(old_size, new_size)); self.dealloc(ptr, layout); } result } - /// Behaves like `alloc`, but also ensures that the contents - /// are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { - let size = layout.size(); - let p = self.alloc(layout); - if let Ok(p) = p { - ptr::write_bytes(p.as_ptr(), 0, size); - } - p - } - - /// Behaves like `alloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_excess(&mut self, layout: Layout) -> Result { - let usable_size = self.usable_size(&layout); - self.alloc(layout).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `alloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// Also it ensures that the contents are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `alloc`. - /// - /// Clients wishing to abort computation in response to an - /// allocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_excess_zeroed(&mut self, layout: Layout) -> Result { - let usable_size = self.usable_size(&layout); - self.alloc_zeroed(layout).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `realloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `realloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `realloc`. - /// - /// Clients wishing to abort computation in response to a - /// reallocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn realloc_excess( - &mut self, - ptr: NonNull, - layout: Layout, - new_size: usize, - ) -> Result { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let usable_size = self.usable_size(&new_layout); - self.realloc(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) - } - - /// Behaves like `realloc`, but also returns the whole size of - /// the returned block. For some `layout` inputs, like arrays, this - /// may include extra storage usable for additional data. - /// Also it ensures that the contents are set to zero before being returned. - /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `realloc` is. - /// - /// # Errors - /// - /// Returning `Err` indicates that either memory is exhausted or - /// `layout` does not meet allocator's size or alignment - /// constraints, just as in `realloc`. - /// - /// Clients wishing to abort computation in response to a - /// reallocation error are encouraged to call the [`handle_alloc_error`] function, - /// rather than directly invoking `panic!` or similar. - /// - /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn realloc_excess_zeroed( - &mut self, - ptr: NonNull, - layout: Layout, - new_size: usize, - ) -> Result { - let new_layout = Layout::from_size_align_unchecked(new_size, layout.align()); - let usable_size = self.usable_size(&new_layout); - self.realloc_zeroed(ptr, layout, new_size).map(|p| Excess(p, usable_size.1)) - } - /// Attempts to extend the allocation referenced by `ptr` to fit `new_size`. /// /// If this returns `Ok`, then the allocator has asserted that the /// memory block referenced by `ptr` now fits `new_size`, and thus can /// be used to carry data of a layout of that size and same alignment as - /// `layout`. (The allocator is allowed to - /// expend effort to accomplish this, such as extending the memory block to - /// include successor blocks, or virtual memory tricks.) + /// `layout`. The returned value is the new size of the allocated block. + /// (The allocator is allowed to expend effort to accomplish this, such + /// as extending the memory block to include successor blocks, or virtual + /// memory tricks.) /// /// Regardless of what this method returns, ownership of the /// memory block referenced by `ptr` has not been transferred, and @@ -1072,18 +929,17 @@ pub unsafe trait AllocRef { /// function; clients are expected either to be able to recover from /// `grow_in_place` failures without aborting, or to fall back on /// another reallocation method before resorting to an abort. + #[inline] unsafe fn grow_in_place( &mut self, ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - let _ = ptr; // this default implementation doesn't care about the actual address. - debug_assert!(new_size >= layout.size()); - let (_l, u) = self.usable_size(&layout); - // _l <= layout.size() [guaranteed by usable_size()] - // layout.size() <= new_layout.size() [required by this method] - if new_size <= u { Ok(()) } else { Err(CannotReallocInPlace) } + ) -> Result { + let _ = ptr; + let _ = layout; + let _ = new_size; + Err(CannotReallocInPlace) } /// Behaves like `grow_in_place`, but also ensures that the new @@ -1108,10 +964,10 @@ pub unsafe trait AllocRef { ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - self.grow_in_place(ptr, layout, new_size)?; + ) -> Result { + let size = self.grow_in_place(ptr, layout, new_size)?; ptr.as_ptr().add(layout.size()).write_bytes(0, new_size - layout.size()); - Ok(()) + Ok(size) } /// Attempts to shrink the allocation referenced by `ptr` to fit `new_size`. @@ -1119,7 +975,8 @@ pub unsafe trait AllocRef { /// If this returns `Ok`, then the allocator has asserted that the /// memory block referenced by `ptr` now fits `new_size`, and /// thus can only be used to carry data of that smaller - /// layout. (The allocator is allowed to take advantage of this, + /// layout. The returned value is the new size the allocated block. + /// (The allocator is allowed to take advantage of this, /// carving off portions of the block for reuse elsewhere.) The /// truncated contents of the block within the smaller layout are /// unaltered, and ownership of block has not been transferred. @@ -1153,17 +1010,16 @@ pub unsafe trait AllocRef { /// function; clients are expected either to be able to recover from /// `shrink_in_place` failures without aborting, or to fall back /// on another reallocation method before resorting to an abort. + #[inline] unsafe fn shrink_in_place( &mut self, ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result<(), CannotReallocInPlace> { - let _ = ptr; // this default implementation doesn't care about the actual address. - debug_assert!(new_size <= layout.size()); - let (l, _u) = self.usable_size(&layout); - // layout.size() <= _u [guaranteed by usable_size()] - // new_layout.size() <= layout.size() [required by this method] - if l <= new_size { Ok(()) } else { Err(CannotReallocInPlace) } + ) -> Result { + let _ = ptr; + let _ = layout; + let _ = new_size; + Err(CannotReallocInPlace) } } diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 8965c6860c4..2da18e06d99 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -137,13 +137,15 @@ pub struct System; #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for System { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr) + unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)).ok_or(AllocErr) + unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)) + .ok_or(AllocErr) + .map(|p| (p, layout.size())) } #[inline] @@ -157,8 +159,10 @@ unsafe impl AllocRef for System { ptr: NonNull, layout: Layout, new_size: usize, - ) -> Result, AllocErr> { - NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)).ok_or(AllocErr) + ) -> Result<(NonNull, usize), AllocErr> { + NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)) + .ok_or(AllocErr) + .map(|p| (p, new_size)) } } diff --git a/src/test/ui/allocator/custom.rs b/src/test/ui/allocator/custom.rs index 0b1f6d5a96e..c275db14b42 100644 --- a/src/test/ui/allocator/custom.rs +++ b/src/test/ui/allocator/custom.rs @@ -37,7 +37,7 @@ fn main() { unsafe { let layout = Layout::from_size_align(4, 2).unwrap(); - let ptr = Global.alloc(layout.clone()).unwrap(); + let (ptr, _) = Global.alloc(layout.clone()).unwrap(); helper::work_with(&ptr); assert_eq!(HITS.load(Ordering::SeqCst), n + 1); Global.dealloc(ptr, layout.clone()); @@ -49,7 +49,7 @@ fn main() { drop(s); assert_eq!(HITS.load(Ordering::SeqCst), n + 4); - let ptr = System.alloc(layout.clone()).unwrap(); + let (ptr, _) = System.alloc(layout.clone()).unwrap(); assert_eq!(HITS.load(Ordering::SeqCst), n + 4); helper::work_with(&ptr); System.dealloc(ptr, layout); diff --git a/src/test/ui/allocator/xcrate-use.rs b/src/test/ui/allocator/xcrate-use.rs index 37b28c195df..e4746d1a7ec 100644 --- a/src/test/ui/allocator/xcrate-use.rs +++ b/src/test/ui/allocator/xcrate-use.rs @@ -20,13 +20,13 @@ fn main() { let n = GLOBAL.0.load(Ordering::SeqCst); let layout = Layout::from_size_align(4, 2).unwrap(); - let ptr = Global.alloc(layout.clone()).unwrap(); + let (ptr, _) = Global.alloc(layout.clone()).unwrap(); helper::work_with(&ptr); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 1); Global.dealloc(ptr, layout.clone()); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); - let ptr = System.alloc(layout.clone()).unwrap(); + let (ptr, _) = System.alloc(layout.clone()).unwrap(); assert_eq!(GLOBAL.0.load(Ordering::SeqCst), n + 2); helper::work_with(&ptr); System.dealloc(ptr, layout); diff --git a/src/test/ui/realloc-16687.rs b/src/test/ui/realloc-16687.rs index 425aa83e70a..eb6224ad1bb 100644 --- a/src/test/ui/realloc-16687.rs +++ b/src/test/ui/realloc-16687.rs @@ -41,13 +41,13 @@ unsafe fn test_triangle() -> bool { println!("allocate({:?})", layout); } - let ret = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); if PRINT { - println!("allocate({:?}) = {:?}", layout, ret); + println!("allocate({:?}) = {:?}", layout, ptr); } - ret.cast().as_ptr() + ptr.cast().as_ptr() } unsafe fn deallocate(ptr: *mut u8, layout: Layout) { @@ -63,16 +63,16 @@ unsafe fn test_triangle() -> bool { println!("reallocate({:?}, old={:?}, new={:?})", ptr, old, new); } - let ret = Global.realloc(NonNull::new_unchecked(ptr), old, new.size()) + let (ptr, _) = Global.realloc(NonNull::new_unchecked(ptr), old, new.size()) .unwrap_or_else(|_| handle_alloc_error( Layout::from_size_align_unchecked(new.size(), old.align()) )); if PRINT { println!("reallocate({:?}, old={:?}, new={:?}) = {:?}", - ptr, old, new, ret); + ptr, old, new, ptr); } - ret.cast().as_ptr() + ptr.cast().as_ptr() } fn idx_to_size(i: usize) -> usize { (i+1) * 10 } diff --git a/src/test/ui/regions/regions-mock-codegen.rs b/src/test/ui/regions/regions-mock-codegen.rs index f50b1c8b17f..fe3a864fe4b 100644 --- a/src/test/ui/regions/regions-mock-codegen.rs +++ b/src/test/ui/regions/regions-mock-codegen.rs @@ -24,29 +24,29 @@ struct Ccx { x: isize } -fn alloc<'a>(_bcx : &'a arena) -> &'a Bcx<'a> { +fn alloc(_bcx: &arena) -> &Bcx<'_> { unsafe { let layout = Layout::new::(); - let ptr = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); + let (ptr, _) = Global.alloc(layout).unwrap_or_else(|_| handle_alloc_error(layout)); &*(ptr.as_ptr() as *const _) } } -fn h<'a>(bcx : &'a Bcx<'a>) -> &'a Bcx<'a> { +fn h<'a>(bcx: &'a Bcx<'a>) -> &'a Bcx<'a> { return alloc(bcx.fcx.arena); } -fn g(fcx : &Fcx) { - let bcx = Bcx { fcx: fcx }; +fn g(fcx: &Fcx) { + let bcx = Bcx { fcx }; let bcx2 = h(&bcx); unsafe { Global.dealloc(NonNull::new_unchecked(bcx2 as *const _ as *mut _), Layout::new::()); } } -fn f(ccx : &Ccx) { +fn f(ccx: &Ccx) { let a = arena(()); - let fcx = Fcx { arena: &a, ccx: ccx }; + let fcx = Fcx { arena: &a, ccx }; return g(&fcx); } From b3777c952f1752de0762e3f0882ac5ffb6eeb7ee Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 17 Feb 2020 15:32:37 -0500 Subject: [PATCH 0701/1250] Remove chalk integration --- Cargo.lock | 21 - src/librustc/Cargo.toml | 1 - src/librustc/query/mod.rs | 10 - src/librustc/traits/mod.rs | 43 -- src/librustc/traits/structural_impls.rs | 72 -- .../infer/canonical/canonicalizer.rs | 12 +- src/librustc_infer/traits/chalk_fulfill.rs | 159 ----- src/librustc_infer/traits/engine.rs | 10 +- .../traits/error_reporting/mod.rs | 21 +- src/librustc_infer/traits/mod.rs | 5 - src/librustc_infer/traits/select.rs | 14 +- src/librustc_session/options.rs | 2 - src/librustc_traits/Cargo.toml | 1 - src/librustc_traits/chalk_context/mod.rs | 638 ------------------ .../chalk_context/program_clauses/builtin.rs | 316 --------- .../chalk_context/program_clauses/mod.rs | 300 -------- .../program_clauses/primitive.rs | 168 ----- .../chalk_context/resolvent_ops.rs | 297 -------- src/librustc_traits/chalk_context/unify.rs | 85 --- src/librustc_traits/generic_types.rs | 65 -- src/librustc_traits/lib.rs | 3 - src/librustc_ty/ty.rs | 7 +- .../chalkify/chalk_initial_program.rs | 16 - .../compile-fail/chalkify/generic_impls.rs | 18 - src/test/compile-fail/chalkify/impl_wf.rs | 39 -- .../recursive_where_clause_on_type.rs | 28 - src/test/compile-fail/chalkify/type_wf.rs | 24 - src/test/ui/chalkify/builtin-copy-clone.rs | 44 -- src/test/ui/chalkify/inherent_impl.rs | 42 -- src/test/ui/chalkify/lower_env1.rs | 14 - src/test/ui/chalkify/lower_env1.stderr | 22 - src/test/ui/chalkify/lower_env2.rs | 16 - src/test/ui/chalkify/lower_env2.stderr | 23 - src/test/ui/chalkify/lower_env3.rs | 16 - src/test/ui/chalkify/lower_env3.stderr | 20 - src/test/ui/chalkify/lower_impl.rs | 19 - src/test/ui/chalkify/lower_impl.stderr | 18 - src/test/ui/chalkify/lower_struct.rs | 8 - src/test/ui/chalkify/lower_struct.stderr | 13 - src/test/ui/chalkify/lower_trait.rs | 13 - src/test/ui/chalkify/lower_trait.stderr | 24 - .../ui/chalkify/lower_trait_higher_rank.rs | 10 - .../chalkify/lower_trait_higher_rank.stderr | 13 - .../ui/chalkify/lower_trait_where_clause.rs | 17 - .../chalkify/lower_trait_where_clause.stderr | 15 - src/test/ui/chalkify/projection.rs | 25 - src/test/ui/chalkify/super_trait.rs | 19 - src/test/ui/chalkify/trait_implied_bound.rs | 18 - src/test/ui/chalkify/type_implied_bound.rs | 29 - src/test/ui/chalkify/type_inference.rs | 26 - src/test/ui/chalkify/type_inference.stderr | 23 - .../ui/const-generics/issues/issue-65675.rs | 10 - .../const-generics/issues/issue-65675.stderr | 8 - 53 files changed, 20 insertions(+), 2860 deletions(-) delete mode 100644 src/librustc_infer/traits/chalk_fulfill.rs delete mode 100644 src/librustc_traits/chalk_context/mod.rs delete mode 100644 src/librustc_traits/chalk_context/program_clauses/builtin.rs delete mode 100644 src/librustc_traits/chalk_context/program_clauses/mod.rs delete mode 100644 src/librustc_traits/chalk_context/program_clauses/primitive.rs delete mode 100644 src/librustc_traits/chalk_context/resolvent_ops.rs delete mode 100644 src/librustc_traits/chalk_context/unify.rs delete mode 100644 src/librustc_traits/generic_types.rs delete mode 100644 src/test/compile-fail/chalkify/chalk_initial_program.rs delete mode 100644 src/test/compile-fail/chalkify/generic_impls.rs delete mode 100644 src/test/compile-fail/chalkify/impl_wf.rs delete mode 100644 src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs delete mode 100644 src/test/compile-fail/chalkify/type_wf.rs delete mode 100644 src/test/ui/chalkify/builtin-copy-clone.rs delete mode 100644 src/test/ui/chalkify/inherent_impl.rs delete mode 100644 src/test/ui/chalkify/lower_env1.rs delete mode 100644 src/test/ui/chalkify/lower_env1.stderr delete mode 100644 src/test/ui/chalkify/lower_env2.rs delete mode 100644 src/test/ui/chalkify/lower_env2.stderr delete mode 100644 src/test/ui/chalkify/lower_env3.rs delete mode 100644 src/test/ui/chalkify/lower_env3.stderr delete mode 100644 src/test/ui/chalkify/lower_impl.rs delete mode 100644 src/test/ui/chalkify/lower_impl.stderr delete mode 100644 src/test/ui/chalkify/lower_struct.rs delete mode 100644 src/test/ui/chalkify/lower_struct.stderr delete mode 100644 src/test/ui/chalkify/lower_trait.rs delete mode 100644 src/test/ui/chalkify/lower_trait.stderr delete mode 100644 src/test/ui/chalkify/lower_trait_higher_rank.rs delete mode 100644 src/test/ui/chalkify/lower_trait_higher_rank.stderr delete mode 100644 src/test/ui/chalkify/lower_trait_where_clause.rs delete mode 100644 src/test/ui/chalkify/lower_trait_where_clause.stderr delete mode 100644 src/test/ui/chalkify/projection.rs delete mode 100644 src/test/ui/chalkify/super_trait.rs delete mode 100644 src/test/ui/chalkify/trait_implied_bound.rs delete mode 100644 src/test/ui/chalkify/type_implied_bound.rs delete mode 100644 src/test/ui/chalkify/type_inference.rs delete mode 100644 src/test/ui/chalkify/type_inference.stderr delete mode 100644 src/test/ui/const-generics/issues/issue-65675.rs delete mode 100644 src/test/ui/const-generics/issues/issue-65675.stderr diff --git a/Cargo.lock b/Cargo.lock index f639095fae7..57af0119baa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -419,25 +419,6 @@ dependencies = [ "rustc-std-workspace-core", ] -[[package]] -name = "chalk-engine" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ec698a6f053a23bfbe646d9f2fde4b02abc19125595270a99e6f44ae0bdd1a" -dependencies = [ - "chalk-macros", - "rustc-hash", -] - -[[package]] -name = "chalk-macros" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "295635afd6853aa9f20baeb7f0204862440c0fe994c5a253d5f479dac41d047e" -dependencies = [ - "lazy_static 0.2.11", -] - [[package]] name = "chrono" version = "0.4.6" @@ -3110,7 +3091,6 @@ dependencies = [ "backtrace", "bitflags", "byteorder", - "chalk-engine", "jobserver", "log", "measureme", @@ -4144,7 +4124,6 @@ checksum = "b725dadae9fabc488df69a287f5a99c5eaf5d10853842a8a3dfac52476f544ee" name = "rustc_traits" version = "0.0.0" dependencies = [ - "chalk-engine", "log", "rustc", "rustc_ast", diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml index bac2540ab45..9d6e05130e1 100644 --- a/src/librustc/Cargo.toml +++ b/src/librustc/Cargo.toml @@ -33,7 +33,6 @@ rustc_span = { path = "../librustc_span" } backtrace = "0.3.40" parking_lot = "0.9" byteorder = { version = "1.3" } -chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } measureme = "0.7.1" rustc_session = { path = "../librustc_session" } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b3315cc3701..9277f5a380b 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -1130,16 +1130,6 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value.value } } - query evaluate_goal( - goal: traits::ChalkCanonicalGoal<'tcx> - ) -> Result< - &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, - NoSolution - > { - no_force - desc { "evaluating trait selection obligation `{}`", goal.value.goal } - } - /// Do not call this query directly: part of the `Eq` type-op query type_op_ascribe_user_type( goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 1a4ea66a5f1..4e02a1744ff 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -7,9 +7,7 @@ pub mod select; pub mod specialization_graph; mod structural_impls; -use crate::infer::canonical::Canonical; use crate::mir::interpret::ErrorHandled; -use crate::ty::fold::{TypeFolder, TypeVisitor}; use crate::ty::subst::SubstsRef; use crate::ty::{self, AdtKind, List, Ty, TyCtxt}; @@ -25,8 +23,6 @@ use std::rc::Rc; pub use self::select::{EvaluationCache, EvaluationResult, OverflowError, SelectionCache}; -pub type ChalkCanonicalGoal<'tcx> = Canonical<'tcx, InEnvironment<'tcx, ty::Predicate<'tcx>>>; - pub use self::ObligationCauseCode::*; pub use self::SelectionError::*; pub use self::Vtable::*; @@ -715,45 +711,6 @@ pub struct VtableTraitAliasData<'tcx, N> { pub nested: Vec, } -pub trait ExClauseFold<'tcx> -where - Self: chalk_engine::context::Context + Clone, -{ - fn fold_ex_clause_with>( - ex_clause: &chalk_engine::ExClause, - folder: &mut F, - ) -> chalk_engine::ExClause; - - fn visit_ex_clause_with>( - ex_clause: &chalk_engine::ExClause, - visitor: &mut V, - ) -> bool; -} - -pub trait ChalkContextLift<'tcx> -where - Self: chalk_engine::context::Context + Clone, -{ - type LiftedExClause: Debug + 'tcx; - type LiftedDelayedLiteral: Debug + 'tcx; - type LiftedLiteral: Debug + 'tcx; - - fn lift_ex_clause_to_tcx( - ex_clause: &chalk_engine::ExClause, - tcx: TyCtxt<'tcx>, - ) -> Option; - - fn lift_delayed_literal_to_tcx( - ex_clause: &chalk_engine::DelayedLiteral, - tcx: TyCtxt<'tcx>, - ) -> Option; - - fn lift_literal_to_tcx( - ex_clause: &chalk_engine::Literal, - tcx: TyCtxt<'tcx>, - ) -> Option; -} - #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 48ed29f2bb3..90b2134af12 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -595,42 +595,6 @@ impl<'a, 'tcx, G: Lift<'tcx>> Lift<'tcx> for traits::InEnvironment<'a, G> { } } -impl<'tcx, C> Lift<'tcx> for chalk_engine::ExClause -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedExClause; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - ::lift_ex_clause_to_tcx(self, tcx) - } -} - -impl<'tcx, C> Lift<'tcx> for chalk_engine::DelayedLiteral -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedDelayedLiteral; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - ::lift_delayed_literal_to_tcx(self, tcx) - } -} - -impl<'tcx, C> Lift<'tcx> for chalk_engine::Literal -where - C: chalk_engine::context::Context + Clone, - C: traits::ChalkContextLift<'tcx>, -{ - type Lifted = C::LiftedLiteral; - - fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - ::lift_literal_to_tcx(self, tcx) - } -} - /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. @@ -674,39 +638,3 @@ impl<'tcx> TypeFoldable<'tcx> for traits::Clauses<'tcx> { self.iter().any(|t| t.visit_with(visitor)) } } - -impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::ExClause -where - C: traits::ExClauseFold<'tcx>, - C::Substitution: Clone, - C::RegionConstraint: Clone, -{ - fn super_fold_with>(&self, folder: &mut F) -> Self { - ::fold_ex_clause_with(self, folder) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - ::visit_ex_clause_with(self, visitor) - } -} - -EnumTypeFoldableImpl! { - impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::DelayedLiteral { - (chalk_engine::DelayedLiteral::CannotProve)(a), - (chalk_engine::DelayedLiteral::Negative)(a), - (chalk_engine::DelayedLiteral::Positive)(a, b), - } where - C: chalk_engine::context::Context> + Clone, -} - -EnumTypeFoldableImpl! { - impl<'tcx, C> TypeFoldable<'tcx> for chalk_engine::Literal { - (chalk_engine::Literal::Negative)(a), - (chalk_engine::Literal::Positive)(a), - } where - C: chalk_engine::context::Context> + Clone, -} - -CloneTypeFoldableAndLiftImpls! { - chalk_engine::TableIndex, -} diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index 26f855b177e..4d3f25290e1 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -357,10 +357,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { // `TyVar(vid)` is unresolved, track its universe index in the canonicalized // result. Err(mut ui) => { - if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk { - // FIXME: perf problem described in #55921. - ui = ty::UniverseIndex::ROOT; - } + // FIXME: perf problem described in #55921. + ui = ty::UniverseIndex::ROOT; self.canonicalize_ty_var( CanonicalVarInfo { kind: CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)), @@ -447,10 +445,8 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { // `ConstVar(vid)` is unresolved, track its universe index in the // canonicalized result Err(mut ui) => { - if !self.infcx.unwrap().tcx.sess.opts.debugging_opts.chalk { - // FIXME: perf problem described in #55921. - ui = ty::UniverseIndex::ROOT; - } + // FIXME: perf problem described in #55921. + ui = ty::UniverseIndex::ROOT; return self.canonicalize_const_var( CanonicalVarInfo { kind: CanonicalVarKind::Const(ui) }, ct, diff --git a/src/librustc_infer/traits/chalk_fulfill.rs b/src/librustc_infer/traits/chalk_fulfill.rs deleted file mode 100644 index 82fa683a290..00000000000 --- a/src/librustc_infer/traits/chalk_fulfill.rs +++ /dev/null @@ -1,159 +0,0 @@ -use crate::infer::canonical::OriginalQueryValues; -use crate::infer::InferCtxt; -use crate::traits::query::NoSolution; -use crate::traits::{ - Environment, FulfillmentError, FulfillmentErrorCode, InEnvironment, ObligationCause, - PredicateObligation, SelectionError, TraitEngine, -}; -use rustc::ty::{self, Ty}; -use rustc_data_structures::fx::FxHashSet; - -pub use rustc::traits::ChalkCanonicalGoal as CanonicalGoal; - -pub struct FulfillmentContext<'tcx> { - obligations: FxHashSet>>, -} - -impl FulfillmentContext<'tcx> { - crate fn new() -> Self { - FulfillmentContext { obligations: FxHashSet::default() } - } -} - -fn in_environment( - infcx: &InferCtxt<'_, 'tcx>, - obligation: PredicateObligation<'tcx>, -) -> InEnvironment<'tcx, PredicateObligation<'tcx>> { - assert!(!infcx.is_in_snapshot()); - let obligation = infcx.resolve_vars_if_possible(&obligation); - - let environment = match obligation.param_env.def_id { - Some(def_id) => infcx.tcx.environment(def_id), - None if obligation.param_env.caller_bounds.is_empty() => { - Environment { clauses: ty::List::empty() } - } - _ => bug!("non-empty `ParamEnv` with no def-id"), - }; - - InEnvironment { environment, goal: obligation } -} - -impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { - fn normalize_projection_type( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - _param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - _cause: ObligationCause<'tcx>, - ) -> Ty<'tcx> { - infcx.tcx.mk_ty(ty::Projection(projection_ty)) - } - - fn register_predicate_obligation( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - obligation: PredicateObligation<'tcx>, - ) { - self.obligations.insert(in_environment(infcx, obligation)); - } - - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - self.select_where_possible(infcx)?; - - if self.obligations.is_empty() { - Ok(()) - } else { - let errors = self - .obligations - .iter() - .map(|obligation| FulfillmentError { - obligation: obligation.goal.clone(), - code: FulfillmentErrorCode::CodeAmbiguity, - points_at_arg_span: false, - }) - .collect(); - Err(errors) - } - } - - fn select_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>> { - let mut errors = Vec::new(); - let mut next_round = FxHashSet::default(); - let mut making_progress; - - loop { - making_progress = false; - - // We iterate over all obligations, and record if we are able - // to unambiguously prove at least one obligation. - for obligation in self.obligations.drain() { - let mut orig_values = OriginalQueryValues::default(); - let canonical_goal = infcx.canonicalize_query( - &InEnvironment { - environment: obligation.environment, - goal: obligation.goal.predicate, - }, - &mut orig_values, - ); - - match infcx.tcx.evaluate_goal(canonical_goal) { - Ok(response) => { - if response.is_proven() { - making_progress = true; - - match infcx.instantiate_query_response_and_region_obligations( - &obligation.goal.cause, - obligation.goal.param_env, - &orig_values, - &response, - ) { - Ok(infer_ok) => next_round.extend( - infer_ok - .obligations - .into_iter() - .map(|obligation| in_environment(infcx, obligation)), - ), - - Err(_err) => errors.push(FulfillmentError { - obligation: obligation.goal, - code: FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - ), - points_at_arg_span: false, - }), - } - } else { - // Ambiguous: retry at next round. - next_round.insert(obligation); - } - } - - Err(NoSolution) => errors.push(FulfillmentError { - obligation: obligation.goal, - code: FulfillmentErrorCode::CodeSelectionError( - SelectionError::Unimplemented, - ), - points_at_arg_span: false, - }), - } - } - next_round = std::mem::replace(&mut self.obligations, next_round); - - if !making_progress { - break; - } - } - - if errors.is_empty() { Ok(()) } else { Err(errors) } - } - - fn pending_obligations(&self) -> Vec> { - self.obligations.iter().map(|obligation| obligation.goal.clone()).collect() - } -} diff --git a/src/librustc_infer/traits/engine.rs b/src/librustc_infer/traits/engine.rs index ba144379616..e23810dd161 100644 --- a/src/librustc_infer/traits/engine.rs +++ b/src/librustc_infer/traits/engine.rs @@ -3,7 +3,7 @@ use crate::traits::Obligation; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_hir::def_id::DefId; -use super::{ChalkFulfillmentContext, FulfillmentContext, FulfillmentError}; +use super::{FulfillmentContext, FulfillmentError}; use super::{ObligationCause, PredicateObligation}; pub trait TraitEngine<'tcx>: 'tcx { @@ -78,11 +78,7 @@ impl> TraitEngineExt<'tcx> for T { } impl dyn TraitEngine<'tcx> { - pub fn new(tcx: TyCtxt<'tcx>) -> Box { - if tcx.sess.opts.debugging_opts.chalk { - Box::new(ChalkFulfillmentContext::new()) - } else { - Box::new(FulfillmentContext::new()) - } + pub fn new(_tcx: TyCtxt<'tcx>) -> Box { + Box::new(FulfillmentContext::new()) } } diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 7a84a5f5c72..63c3f827c2e 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -812,21 +812,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } ty::Predicate::WellFormed(ty) => { - if !self.tcx.sess.opts.debugging_opts.chalk { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } else { - // FIXME: we'll need a better message which takes into account - // which bounds actually failed to hold. - self.tcx.sess.struct_span_err( - span, - &format!("the type `{}` is not well-formed (chalk)", ty), - ) - } + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); } ty::Predicate::ConstEvaluatable(..) => { diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 2815a77882a..61702d74f1a 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -4,7 +4,6 @@ #[allow(dead_code)] pub mod auto_trait; -mod chalk_fulfill; pub mod codegen; mod coherence; mod engine; @@ -74,10 +73,6 @@ pub use self::util::{ supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, }; -pub use self::chalk_fulfill::{ - CanonicalGoal as ChalkCanonicalGoal, FulfillmentContext as ChalkFulfillmentContext, -}; - pub use rustc::traits::*; /// Whether to skip the leak check, as part of a future compatibility warning step. diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index a79cbfd5e17..4c312c9fce2 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2917,15 +2917,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { trait_ref, )?); - // FIXME: Chalk - - if !self.tcx().sess.opts.debugging_opts.chalk { - obligations.push(Obligation::new( - obligation.cause.clone(), - obligation.param_env, - ty::Predicate::ClosureKind(closure_def_id, substs, kind), - )); - } + obligations.push(Obligation::new( + obligation.cause.clone(), + obligation.param_env, + ty::Predicate::ClosureKind(closure_def_id, substs, kind), + )); Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations }) } diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index d3163fa3564..a1ecf4e8528 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -922,8 +922,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, "tell the linker to strip debuginfo when building without debuginfo enabled."), share_generics: Option = (None, parse_opt_bool, [TRACKED], "make the current crate share its generic instantiations"), - chalk: bool = (false, parse_bool, [TRACKED], - "enable the experimental Chalk-based trait solving engine"), no_parallel_llvm: bool = (false, parse_bool, [UNTRACKED], "don't run LLVM in parallel (while keeping codegen-units and ThinLTO)"), no_leak_check: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc_traits/Cargo.toml b/src/librustc_traits/Cargo.toml index 3fdbb4e6805..0dc3ad29833 100644 --- a/src/librustc_traits/Cargo.toml +++ b/src/librustc_traits/Cargo.toml @@ -17,6 +17,5 @@ rustc_macros = { path = "../librustc_macros" } rustc_target = { path = "../librustc_target" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } -chalk-engine = { version = "0.9.0", default-features=false } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_traits/chalk_context/mod.rs b/src/librustc_traits/chalk_context/mod.rs deleted file mode 100644 index 240a93f0900..00000000000 --- a/src/librustc_traits/chalk_context/mod.rs +++ /dev/null @@ -1,638 +0,0 @@ -mod program_clauses; -mod resolvent_ops; -mod unify; - -use chalk_engine::fallible::Fallible; -use chalk_engine::forest::Forest; -use chalk_engine::{context, hh::HhGoal, DelayedLiteral, ExClause, Literal}; -use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; -use rustc::ty::query::Providers; -use rustc::ty::subst::{GenericArg, GenericArgKind}; -use rustc::ty::{self, TyCtxt}; -use rustc_infer::infer::canonical::{ - Canonical, CanonicalVarValues, Certainty, OriginalQueryValues, QueryRegionConstraints, - QueryResponse, -}; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime, TyCtxtInferExt}; -use rustc_infer::traits::{ - self, ChalkCanonicalGoal, ChalkContextLift, Clause, DomainGoal, Environment, ExClauseFold, - Goal, GoalKind, InEnvironment, QuantifierKind, -}; -use rustc_macros::{Lift, TypeFoldable}; -use rustc_span::DUMMY_SP; - -use std::fmt::{self, Debug}; -use std::marker::PhantomData; - -use self::unify::*; - -#[derive(Copy, Clone, Debug)] -crate struct ChalkArenas<'tcx> { - _phantom: PhantomData<&'tcx ()>, -} - -#[derive(Copy, Clone)] -crate struct ChalkContext<'tcx> { - _arenas: ChalkArenas<'tcx>, - tcx: TyCtxt<'tcx>, -} - -#[derive(Copy, Clone)] -crate struct ChalkInferenceContext<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, -} - -#[derive(Copy, Clone, Debug)] -crate struct UniverseMap; - -crate type RegionConstraint<'tcx> = ty::OutlivesPredicate, ty::Region<'tcx>>; - -#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, Lift)] -crate struct ConstrainedSubst<'tcx> { - subst: CanonicalVarValues<'tcx>, - constraints: Vec>, -} - -impl context::Context for ChalkArenas<'tcx> { - type CanonicalExClause = Canonical<'tcx, ChalkExClause<'tcx>>; - - type CanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>; - - // u-canonicalization not yet implemented - type UCanonicalGoalInEnvironment = Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>; - - type CanonicalConstrainedSubst = Canonical<'tcx, ConstrainedSubst<'tcx>>; - - // u-canonicalization not yet implemented - type UniverseMap = UniverseMap; - - type Solution = Canonical<'tcx, QueryResponse<'tcx, ()>>; - - type InferenceNormalizedSubst = CanonicalVarValues<'tcx>; - - type GoalInEnvironment = InEnvironment<'tcx, Goal<'tcx>>; - - type RegionConstraint = RegionConstraint<'tcx>; - - type Substitution = CanonicalVarValues<'tcx>; - - type Environment = Environment<'tcx>; - - type Goal = Goal<'tcx>; - - type DomainGoal = DomainGoal<'tcx>; - - type BindersGoal = ty::Binder>; - - type Parameter = GenericArg<'tcx>; - - type ProgramClause = Clause<'tcx>; - - type ProgramClauses = Vec>; - - type UnificationResult = UnificationResult<'tcx>; - - type Variance = ty::Variance; - - fn goal_in_environment( - env: &Environment<'tcx>, - goal: Goal<'tcx>, - ) -> InEnvironment<'tcx, Goal<'tcx>> { - env.with(goal) - } -} - -impl context::AggregateOps> for ChalkContext<'tcx> { - fn make_solution( - &self, - root_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - mut simplified_answers: impl context::AnswerStream>, - ) -> Option>> { - use chalk_engine::SimplifiedAnswer; - - debug!("make_solution(root_goal = {:?})", root_goal); - - if simplified_answers.peek_answer().is_none() { - return None; - } - - let SimplifiedAnswer { subst: constrained_subst, ambiguous } = - simplified_answers.next_answer().unwrap(); - - debug!("make_solution: ambiguous flag = {}", ambiguous); - - let ambiguous = simplified_answers.peek_answer().is_some() || ambiguous; - - let solution = constrained_subst.unchecked_map(|cs| match ambiguous { - true => QueryResponse { - var_values: cs.subst.make_identity(self.tcx), - region_constraints: QueryRegionConstraints::default(), - certainty: Certainty::Ambiguous, - value: (), - }, - - false => QueryResponse { - var_values: cs.subst, - region_constraints: QueryRegionConstraints::default(), - - // FIXME: restore this later once we get better at handling regions - // region_constraints: cs.constraints - // .into_iter() - // .map(|c| ty::Binder::bind(c)) - // .collect(), - certainty: Certainty::Proven, - value: (), - }, - }); - - debug!("make_solution: solution = {:?}", solution); - - Some(solution) - } -} - -impl context::ContextOps> for ChalkContext<'tcx> { - /// Returns `true` if this is a coinductive goal: basically proving that an auto trait - /// is implemented or proving that a trait reference is well-formed. - fn is_coinductive(&self, goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> bool { - use rustc::traits::{WellFormed, WhereClause}; - - let mut goal = goal.value.goal; - loop { - match goal { - GoalKind::DomainGoal(domain_goal) => match domain_goal { - DomainGoal::WellFormed(WellFormed::Trait(..)) => return true, - DomainGoal::Holds(WhereClause::Implemented(trait_predicate)) => { - return self.tcx.trait_is_auto(trait_predicate.def_id()); - } - _ => return false, - }, - - GoalKind::Quantified(_, bound_goal) => goal = *bound_goal.skip_binder(), - _ => return false, - } - } - } - - /// Creates an inference table for processing a new goal and instantiate that goal - /// in that context, returning "all the pieces". - /// - /// More specifically: given a u-canonical goal `arg`, creates a - /// new inference table `T` and populates it with the universes - /// found in `arg`. Then, creates a substitution `S` that maps - /// each bound variable in `arg` to a fresh inference variable - /// from T. Returns: - /// - /// - the table `T`, - /// - the substitution `S`, - /// - the environment and goal found by substitution `S` into `arg`. - fn instantiate_ucanonical_goal( - &self, - arg: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - op: impl context::WithInstantiatedUCanonicalGoal, Output = R>, - ) -> R { - self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, arg, |ref infcx, arg, subst| { - let chalk_infcx = &mut ChalkInferenceContext { infcx }; - op.with(chalk_infcx, subst, arg.environment, arg.goal) - }) - } - - fn instantiate_ex_clause( - &self, - _num_universes: usize, - arg: &Canonical<'tcx, ChalkExClause<'tcx>>, - op: impl context::WithInstantiatedExClause, Output = R>, - ) -> R { - self.tcx.infer_ctxt().enter_with_canonical(DUMMY_SP, &arg.upcast(), |ref infcx, arg, _| { - let chalk_infcx = &mut ChalkInferenceContext { infcx }; - op.with(chalk_infcx, arg) - }) - } - - /// Returns `true` if this solution has no region constraints. - fn empty_constraints(ccs: &Canonical<'tcx, ConstrainedSubst<'tcx>>) -> bool { - ccs.value.constraints.is_empty() - } - - fn inference_normalized_subst_from_ex_clause( - canon_ex_clause: &'a Canonical<'tcx, ChalkExClause<'tcx>>, - ) -> &'a CanonicalVarValues<'tcx> { - &canon_ex_clause.value.subst - } - - fn inference_normalized_subst_from_subst( - canon_subst: &'a Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> &'a CanonicalVarValues<'tcx> { - &canon_subst.value.subst - } - - fn canonical( - u_canon: &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> &'a Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - u_canon - } - - fn is_trivial_substitution( - u_canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - canonical_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> bool { - let subst = &canonical_subst.value.subst; - assert_eq!(u_canon.variables.len(), subst.var_values.len()); - subst.var_values.iter_enumerated().all(|(cvar, kind)| match kind.unpack() { - GenericArgKind::Lifetime(r) => match r { - &ty::ReLateBound(debruijn, br) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == br.assert_bound_var() - } - _ => false, - }, - GenericArgKind::Type(ty) => match ty.kind { - ty::Bound(debruijn, bound_ty) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == bound_ty.var - } - _ => false, - }, - GenericArgKind::Const(ct) => match ct.val { - ty::ConstKind::Bound(debruijn, bound_ct) => { - debug_assert_eq!(debruijn, ty::INNERMOST); - cvar == bound_ct - } - _ => false, - }, - }) - } - - fn num_universes(canon: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>) -> usize { - canon.max_universe.index() + 1 - } - - /// Convert a goal G *from* the canonical universes *into* our - /// local universes. This will yield a goal G' that is the same - /// but for the universes of universally quantified names. - fn map_goal_from_canonical( - _map: &UniverseMap, - value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - *value // FIXME universe maps not implemented yet - } - - fn map_subst_from_canonical( - _map: &UniverseMap, - value: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - value.clone() // FIXME universe maps not implemented yet - } -} - -impl context::InferenceTable, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn into_goal(&self, domain_goal: DomainGoal<'tcx>) -> Goal<'tcx> { - self.infcx.tcx.mk_goal(GoalKind::DomainGoal(domain_goal)) - } - - fn cannot_prove(&self) -> Goal<'tcx> { - self.infcx.tcx.mk_goal(GoalKind::CannotProve) - } - - fn into_hh_goal(&mut self, goal: Goal<'tcx>) -> ChalkHhGoal<'tcx> { - match *goal { - GoalKind::Implies(hypotheses, goal) => { - HhGoal::Implies(hypotheses.iter().cloned().collect(), goal) - } - GoalKind::And(left, right) => HhGoal::And(left, right), - GoalKind::Not(subgoal) => HhGoal::Not(subgoal), - GoalKind::DomainGoal(d) => HhGoal::DomainGoal(d), - GoalKind::Quantified(QuantifierKind::Universal, binder) => HhGoal::ForAll(binder), - GoalKind::Quantified(QuantifierKind::Existential, binder) => HhGoal::Exists(binder), - GoalKind::Subtype(a, b) => HhGoal::Unify(ty::Variance::Covariant, a.into(), b.into()), - GoalKind::CannotProve => HhGoal::CannotProve, - } - } - - fn add_clauses( - &mut self, - env: &Environment<'tcx>, - clauses: Vec>, - ) -> Environment<'tcx> { - Environment { - clauses: self - .infcx - .tcx - .mk_clauses(env.clauses.iter().cloned().chain(clauses.into_iter())), - } - } -} - -impl context::TruncateOps, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn truncate_goal( - &mut self, - _subgoal: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Option>> { - None // FIXME we should truncate at some point! - } - - fn truncate_answer( - &mut self, - _subst: &CanonicalVarValues<'tcx>, - ) -> Option> { - None // FIXME we should truncate at some point! - } -} - -impl context::UnificationOps, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn program_clauses( - &self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - ) -> Vec> { - self.program_clauses_impl(environment, goal) - } - - fn instantiate_binders_universally(&mut self, arg: &ty::Binder>) -> Goal<'tcx> { - self.infcx.replace_bound_vars_with_placeholders(arg).0 - } - - fn instantiate_binders_existentially(&mut self, arg: &ty::Binder>) -> Goal<'tcx> { - self.infcx - .replace_bound_vars_with_fresh_vars( - DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, - arg, - ) - .0 - } - - fn debug_ex_clause(&mut self, value: &'v ChalkExClause<'tcx>) -> Box { - let string = format!("{:?}", self.infcx.resolve_vars_if_possible(value)); - Box::new(string) - } - - fn canonicalize_goal( - &mut self, - value: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>> { - let mut _orig_values = OriginalQueryValues::default(); - self.infcx.canonicalize_query(value, &mut _orig_values) - } - - fn canonicalize_ex_clause( - &mut self, - value: &ChalkExClause<'tcx>, - ) -> Canonical<'tcx, ChalkExClause<'tcx>> { - self.infcx.canonicalize_response(value) - } - - fn canonicalize_constrained_subst( - &mut self, - subst: CanonicalVarValues<'tcx>, - constraints: Vec>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - self.infcx.canonicalize_response(&ConstrainedSubst { subst, constraints }) - } - - fn u_canonicalize_goal( - &mut self, - value: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - ) -> (Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, UniverseMap) { - (*value, UniverseMap) - } - - fn invert_goal( - &mut self, - _value: &InEnvironment<'tcx, Goal<'tcx>>, - ) -> Option>> { - panic!("goal inversion not yet implemented") - } - - fn unify_parameters( - &mut self, - environment: &Environment<'tcx>, - variance: ty::Variance, - a: &GenericArg<'tcx>, - b: &GenericArg<'tcx>, - ) -> Fallible> { - self.infcx.commit_if_ok(|_| { - unify(self.infcx, *environment, variance, a, b) - .map_err(|_| chalk_engine::fallible::NoSolution) - }) - } - - fn sink_answer_subset( - &self, - value: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Canonical<'tcx, ConstrainedSubst<'tcx>> { - value.clone() - } - - fn lift_delayed_literal( - &self, - value: DelayedLiteral>, - ) -> DelayedLiteral> { - match self.infcx.tcx.lift(&value) { - Some(literal) => literal, - None => bug!("cannot lift {:?}", value), - } - } - - fn into_ex_clause( - &mut self, - result: UnificationResult<'tcx>, - ex_clause: &mut ChalkExClause<'tcx>, - ) { - into_ex_clause(result, ex_clause); - } -} - -crate fn into_ex_clause(result: UnificationResult<'tcx>, ex_clause: &mut ChalkExClause<'tcx>) { - ex_clause.subgoals.extend(result.goals.into_iter().map(Literal::Positive)); - - // FIXME: restore this later once we get better at handling regions - let _ = result.constraints.len(); // trick `-D dead-code` - // ex_clause.constraints.extend(result.constraints); -} - -type ChalkHhGoal<'tcx> = HhGoal>; - -type ChalkExClause<'tcx> = ExClause>; - -impl Debug for ChalkContext<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ChalkContext") - } -} - -impl Debug for ChalkInferenceContext<'cx, 'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "ChalkInferenceContext") - } -} - -impl ChalkContextLift<'tcx> for ChalkArenas<'a> { - type LiftedExClause = ChalkExClause<'tcx>; - type LiftedDelayedLiteral = DelayedLiteral>; - type LiftedLiteral = Literal>; - - fn lift_ex_clause_to_tcx( - ex_clause: &ChalkExClause<'a>, - tcx: TyCtxt<'tcx>, - ) -> Option { - Some(ChalkExClause { - subst: tcx.lift(&ex_clause.subst)?, - delayed_literals: tcx.lift(&ex_clause.delayed_literals)?, - constraints: tcx.lift(&ex_clause.constraints)?, - subgoals: tcx.lift(&ex_clause.subgoals)?, - }) - } - - fn lift_delayed_literal_to_tcx( - literal: &DelayedLiteral>, - tcx: TyCtxt<'tcx>, - ) -> Option { - Some(match literal { - DelayedLiteral::CannotProve(()) => DelayedLiteral::CannotProve(()), - DelayedLiteral::Negative(index) => DelayedLiteral::Negative(*index), - DelayedLiteral::Positive(index, subst) => { - DelayedLiteral::Positive(*index, tcx.lift(subst)?) - } - }) - } - - fn lift_literal_to_tcx( - literal: &Literal>, - tcx: TyCtxt<'tcx>, - ) -> Option { - Some(match literal { - Literal::Negative(goal) => Literal::Negative(tcx.lift(goal)?), - Literal::Positive(goal) => Literal::Positive(tcx.lift(goal)?), - }) - } -} - -impl ExClauseFold<'tcx> for ChalkArenas<'tcx> { - fn fold_ex_clause_with>( - ex_clause: &ChalkExClause<'tcx>, - folder: &mut F, - ) -> ChalkExClause<'tcx> { - ExClause { - subst: ex_clause.subst.fold_with(folder), - delayed_literals: ex_clause.delayed_literals.fold_with(folder), - constraints: ex_clause.constraints.fold_with(folder), - subgoals: ex_clause.subgoals.fold_with(folder), - } - } - - fn visit_ex_clause_with>( - ex_clause: &ExClause, - visitor: &mut V, - ) -> bool { - let ExClause { subst, delayed_literals, constraints, subgoals } = ex_clause; - subst.visit_with(visitor) - || delayed_literals.visit_with(visitor) - || constraints.visit_with(visitor) - || subgoals.visit_with(visitor) - } -} - -trait Upcast<'tcx>: 'tcx { - type Upcasted: 'tcx; - - fn upcast(&self) -> Self::Upcasted; -} - -impl<'tcx> Upcast<'tcx> for DelayedLiteral> { - type Upcasted = DelayedLiteral>; - - fn upcast(&self) -> Self::Upcasted { - match self { - &DelayedLiteral::CannotProve(..) => DelayedLiteral::CannotProve(()), - &DelayedLiteral::Negative(index) => DelayedLiteral::Negative(index), - DelayedLiteral::Positive(index, subst) => { - DelayedLiteral::Positive(*index, subst.clone()) - } - } - } -} - -impl<'tcx> Upcast<'tcx> for Literal> { - type Upcasted = Literal>; - - fn upcast(&self) -> Self::Upcasted { - match self { - &Literal::Negative(goal) => Literal::Negative(goal), - &Literal::Positive(goal) => Literal::Positive(goal), - } - } -} - -impl<'tcx> Upcast<'tcx> for ExClause> { - type Upcasted = ExClause>; - - fn upcast(&self) -> Self::Upcasted { - ExClause { - subst: self.subst.clone(), - delayed_literals: self.delayed_literals.iter().map(|l| l.upcast()).collect(), - constraints: self.constraints.clone(), - subgoals: self.subgoals.iter().map(|g| g.upcast()).collect(), - } - } -} - -impl<'tcx, T> Upcast<'tcx> for Canonical<'tcx, T> -where - T: Upcast<'tcx>, -{ - type Upcasted = Canonical<'tcx, T::Upcasted>; - - fn upcast(&self) -> Self::Upcasted { - Canonical { - max_universe: self.max_universe, - value: self.value.upcast(), - variables: self.variables, - } - } -} - -crate fn provide(p: &mut Providers<'_>) { - *p = Providers { evaluate_goal, ..*p }; -} - -crate fn evaluate_goal<'tcx>( - tcx: TyCtxt<'tcx>, - goal: ChalkCanonicalGoal<'tcx>, -) -> Result<&'tcx Canonical<'tcx, QueryResponse<'tcx, ()>>, traits::query::NoSolution> { - use crate::lowering::Lower; - use rustc::traits::WellFormed; - - let goal = goal.unchecked_map(|goal| InEnvironment { - environment: goal.environment, - goal: match goal.goal { - ty::Predicate::WellFormed(ty) => { - tcx.mk_goal(GoalKind::DomainGoal(DomainGoal::WellFormed(WellFormed::Ty(ty)))) - } - - ty::Predicate::Subtype(predicate) => tcx.mk_goal(GoalKind::Quantified( - QuantifierKind::Universal, - predicate.map_bound(|pred| tcx.mk_goal(GoalKind::Subtype(pred.a, pred.b))), - )), - - other => tcx.mk_goal(GoalKind::from_poly_domain_goal(other.lower(), tcx)), - }, - }); - - debug!("evaluate_goal(goal = {:?})", goal); - - let context = ChalkContext { _arenas: ChalkArenas { _phantom: PhantomData }, tcx }; - - let mut forest = Forest::new(context); - let solution = forest.solve(&goal); - - debug!("evaluate_goal: solution = {:?}", solution); - - solution.map(|ok| Ok(&*tcx.arena.alloc(ok))).unwrap_or(Err(traits::query::NoSolution)) -} diff --git a/src/librustc_traits/chalk_context/program_clauses/builtin.rs b/src/librustc_traits/chalk_context/program_clauses/builtin.rs deleted file mode 100644 index 7512cbbd882..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/builtin.rs +++ /dev/null @@ -1,316 +0,0 @@ -use crate::generic_types; -use crate::lowering::Lower; -use rustc::traits::{Clause, GoalKind, ProgramClause, ProgramClauseCategory}; -use rustc::ty::subst::{GenericArg, InternalSubsts, Subst}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; - -/// Returns a predicate of the form -/// `Implemented(ty: Trait) :- Implemented(nested: Trait)...` -/// where `Trait` is specified by `trait_def_id`. -fn builtin_impl_clause( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - nested: &[GenericArg<'tcx>], - trait_def_id: DefId, -) -> ProgramClause<'tcx> { - ProgramClause { - goal: ty::TraitPredicate { - trait_ref: ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, &[]) }, - } - .lower(), - hypotheses: tcx.mk_goals( - nested - .iter() - .cloned() - .map(|nested_ty| ty::TraitRef { - def_id: trait_def_id, - substs: tcx.mk_substs_trait(nested_ty.expect_ty(), &[]), - }) - .map(|trait_ref| ty::TraitPredicate { trait_ref }) - .map(|pred| GoalKind::DomainGoal(pred.lower())) - .map(|goal_kind| tcx.mk_goal(goal_kind)), - ), - category: ProgramClauseCategory::Other, - } -} - -crate fn assemble_builtin_unsize_impls<'tcx>( - tcx: TyCtxt<'tcx>, - unsize_def_id: DefId, - source: Ty<'tcx>, - target: Ty<'tcx>, - clauses: &mut Vec>, -) { - match (&source.kind, &target.kind) { - (ty::Dynamic(data_a, ..), ty::Dynamic(data_b, ..)) => { - if data_a.principal_def_id() != data_b.principal_def_id() - || data_b.auto_traits().any(|b| data_a.auto_traits().all(|a| a != b)) - { - return; - } - - // FIXME: rules for trait upcast - } - - (_, &ty::Dynamic(..)) => { - // FIXME: basically, we should have something like: - // ``` - // forall { - // Implemented(T: Unsize< for<...> dyn Trait<...> >) :- - // for<...> Implemented(T: Trait<...>). - // } - // ``` - // The question is: how to correctly handle the higher-ranked - // `for<...>` binder in order to have a generic rule? - // (Having generic rules is useful for caching, as we may be able - // to turn this function and others into tcx queries later on). - } - - (ty::Array(_, length), ty::Slice(_)) => { - let ty_param = generic_types::bound(tcx, 0); - let array_ty = tcx.mk_ty(ty::Array(ty_param, length)); - let slice_ty = tcx.mk_ty(ty::Slice(ty_param)); - - // `forall { Implemented([T; N]: Unsize<[T]>). }` - let clause = ProgramClause { - goal: ty::TraitPredicate { - trait_ref: ty::TraitRef { - def_id: unsize_def_id, - substs: tcx.mk_substs_trait(array_ty, &[slice_ty.into()]), - }, - } - .lower(), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::Other, - }; - - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - } - - (ty::Infer(ty::TyVar(_)), _) | (_, ty::Infer(ty::TyVar(_))) => { - // FIXME: ambiguous - } - - (ty::Adt(def_id_a, ..), ty::Adt(def_id_b, ..)) => { - if def_id_a != def_id_b { - return; - } - - // FIXME: rules for struct unsizing - } - - (&ty::Tuple(tys_a), &ty::Tuple(tys_b)) => { - if tys_a.len() != tys_b.len() { - return; - } - - // FIXME: rules for tuple unsizing - } - - _ => (), - } -} - -crate fn assemble_builtin_sized_impls<'tcx>( - tcx: TyCtxt<'tcx>, - sized_def_id: DefId, - ty: Ty<'tcx>, - clauses: &mut Vec>, -) { - let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| { - let clause = builtin_impl_clause(tcx, ty, nested, sized_def_id); - // Bind innermost bound vars that may exist in `ty` and `nested`. - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - }; - - match &ty.kind { - // Non parametric primitive types. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Infer(ty::IntVar(_)) - | ty::Infer(ty::FloatVar(_)) - | ty::Error - | ty::Never => push_builtin_impl(ty, &[]), - - // These ones are always `Sized`. - &ty::Array(_, length) => { - push_builtin_impl(tcx.mk_ty(ty::Array(generic_types::bound(tcx, 0), length)), &[]); - } - ty::RawPtr(ptr) => { - push_builtin_impl(generic_types::raw_ptr(tcx, ptr.mutbl), &[]); - } - &ty::Ref(_, _, mutbl) => { - push_builtin_impl(generic_types::ref_ty(tcx, mutbl), &[]); - } - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - let fn_ptr = generic_types::fn_ptr( - tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ); - push_builtin_impl(fn_ptr, &[]); - } - &ty::FnDef(def_id, ..) => { - push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]); - } - &ty::Closure(def_id, ..) => { - push_builtin_impl(generic_types::closure(tcx, def_id), &[]); - } - &ty::Generator(def_id, ..) => { - push_builtin_impl(generic_types::generator(tcx, def_id), &[]); - } - - // `Sized` if the last type is `Sized` (because else we will get a WF error anyway). - &ty::Tuple(type_list) => { - let type_list = generic_types::type_list(tcx, type_list.len()); - push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &type_list); - } - - // Struct def - ty::Adt(adt_def, _) => { - let substs = InternalSubsts::bound_vars_for_item(tcx, adt_def.did); - let adt = tcx.mk_ty(ty::Adt(adt_def, substs)); - let sized_constraint = adt_def - .sized_constraint(tcx) - .iter() - .map(|ty| GenericArg::from(ty.subst(tcx, substs))) - .collect::>(); - push_builtin_impl(adt, &sized_constraint); - } - - // Artificially trigger an ambiguity by adding two possible types to - // unify against. - ty::Infer(ty::TyVar(_)) => { - push_builtin_impl(tcx.types.i32, &[]); - push_builtin_impl(tcx.types.f32, &[]); - } - - ty::Projection(_projection_ty) => { - // FIXME: add builtin impls from the associated type values found in - // trait impls of `projection_ty.trait_ref(tcx)`. - } - - // The `Sized` bound can only come from the environment. - ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) => (), - - // Definitely not `Sized`. - ty::Foreign(..) | ty::Str | ty::Slice(..) | ty::Dynamic(..) | ty::Opaque(..) => (), - - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::Infer(ty::FreshTy(_)) - | ty::Infer(ty::FreshIntTy(_)) - | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty), - } -} - -crate fn assemble_builtin_copy_clone_impls<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - ty: Ty<'tcx>, - clauses: &mut Vec>, -) { - let mut push_builtin_impl = |ty: Ty<'tcx>, nested: &[GenericArg<'tcx>]| { - let clause = builtin_impl_clause(tcx, ty, nested, trait_def_id); - // Bind innermost bound vars that may exist in `ty` and `nested`. - clauses.push(Clause::ForAll(ty::Binder::bind(clause))); - }; - - match &ty.kind { - // Implementations provided in libcore. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::RawPtr(..) - | ty::Never - | ty::Ref(_, _, hir::Mutability::Not) => (), - - // Non parametric primitive types. - ty::Infer(ty::IntVar(_)) | ty::Infer(ty::FloatVar(_)) | ty::Error => { - push_builtin_impl(ty, &[]) - } - - // These implement `Copy`/`Clone` if their element types do. - &ty::Array(_, length) => { - let element_ty = generic_types::bound(tcx, 0); - push_builtin_impl( - tcx.mk_ty(ty::Array(element_ty, length)), - &[GenericArg::from(element_ty)], - ); - } - &ty::Tuple(type_list) => { - let type_list = generic_types::type_list(tcx, type_list.len()); - push_builtin_impl(tcx.mk_ty(ty::Tuple(type_list)), &**type_list); - } - &ty::Closure(def_id, ..) => { - let closure_ty = generic_types::closure(tcx, def_id); - let upvar_tys: Vec<_> = match &closure_ty.kind { - ty::Closure(_, substs) => substs - .as_closure() - .upvar_tys(def_id, tcx) - .map(|ty| GenericArg::from(ty)) - .collect(), - _ => bug!(), - }; - push_builtin_impl(closure_ty, &upvar_tys); - } - - // These ones are always `Clone`. - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - let fn_ptr = generic_types::fn_ptr( - tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ); - push_builtin_impl(fn_ptr, &[]); - } - &ty::FnDef(def_id, ..) => { - push_builtin_impl(generic_types::fn_def(tcx, def_id), &[]); - } - - // These depend on whatever user-defined impls might exist. - ty::Adt(_, _) => (), - - // Artificially trigger an ambiguity by adding two possible types to - // unify against. - ty::Infer(ty::TyVar(_)) => { - push_builtin_impl(tcx.types.i32, &[]); - push_builtin_impl(tcx.types.f32, &[]); - } - - ty::Projection(_projection_ty) => { - // FIXME: add builtin impls from the associated type values found in - // trait impls of `projection_ty.trait_ref(tcx)`. - } - - // The `Copy`/`Clone` bound can only come from the environment. - ty::Param(..) | ty::Placeholder(..) | ty::UnnormalizedProjection(..) | ty::Opaque(..) => (), - - // Definitely not `Copy`/`Clone`. - ty::Dynamic(..) - | ty::Foreign(..) - | ty::Generator(..) - | ty::Str - | ty::Slice(..) - | ty::Ref(_, _, hir::Mutability::Mut) => (), - - ty::Bound(..) - | ty::GeneratorWitness(..) - | ty::Infer(ty::FreshTy(_)) - | ty::Infer(ty::FreshIntTy(_)) - | ty::Infer(ty::FreshFloatTy(_)) => bug!("unexpected type {:?}", ty), - } -} diff --git a/src/librustc_traits/chalk_context/program_clauses/mod.rs b/src/librustc_traits/chalk_context/program_clauses/mod.rs deleted file mode 100644 index 38a4a729648..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/mod.rs +++ /dev/null @@ -1,300 +0,0 @@ -mod builtin; -mod primitive; - -use super::ChalkInferenceContext; -use rustc::traits::{ - Clause, DomainGoal, Environment, FromEnv, ProgramClause, ProgramClauseCategory, WellFormed, -}; -use rustc::ty::{self, TyCtxt}; -use rustc_hir::def_id::DefId; -use std::iter; - -use self::builtin::*; -use self::primitive::*; - -fn assemble_clauses_from_impls<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - clauses: &mut Vec>, -) { - tcx.for_each_impl(trait_def_id, |impl_def_id| { - clauses.extend(tcx.program_clauses_for(impl_def_id).into_iter().cloned()); - }); -} - -fn assemble_clauses_from_assoc_ty_values<'tcx>( - tcx: TyCtxt<'tcx>, - trait_def_id: DefId, - clauses: &mut Vec>, -) { - tcx.for_each_impl(trait_def_id, |impl_def_id| { - for def_id in tcx.associated_item_def_ids(impl_def_id).iter() { - clauses.extend(tcx.program_clauses_for(*def_id).into_iter().cloned()); - } - }); -} - -impl ChalkInferenceContext<'cx, 'tcx> { - pub(super) fn program_clauses_impl( - &self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - ) -> Vec> { - use rustc::infer::canonical::OriginalQueryValues; - use rustc::traits::WhereClause::*; - - let goal = self.infcx.resolve_vars_if_possible(goal); - - debug!("program_clauses(goal = {:?})", goal); - - let mut clauses = match goal { - DomainGoal::Holds(Implemented(trait_predicate)) => { - // These come from: - // * implementations of the trait itself (rule `Implemented-From-Impl`) - // * the trait decl (rule `Implemented-From-Env`) - - let mut clauses = vec![]; - - assemble_clauses_from_impls(self.infcx.tcx, trait_predicate.def_id(), &mut clauses); - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().sized_trait() { - assemble_builtin_sized_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().unsize_trait() { - let source = trait_predicate.self_ty(); - let target = trait_predicate.trait_ref.substs.type_at(1); - assemble_builtin_unsize_impls( - self.infcx.tcx, - trait_predicate.def_id(), - source, - target, - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().copy_trait() { - assemble_builtin_copy_clone_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - if Some(trait_predicate.def_id()) == self.infcx.tcx.lang_items().clone_trait() { - // For all builtin impls, the conditions for `Copy` and - // `Clone` are the same. - assemble_builtin_copy_clone_impls( - self.infcx.tcx, - trait_predicate.def_id(), - trait_predicate.self_ty(), - &mut clauses, - ); - } - - // FIXME: we need to add special rules for other builtin impls: - // * `Generator` - // * `FnOnce` / `FnMut` / `Fn` - // * trait objects - // * auto traits - - // Rule `Implemented-From-Env` will be computed from the environment. - clauses - } - - DomainGoal::Holds(ProjectionEq(projection_predicate)) => { - // These come from: - // * the assoc type definition (rule `ProjectionEq-Placeholder`) - // * normalization of the assoc ty values (rule `ProjectionEq-Normalize`) - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - - let clauses = self - .infcx - .tcx - .program_clauses_for(projection_predicate.projection_ty.item_def_id) - .into_iter() - // only select `ProjectionEq-Placeholder` and `ProjectionEq-Normalize` - .filter(|clause| clause.category() == ProgramClauseCategory::Other) - .cloned() - .collect::>(); - - // Rules `Implied-Bound-From-Trait` and `Implied-Bound-From-Type` will be computed - // from the environment. - clauses - } - - // For outlive requirements, just assume they hold. `ResolventOps::resolvent_clause` - // will register them as actual region constraints later. - DomainGoal::Holds(RegionOutlives(..)) | DomainGoal::Holds(TypeOutlives(..)) => { - vec![Clause::Implies(ProgramClause { - goal, - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::Other, - })] - } - - DomainGoal::WellFormed(WellFormed::Trait(trait_predicate)) => { - // These come from -- the trait decl (rule `WellFormed-TraitRef`). - self.infcx - .tcx - .program_clauses_for(trait_predicate.def_id()) - .into_iter() - // only select `WellFormed-TraitRef` - .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed) - .cloned() - .collect() - } - - DomainGoal::WellFormed(WellFormed::Ty(ty)) => { - // These come from: - // * the associated type definition if `ty` refers to an unnormalized - // associated type (rule `WellFormed-AssocTy`) - // * custom rules for built-in types - // * the type definition otherwise (rule `WellFormed-Type`) - let clauses = match ty.kind { - ty::Projection(data) => self.infcx.tcx.program_clauses_for(data.item_def_id), - - // These types are always WF. - ty::Bool - | ty::Char - | ty::Int(..) - | ty::Uint(..) - | ty::Float(..) - | ty::Str - | ty::Param(..) - | ty::Placeholder(..) - | ty::Error - | ty::Never => { - let wf_clause = ProgramClause { - goal, - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::Implies(wf_clause); - - self.infcx.tcx.mk_clauses(iter::once(wf_clause)) - } - - // Always WF (recall that we do not check for parameters to be WF). - ty::RawPtr(ptr) => wf_clause_for_raw_ptr(self.infcx.tcx, ptr.mutbl), - - // Always WF (recall that we do not check for parameters to be WF). - ty::FnPtr(fn_ptr) => { - let fn_ptr = fn_ptr.skip_binder(); - wf_clause_for_fn_ptr( - self.infcx.tcx, - fn_ptr.inputs_and_output.len(), - fn_ptr.c_variadic, - fn_ptr.unsafety, - fn_ptr.abi, - ) - } - - // WF if inner type is `Sized`. - ty::Slice(..) => wf_clause_for_slice(self.infcx.tcx), - - // WF if inner type is `Sized`. - ty::Array(_, length) => wf_clause_for_array(self.infcx.tcx, length), - - // WF if all types but the last one are `Sized`. - ty::Tuple(types) => wf_clause_for_tuple(self.infcx.tcx, types.len()), - - // WF if `sub_ty` outlives `region`. - ty::Ref(_, _, mutbl) => wf_clause_for_ref(self.infcx.tcx, mutbl), - - ty::FnDef(def_id, ..) => wf_clause_for_fn_def(self.infcx.tcx, def_id), - - ty::Dynamic(..) => { - // FIXME: no rules yet for trait objects - ty::List::empty() - } - - ty::Adt(def, ..) => self.infcx.tcx.program_clauses_for(def.did), - - // FIXME: these are probably wrong - ty::Foreign(def_id) - | ty::Closure(def_id, ..) - | ty::Generator(def_id, ..) - | ty::Opaque(def_id, ..) => self.infcx.tcx.program_clauses_for(def_id), - - // Artificially trigger an ambiguity. - ty::Infer(..) => { - let tcx = self.infcx.tcx; - let types = [tcx.types.i32, tcx.types.u32, tcx.types.f32, tcx.types.f64]; - let clauses = types - .iter() - .cloned() - .map(|ty| ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ty)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }) - .map(|clause| Clause::Implies(clause)); - tcx.mk_clauses(clauses) - } - - ty::GeneratorWitness(..) | ty::UnnormalizedProjection(..) | ty::Bound(..) => { - bug!("unexpected type {:?}", ty) - } - }; - - clauses - .into_iter() - .filter(|clause| clause.category() == ProgramClauseCategory::WellFormed) - .cloned() - .collect() - } - - DomainGoal::FromEnv(FromEnv::Trait(..)) => { - // These come from: - // * implied bounds from trait definitions (rule `Implied-Bound-From-Trait`) - // * implied bounds from type definitions (rule `Implied-Bound-From-Type`) - // * implied bounds from assoc type defs (rules `Implied-Trait-From-AssocTy`, - // `Implied-Bound-From-AssocTy` and `Implied-WC-From-AssocTy`) - - // All of these rules are computed in the environment. - vec![] - } - - DomainGoal::FromEnv(FromEnv::Ty(..)) => { - // There are no `FromEnv::Ty(..) :- ...` rules (this predicate only - // comes from the environment). - vec![] - } - - DomainGoal::Normalize(projection_predicate) => { - // These come from -- assoc ty values (rule `Normalize-From-Impl`). - let mut clauses = vec![]; - - assemble_clauses_from_assoc_ty_values( - self.infcx.tcx, - projection_predicate.projection_ty.trait_ref(self.infcx.tcx).def_id, - &mut clauses, - ); - - clauses - } - }; - - debug!("program_clauses: clauses = {:?}", clauses); - debug!("program_clauses: adding clauses from environment = {:?}", environment); - - let mut _orig_query_values = OriginalQueryValues::default(); - let canonical_environment = - self.infcx.canonicalize_query(environment, &mut _orig_query_values).value; - let env_clauses = self.infcx.tcx.program_clauses_for_env(canonical_environment); - - debug!("program_clauses: env_clauses = {:?}", env_clauses); - - clauses.extend(env_clauses.into_iter().cloned()); - clauses.extend(environment.clauses.iter().cloned()); - clauses - } -} diff --git a/src/librustc_traits/chalk_context/program_clauses/primitive.rs b/src/librustc_traits/chalk_context/program_clauses/primitive.rs deleted file mode 100644 index ae4afe58436..00000000000 --- a/src/librustc_traits/chalk_context/program_clauses/primitive.rs +++ /dev/null @@ -1,168 +0,0 @@ -use crate::generic_types; -use crate::lowering::Lower; -use rustc::traits::{ - Clause, Clauses, DomainGoal, GoalKind, ProgramClause, ProgramClauseCategory, WellFormed, -}; -use rustc::ty::{self, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_target::spec::abi; -use std::iter; - -crate fn wf_clause_for_raw_ptr(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> { - let ptr_ty = generic_types::raw_ptr(tcx, mutbl); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ptr_ty)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::Implies(wf_clause); - - // `forall { WellFormed(*const T). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_fn_ptr( - tcx: TyCtxt<'_>, - arity_and_output: usize, - variadic: bool, - unsafety: hir::Unsafety, - abi: abi::Abi, -) -> Clauses<'_> { - let fn_ptr = generic_types::fn_ptr(tcx, arity_and_output, variadic, unsafety, abi); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(fn_ptr)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall { WellFormed(for<> fn(T1, ..., Tn) -> Tn+1). }` - // where `n + 1` == `arity_and_output` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_slice(tcx: TyCtxt<'_>) -> Clauses<'_> { - let ty = generic_types::bound(tcx, 0); - let slice_ty = tcx.mk_slice(ty); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - let sized_implemented = - ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) }; - let sized_implemented: DomainGoal<'_> = - ty::TraitPredicate { trait_ref: sized_implemented }.lower(); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(slice_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall { WellFormed([T]) :- Implemented(T: Sized). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_array<'tcx>( - tcx: TyCtxt<'tcx>, - length: &'tcx ty::Const<'tcx>, -) -> Clauses<'tcx> { - let ty = generic_types::bound(tcx, 0); - let array_ty = tcx.mk_ty(ty::Array(ty, length)); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - let sized_implemented = - ty::TraitRef { def_id: sized_trait, substs: tcx.mk_substs_trait(ty, ty::List::empty()) }; - let sized_implemented: DomainGoal<'_> = - ty::TraitPredicate { trait_ref: sized_implemented }.lower(); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(array_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(GoalKind::DomainGoal(sized_implemented)))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall { WellFormed([T; length]) :- Implemented(T: Sized). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_tuple(tcx: TyCtxt<'_>, arity: usize) -> Clauses<'_> { - let type_list = generic_types::type_list(tcx, arity); - let tuple_ty = tcx.mk_ty(ty::Tuple(type_list)); - - let sized_trait = match tcx.lang_items().sized_trait() { - Some(def_id) => def_id, - None => return ty::List::empty(), - }; - - // If `arity == 0` (i.e. the unit type) or `arity == 1`, this list of - // hypotheses is actually empty. - let sized_implemented = type_list[0..std::cmp::max(arity, 1) - 1] - .iter() - .map(|ty| ty::TraitRef { - def_id: sized_trait, - substs: tcx.mk_substs_trait(ty.expect_ty(), ty::List::empty()), - }) - .map(|trait_ref| ty::TraitPredicate { trait_ref }) - .map(|predicate| predicate.lower()); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(tuple_ty)), - hypotheses: tcx.mk_goals( - sized_implemented.map(|domain_goal| tcx.mk_goal(GoalKind::DomainGoal(domain_goal))), - ), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // ``` - // forall { - // WellFormed((T1, ..., Tn)) :- - // Implemented(T1: Sized), - // ... - // Implemented(Tn-1: Sized). - // } - // ``` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_ref(tcx: TyCtxt<'_>, mutbl: hir::Mutability) -> Clauses<'_> { - let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))); - let ty = generic_types::bound(tcx, 1); - let ref_ty = tcx.mk_ref(region, ty::TypeAndMut { ty, mutbl }); - - let outlives: DomainGoal<'_> = ty::OutlivesPredicate(ty, region).lower(); - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(ref_ty)), - hypotheses: tcx.mk_goals(iter::once(tcx.mk_goal(outlives.into_goal()))), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall<'a, T> { WellFormed(&'a T) :- Outlives(T: 'a). }` - tcx.mk_clauses(iter::once(wf_clause)) -} - -crate fn wf_clause_for_fn_def(tcx: TyCtxt<'_>, def_id: DefId) -> Clauses<'_> { - let fn_def = generic_types::fn_def(tcx, def_id); - - let wf_clause = ProgramClause { - goal: DomainGoal::WellFormed(WellFormed::Ty(fn_def)), - hypotheses: ty::List::empty(), - category: ProgramClauseCategory::WellFormed, - }; - let wf_clause = Clause::ForAll(ty::Binder::bind(wf_clause)); - - // `forall { WellFormed(fn some_fn(T1, ..., Tn) -> Tn+1). }` - // where `def_id` maps to the `some_fn` function definition - tcx.mk_clauses(iter::once(wf_clause)) -} diff --git a/src/librustc_traits/chalk_context/resolvent_ops.rs b/src/librustc_traits/chalk_context/resolvent_ops.rs deleted file mode 100644 index 796ce6085fd..00000000000 --- a/src/librustc_traits/chalk_context/resolvent_ops.rs +++ /dev/null @@ -1,297 +0,0 @@ -use chalk_engine::fallible::{Fallible, NoSolution}; -use chalk_engine::{context, ExClause, Literal}; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc::ty::subst::GenericArg; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_infer::infer::canonical::{Canonical, CanonicalVarValues}; -use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; -use rustc_infer::traits::{ - Clause, DomainGoal, Environment, Goal, GoalKind, InEnvironment, ProgramClause, WhereClause, -}; -use rustc_span::DUMMY_SP; - -use super::unify::*; -use super::{ChalkArenas, ChalkExClause, ChalkInferenceContext, ConstrainedSubst}; - -impl context::ResolventOps, ChalkArenas<'tcx>> - for ChalkInferenceContext<'cx, 'tcx> -{ - fn resolvent_clause( - &mut self, - environment: &Environment<'tcx>, - goal: &DomainGoal<'tcx>, - subst: &CanonicalVarValues<'tcx>, - clause: &Clause<'tcx>, - ) -> Fallible>> { - use chalk_engine::context::UnificationOps; - - debug!("resolvent_clause(goal = {:?}, clause = {:?})", goal, clause); - - let result = self.infcx.probe(|_| { - let ProgramClause { goal: consequence, hypotheses, .. } = match clause { - Clause::Implies(program_clause) => *program_clause, - Clause::ForAll(program_clause) => { - self.infcx - .replace_bound_vars_with_fresh_vars( - DUMMY_SP, - LateBoundRegionConversionTime::HigherRankedType, - program_clause, - ) - .0 - } - }; - - let result = - unify(self.infcx, *environment, ty::Variance::Invariant, goal, &consequence) - .map_err(|_| NoSolution)?; - - let mut ex_clause = ExClause { - subst: subst.clone(), - delayed_literals: vec![], - constraints: vec![], - subgoals: vec![], - }; - - self.into_ex_clause(result, &mut ex_clause); - - ex_clause.subgoals.extend(hypotheses.iter().map(|g| match g { - GoalKind::Not(g) => Literal::Negative(environment.with(*g)), - g => Literal::Positive(environment.with(*g)), - })); - - // If we have a goal of the form `T: 'a` or `'a: 'b`, then just - // assume it is true (no subgoals) and register it as a constraint - // instead. - match goal { - DomainGoal::Holds(WhereClause::RegionOutlives(pred)) => { - assert_eq!(ex_clause.subgoals.len(), 0); - ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); - } - - DomainGoal::Holds(WhereClause::TypeOutlives(pred)) => { - assert_eq!(ex_clause.subgoals.len(), 0); - ex_clause.constraints.push(ty::OutlivesPredicate(pred.0.into(), pred.1)); - } - - _ => (), - }; - - let canonical_ex_clause = self.canonicalize_ex_clause(&ex_clause); - Ok(canonical_ex_clause) - }); - - debug!("resolvent_clause: result = {:?}", result); - result - } - - fn apply_answer_subst( - &mut self, - ex_clause: ChalkExClause<'tcx>, - selected_goal: &InEnvironment<'tcx, Goal<'tcx>>, - answer_table_goal: &Canonical<'tcx, InEnvironment<'tcx, Goal<'tcx>>>, - canonical_answer_subst: &Canonical<'tcx, ConstrainedSubst<'tcx>>, - ) -> Fallible> { - debug!( - "apply_answer_subst(ex_clause = {:?}, selected_goal = {:?})", - self.infcx.resolve_vars_if_possible(&ex_clause), - self.infcx.resolve_vars_if_possible(selected_goal) - ); - - let (answer_subst, _) = self - .infcx - .instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, canonical_answer_subst); - - let mut substitutor = AnswerSubstitutor { - infcx: self.infcx, - environment: selected_goal.environment, - answer_subst: answer_subst.subst, - binder_index: ty::INNERMOST, - ex_clause, - }; - - substitutor.relate(&answer_table_goal.value, &selected_goal).map_err(|_| NoSolution)?; - - let mut ex_clause = substitutor.ex_clause; - ex_clause.constraints.extend(answer_subst.constraints); - - debug!("apply_answer_subst: ex_clause = {:?}", ex_clause); - Ok(ex_clause) - } -} - -struct AnswerSubstitutor<'cx, 'tcx> { - infcx: &'cx InferCtxt<'cx, 'tcx>, - environment: Environment<'tcx>, - answer_subst: CanonicalVarValues<'tcx>, - binder_index: ty::DebruijnIndex, - ex_clause: ChalkExClause<'tcx>, -} - -impl AnswerSubstitutor<'cx, 'tcx> { - fn unify_free_answer_var( - &mut self, - answer_var: ty::BoundVar, - pending: GenericArg<'tcx>, - ) -> RelateResult<'tcx, ()> { - let answer_param = &self.answer_subst.var_values[answer_var]; - let pending = - &ty::fold::shift_out_vars(self.infcx.tcx, &pending, self.binder_index.as_u32()); - - super::into_ex_clause( - unify(self.infcx, self.environment, ty::Variance::Invariant, answer_param, pending)?, - &mut self.ex_clause, - ); - - Ok(()) - } -} - -impl TypeRelation<'tcx> for AnswerSubstitutor<'cx, 'tcx> { - fn tcx(&self) -> TyCtxt<'tcx> { - self.infcx.tcx - } - - fn param_env(&self) -> ty::ParamEnv<'tcx> { - // FIXME(oli-obk): learn chalk and create param envs - ty::ParamEnv::empty() - } - - fn tag(&self) -> &'static str { - "chalk_context::answer_substitutor" - } - - fn a_is_expected(&self) -> bool { - true - } - - fn relate_with_variance>( - &mut self, - _variance: ty::Variance, - a: &T, - b: &T, - ) -> RelateResult<'tcx, T> { - // We don't care about variance. - self.relate(a, b) - } - - fn binders>( - &mut self, - a: &ty::Binder, - b: &ty::Binder, - ) -> RelateResult<'tcx, ty::Binder> { - self.binder_index.shift_in(1); - let result = self.relate(a.skip_binder(), b.skip_binder())?; - self.binder_index.shift_out(1); - Ok(ty::Binder::bind(result)) - } - - fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { - let b = self.infcx.shallow_resolve(b); - debug!("AnswerSubstitutor::tys(a = {:?}, b = {:?})", a, b); - - if let &ty::Bound(debruijn, bound_ty) = &a.kind { - // Free bound var - if debruijn == self.binder_index { - self.unify_free_answer_var(bound_ty.var, b.into())?; - return Ok(b); - } - } - - match (&a.kind, &b.kind) { - (&ty::Bound(a_debruijn, a_bound), &ty::Bound(b_debruijn, b_bound)) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound.var, b_bound.var); - Ok(a) - } - - // Those should have been canonicalized away. - (ty::Placeholder(..), _) => { - bug!("unexpected placeholder ty in `AnswerSubstitutor`: {:?} ", a); - } - - // Everything else should just be a perfect match as well, - // and we forbid inference variables. - _ => match ty::relate::super_relate_tys(self, a, b) { - Ok(ty) => Ok(ty), - Err(err) => bug!("type mismatch in `AnswerSubstitutor`: {}", err), - }, - } - } - - fn regions( - &mut self, - a: ty::Region<'tcx>, - b: ty::Region<'tcx>, - ) -> RelateResult<'tcx, ty::Region<'tcx>> { - let b = match b { - &ty::ReVar(vid) => self - .infcx - .inner - .borrow_mut() - .unwrap_region_constraints() - .opportunistic_resolve_var(self.infcx.tcx, vid), - - other => other, - }; - - if let &ty::ReLateBound(debruijn, bound) = a { - // Free bound region - if debruijn == self.binder_index { - self.unify_free_answer_var(bound.assert_bound_var(), b.into())?; - return Ok(b); - } - } - - match (a, b) { - (&ty::ReLateBound(a_debruijn, a_bound), &ty::ReLateBound(b_debruijn, b_bound)) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound.assert_bound_var(), b_bound.assert_bound_var()); - } - - (ty::ReStatic, ty::ReStatic) | (ty::ReErased, ty::ReErased) => (), - - (ty::ReEmpty(a_ui), ty::ReEmpty(b_ui)) => { - assert_eq!(a_ui, b_ui); - } - - (&ty::ReFree(a_free), &ty::ReFree(b_free)) => { - assert_eq!(a_free, b_free); - } - - _ => bug!("unexpected regions in `AnswerSubstitutor`: {:?}, {:?}", a, b), - } - - Ok(a) - } - - fn consts( - &mut self, - a: &'tcx ty::Const<'tcx>, - b: &'tcx ty::Const<'tcx>, - ) -> RelateResult<'tcx, &'tcx ty::Const<'tcx>> { - if let ty::Const { val: ty::ConstKind::Bound(debruijn, bound_ct), .. } = a { - if *debruijn == self.binder_index { - self.unify_free_answer_var(*bound_ct, b.into())?; - return Ok(b); - } - } - - match (a, b) { - ( - ty::Const { val: ty::ConstKind::Bound(a_debruijn, a_bound), .. }, - ty::Const { val: ty::ConstKind::Bound(b_debruijn, b_bound), .. }, - ) => { - assert_eq!(a_debruijn, b_debruijn); - assert_eq!(a_bound, b_bound); - Ok(a) - } - - // Everything else should just be a perfect match as well, - // and we forbid inference variables. - _ => match ty::relate::super_relate_consts(self, a, b) { - Ok(ct) => Ok(ct), - Err(err) => bug!("const mismatch in `AnswerSubstitutor`: {}", err), - }, - } - } -} diff --git a/src/librustc_traits/chalk_context/unify.rs b/src/librustc_traits/chalk_context/unify.rs deleted file mode 100644 index 3274a301bb6..00000000000 --- a/src/librustc_traits/chalk_context/unify.rs +++ /dev/null @@ -1,85 +0,0 @@ -use rustc::ty; -use rustc::ty::relate::{Relate, RelateResult, TypeRelation}; -use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; -use rustc_infer::infer::{InferCtxt, RegionVariableOrigin}; -use rustc_infer::traits::{DomainGoal, Environment, Goal, InEnvironment}; -use rustc_span::DUMMY_SP; - -crate struct UnificationResult<'tcx> { - crate goals: Vec>>, - crate constraints: Vec>, -} - -crate fn unify<'me, 'tcx, T: Relate<'tcx>>( - infcx: &'me InferCtxt<'me, 'tcx>, - environment: Environment<'tcx>, - variance: ty::Variance, - a: &T, - b: &T, -) -> RelateResult<'tcx, UnificationResult<'tcx>> { - debug!( - "unify( - a = {:?}, - b = {:?}, - environment = {:?}, - )", - a, b, environment - ); - - let mut delegate = ChalkTypeRelatingDelegate::new(infcx, environment); - - TypeRelating::new(infcx, &mut delegate, variance).relate(a, b)?; - - debug!("unify: goals = {:?}, constraints = {:?}", delegate.goals, delegate.constraints); - - Ok(UnificationResult { goals: delegate.goals, constraints: delegate.constraints }) -} - -struct ChalkTypeRelatingDelegate<'me, 'tcx> { - infcx: &'me InferCtxt<'me, 'tcx>, - environment: Environment<'tcx>, - goals: Vec>>, - constraints: Vec>, -} - -impl ChalkTypeRelatingDelegate<'me, 'tcx> { - fn new(infcx: &'me InferCtxt<'me, 'tcx>, environment: Environment<'tcx>) -> Self { - Self { infcx, environment, goals: Vec::new(), constraints: Vec::new() } - } -} - -impl TypeRelatingDelegate<'tcx> for &mut ChalkTypeRelatingDelegate<'_, 'tcx> { - fn create_next_universe(&mut self) -> ty::UniverseIndex { - self.infcx.create_next_universe() - } - - fn next_existential_region_var(&mut self, _was_placeholder: bool) -> ty::Region<'tcx> { - self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(DUMMY_SP)) - } - - fn next_placeholder_region(&mut self, placeholder: ty::PlaceholderRegion) -> ty::Region<'tcx> { - self.infcx.tcx.mk_region(ty::RePlaceholder(placeholder)) - } - - fn generalize_existential(&mut self, universe: ty::UniverseIndex) -> ty::Region<'tcx> { - self.infcx - .next_region_var_in_universe(RegionVariableOrigin::MiscVariable(DUMMY_SP), universe) - } - - fn push_outlives(&mut self, sup: ty::Region<'tcx>, sub: ty::Region<'tcx>) { - self.constraints.push(ty::OutlivesPredicate(sup.into(), sub)); - } - - fn push_domain_goal(&mut self, domain_goal: DomainGoal<'tcx>) { - let goal = self.environment.with(self.infcx.tcx.mk_goal(domain_goal.into_goal())); - self.goals.push(goal); - } - - fn normalization() -> NormalizationStrategy { - NormalizationStrategy::Lazy - } - - fn forbid_inference_vars() -> bool { - false - } -} diff --git a/src/librustc_traits/generic_types.rs b/src/librustc_traits/generic_types.rs deleted file mode 100644 index 44a2c5464cd..00000000000 --- a/src/librustc_traits/generic_types.rs +++ /dev/null @@ -1,65 +0,0 @@ -//! Utilities for creating generic types with bound vars in place of parameter values. - -use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_target::spec::abi; - -crate fn bound(tcx: TyCtxt<'tcx>, index: u32) -> Ty<'tcx> { - let ty = ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(index).into()); - tcx.mk_ty(ty) -} - -crate fn raw_ptr(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> { - tcx.mk_ptr(ty::TypeAndMut { ty: bound(tcx, 0), mutbl }) -} - -crate fn fn_ptr( - tcx: TyCtxt<'tcx>, - arity_and_output: usize, - c_variadic: bool, - unsafety: hir::Unsafety, - abi: abi::Abi, -) -> Ty<'tcx> { - let inputs_and_output = tcx.mk_type_list( - (0..arity_and_output) - .map(|i| ty::BoundVar::from(i)) - // DebruijnIndex(1) because we are going to inject these in a `PolyFnSig` - .map(|var| tcx.mk_ty(ty::Bound(ty::DebruijnIndex::from(1usize), var.into()))), - ); - - let fn_sig = ty::Binder::bind(ty::FnSig { inputs_and_output, c_variadic, unsafety, abi }); - tcx.mk_fn_ptr(fn_sig) -} - -crate fn type_list(tcx: TyCtxt<'tcx>, arity: usize) -> SubstsRef<'tcx> { - tcx.mk_substs( - (0..arity) - .map(|i| ty::BoundVar::from(i)) - .map(|var| tcx.mk_ty(ty::Bound(ty::INNERMOST, var.into()))) - .map(|ty| GenericArg::from(ty)), - ) -} - -crate fn ref_ty(tcx: TyCtxt<'tcx>, mutbl: hir::Mutability) -> Ty<'tcx> { - let region = tcx.mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(0))); - - tcx.mk_ref(region, ty::TypeAndMut { ty: bound(tcx, 1), mutbl }) -} - -crate fn fn_def(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_ty(ty::FnDef(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id))) -} - -crate fn closure(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_closure(def_id, InternalSubsts::bound_vars_for_item(tcx, def_id)) -} - -crate fn generator(tcx: TyCtxt<'tcx>, def_id: DefId) -> Ty<'tcx> { - tcx.mk_generator( - def_id, - InternalSubsts::bound_vars_for_item(tcx, def_id), - hir::Movability::Movable, - ) -} diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs index fefe82fdece..894e3ef3a8f 100644 --- a/src/librustc_traits/lib.rs +++ b/src/librustc_traits/lib.rs @@ -11,10 +11,8 @@ extern crate log; #[macro_use] extern crate rustc; -mod chalk_context; mod dropck_outlives; mod evaluate_obligation; -mod generic_types; mod implied_outlives_bounds; pub mod lowering; mod normalize_erasing_regions; @@ -28,7 +26,6 @@ pub fn provide(p: &mut Providers<'_>) { evaluate_obligation::provide(p); implied_outlives_bounds::provide(p); lowering::provide(p); - chalk_context::provide(p); normalize_projection_ty::provide(p); normalize_erasing_regions::provide(p); type_op::provide(p); diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index d466bbcca79..6bc29d0493e 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -252,11 +252,8 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> { // are any errors at that point, so after type checking you can be // sure that this will succeed without errors anyway. - let unnormalized_env = ty::ParamEnv::new( - tcx.intern_predicates(&predicates), - traits::Reveal::UserFacing, - tcx.sess.opts.debugging_opts.chalk.then_some(def_id), - ); + let unnormalized_env = + ty::ParamEnv::new(tcx.intern_predicates(&predicates), traits::Reveal::UserFacing, None); let body_id = tcx.hir().as_local_hir_id(def_id).map_or(hir::DUMMY_HIR_ID, |id| { tcx.hir().maybe_body_owned_by(id).map_or(id, |body| body.hir_id) diff --git a/src/test/compile-fail/chalkify/chalk_initial_program.rs b/src/test/compile-fail/chalkify/chalk_initial_program.rs deleted file mode 100644 index df25bad622b..00000000000 --- a/src/test/compile-fail/chalkify/chalk_initial_program.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -impl Foo for i32 { } - -impl Foo for u32 { } - -fn gimme() { } - -// Note: this also tests that `std::process::Termination` is implemented for `()`. -fn main() { - gimme::(); - gimme::(); - gimme::(); //~ERROR the trait bound `f32: Foo` is not satisfied -} diff --git a/src/test/compile-fail/chalkify/generic_impls.rs b/src/test/compile-fail/chalkify/generic_impls.rs deleted file mode 100644 index d70c6f8055d..00000000000 --- a/src/test/compile-fail/chalkify/generic_impls.rs +++ /dev/null @@ -1,18 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -impl Foo for (T, u32) { } - -fn gimme() { } - -fn foo() { - gimme::<(T, u32)>(); - gimme::<(Option, u32)>(); - gimme::<(Option, f32)>(); //~ ERROR -} - -fn main() { - gimme::<(i32, u32)>(); - gimme::<(i32, f32)>(); //~ ERROR -} diff --git a/src/test/compile-fail/chalkify/impl_wf.rs b/src/test/compile-fail/chalkify/impl_wf.rs deleted file mode 100644 index 6bb4cf86e79..00000000000 --- a/src/test/compile-fail/chalkify/impl_wf.rs +++ /dev/null @@ -1,39 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo: Sized { } - -trait Bar { - type Item: Foo; -} - -impl Foo for i32 { } - -impl Foo for str { } -//~^ ERROR the size for values of type `str` cannot be known at compilation time - -// Implicit `T: Sized` bound. -impl Foo for Option { } - -impl Bar for () { - type Item = i32; -} - -impl Bar for Option { - type Item = Option; -} - -impl Bar for f32 { -//~^ ERROR the trait bound `f32: Foo` is not satisfied - type Item = f32; - //~^ ERROR the trait bound `f32: Foo` is not satisfied -} - -trait Baz where U: Foo { } - -impl Baz for i32 { } - -impl Baz for f32 { } -//~^ ERROR the trait bound `f32: Foo` is not satisfied - -fn main() { -} diff --git a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs b/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs deleted file mode 100644 index 861f86e6165..00000000000 --- a/src/test/compile-fail/chalkify/recursive_where_clause_on_type.rs +++ /dev/null @@ -1,28 +0,0 @@ -// compile-flags: -Z chalk - -#![feature(trivial_bounds)] - -trait Bar { - fn foo(); -} -trait Foo: Bar { } - -struct S where S: Foo; - -impl Foo for S { -} - -fn bar() { - T::foo(); -} - -fn foo() { - bar::() -} - -fn main() { - // For some reason, the error is duplicated... - - foo::() //~ ERROR the type `S` is not well-formed (chalk) - //~^ ERROR the type `S` is not well-formed (chalk) -} diff --git a/src/test/compile-fail/chalkify/type_wf.rs b/src/test/compile-fail/chalkify/type_wf.rs deleted file mode 100644 index d1aa975ddc2..00000000000 --- a/src/test/compile-fail/chalkify/type_wf.rs +++ /dev/null @@ -1,24 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } - -struct S { - x: T, -} - -impl Foo for i32 { } -impl Foo for Option { } - -fn main() { - let s = S { - x: 5, - }; - - let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied - x: 5.0, - }; - - let s = S { - x: Some(5.0), - }; -} diff --git a/src/test/ui/chalkify/builtin-copy-clone.rs b/src/test/ui/chalkify/builtin-copy-clone.rs deleted file mode 100644 index d403514b553..00000000000 --- a/src/test/ui/chalkify/builtin-copy-clone.rs +++ /dev/null @@ -1,44 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -// Test that `Clone` is correctly implemented for builtin types. - -#[derive(Copy, Clone)] -struct S(i32); - -fn test_clone(arg: T) { - let _ = arg.clone(); -} - -fn test_copy(arg: T) { - let _ = arg; - let _ = arg; -} - -fn test_copy_clone(arg: T) { - test_copy(arg); - test_clone(arg); -} - -fn foo() { } - -fn main() { - test_copy_clone(foo); - let f: fn() = foo; - test_copy_clone(f); - // FIXME: add closures when they're considered WF - test_copy_clone([1; 56]); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)); - test_copy_clone((1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, true, 'a', 1.1)); - test_copy_clone(()); - test_copy_clone(((1, 1), (1, 1, 1), (1.1, 1, 1, 'a'), ())); - - let a = ( - (S(1), S(0)), - ( - (S(0), S(0), S(1)), - S(0) - ) - ); - test_copy_clone(a); -} diff --git a/src/test/ui/chalkify/inherent_impl.rs b/src/test/ui/chalkify/inherent_impl.rs deleted file mode 100644 index 44e120c1eeb..00000000000 --- a/src/test/ui/chalkify/inherent_impl.rs +++ /dev/null @@ -1,42 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } - -impl Foo for i32 { } - -struct S { - x: T, -} - -fn only_foo(_x: &T) { } - -impl S { - // Test that we have the correct environment inside an inherent method. - fn dummy_foo(&self) { - only_foo(&self.x) - } -} - -trait Bar { } -impl Bar for u32 { } - -fn only_bar() { } - -impl S { - // Test that the environment of `dummy_bar` adds up with the environment - // of the inherent impl. - fn dummy_bar(&self) { - only_foo(&self.x); - only_bar::(); - } -} - -fn main() { - let s = S { - x: 5, - }; - - s.dummy_foo(); - s.dummy_bar::(); -} diff --git a/src/test/ui/chalkify/lower_env1.rs b/src/test/ui/chalkify/lower_env1.rs deleted file mode 100644 index afb6bddbf26..00000000000 --- a/src/test/ui/chalkify/lower_env1.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Bar where Self: Foo { } - -#[rustc_dump_env_program_clauses] //~ ERROR program clause dump -fn bar() { -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env1.stderr b/src/test/ui/chalkify/lower_env1.stderr deleted file mode 100644 index bc426e0707b..00000000000 --- a/src/test/ui/chalkify/lower_env1.stderr +++ /dev/null @@ -1,22 +0,0 @@ -error: program clause dump - --> $DIR/lower_env1.rs:6:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { FromEnv(Self: Foo) :- FromEnv(Self: Bar). } - = note: forall { Implemented(Self: Bar) :- FromEnv(Self: Bar). } - = note: forall { WellFormed(Self: Bar) :- Implemented(Self: Bar), WellFormed(Self: Foo). } - -error: program clause dump - --> $DIR/lower_env1.rs:9:1 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { FromEnv(Self: Foo) :- FromEnv(Self: Bar). } - = note: forall { Implemented(Self: Bar) :- FromEnv(Self: Bar). } - = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_env2.rs b/src/test/ui/chalkify/lower_env2.rs deleted file mode 100644 index a067575a9cf..00000000000 --- a/src/test/ui/chalkify/lower_env2.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -struct S<'a, T: ?Sized> where T: Foo { - data: &'a T, -} - -#[rustc_dump_env_program_clauses] //~ ERROR program clause dump -fn bar(_x: S<'_, T>) { // note that we have an implicit `T: Sized` bound -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env2.stderr b/src/test/ui/chalkify/lower_env2.stderr deleted file mode 100644 index 613a568a854..00000000000 --- a/src/test/ui/chalkify/lower_env2.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: program clause dump - --> $DIR/lower_env2.rs:6:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { WellFormed(S<'a, T>) :- WellFormed(T: Foo), TypeOutlives(T: 'a). } - -error: program clause dump - --> $DIR/lower_env2.rs:11:1 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: Foo) :- FromEnv(S<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(S<'a, T>). } - = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - = note: forall { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_env3.rs b/src/test/ui/chalkify/lower_env3.rs deleted file mode 100644 index 61ed3cbb277..00000000000 --- a/src/test/ui/chalkify/lower_env3.rs +++ /dev/null @@ -1,16 +0,0 @@ -#![feature(rustc_attrs)] -#![allow(dead_code)] - -trait Foo { - #[rustc_dump_env_program_clauses] //~ ERROR program clause dump - fn foo(&self); -} - -impl Foo for T where T: Clone { - #[rustc_dump_env_program_clauses] //~ ERROR program clause dump - fn foo(&self) { - } -} - -fn main() { -} diff --git a/src/test/ui/chalkify/lower_env3.stderr b/src/test/ui/chalkify/lower_env3.stderr deleted file mode 100644 index a1fc83bfea8..00000000000 --- a/src/test/ui/chalkify/lower_env3.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: program clause dump - --> $DIR/lower_env3.rs:5:5 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - -error: program clause dump - --> $DIR/lower_env3.rs:10:5 - | -LL | #[rustc_dump_env_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { FromEnv(Self: std::marker::Sized) :- FromEnv(Self: std::clone::Clone). } - = note: forall { Implemented(Self: std::clone::Clone) :- FromEnv(Self: std::clone::Clone). } - = note: forall { Implemented(Self: std::marker::Sized) :- FromEnv(Self: std::marker::Sized). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_impl.rs b/src/test/ui/chalkify/lower_impl.rs deleted file mode 100644 index 1bd44a9f498..00000000000 --- a/src/test/ui/chalkify/lower_impl.rs +++ /dev/null @@ -1,19 +0,0 @@ -#![feature(rustc_attrs)] - -trait Foo { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -impl Foo for T where T: Iterator { } - -trait Bar { - type Assoc; -} - -impl Bar for T where T: Iterator { - #[rustc_dump_program_clauses] //~ ERROR program clause dump - type Assoc = Vec; -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_impl.stderr b/src/test/ui/chalkify/lower_impl.stderr deleted file mode 100644 index d6827fbff3d..00000000000 --- a/src/test/ui/chalkify/lower_impl.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: program clause dump - --> $DIR/lower_impl.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { Implemented(T: Foo) :- ProjectionEq(::Item == i32), TypeOutlives(T: 'static), Implemented(T: std::iter::Iterator), Implemented(T: std::marker::Sized). } - -error: program clause dump - --> $DIR/lower_impl.rs:13:5 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { Normalize(::Assoc -> std::vec::Vec) :- Implemented(T: Bar). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_struct.rs b/src/test/ui/chalkify/lower_struct.rs deleted file mode 100644 index aecccea5c14..00000000000 --- a/src/test/ui/chalkify/lower_struct.rs +++ /dev/null @@ -1,8 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -struct Foo<'a, T> where Box: Clone { - _x: std::marker::PhantomData<&'a T>, -} - -fn main() { } diff --git a/src/test/ui/chalkify/lower_struct.stderr b/src/test/ui/chalkify/lower_struct.stderr deleted file mode 100644 index 0331c2fca16..00000000000 --- a/src/test/ui/chalkify/lower_struct.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: program clause dump - --> $DIR/lower_struct.rs:3:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, T> { FromEnv(T: std::marker::Sized) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { FromEnv(std::boxed::Box: std::clone::Clone) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { TypeOutlives(T: 'a) :- FromEnv(Foo<'a, T>). } - = note: forall<'a, T> { WellFormed(Foo<'a, T>) :- WellFormed(T: std::marker::Sized), WellFormed(std::boxed::Box: std::clone::Clone), TypeOutlives(T: 'a). } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/lower_trait.rs b/src/test/ui/chalkify/lower_trait.rs deleted file mode 100644 index 0e1956022f9..00000000000 --- a/src/test/ui/chalkify/lower_trait.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![feature(rustc_attrs)] - -trait Bar { } - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo { - #[rustc_dump_program_clauses] //~ ERROR program clause dump - type Assoc: Bar + ?Sized; -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait.stderr b/src/test/ui/chalkify/lower_trait.stderr deleted file mode 100644 index ed3bded398a..00000000000 --- a/src/test/ui/chalkify/lower_trait.stderr +++ /dev/null @@ -1,24 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { FromEnv(>::Assoc: Bar) :- FromEnv(Self: Foo). } - = note: forall { FromEnv(S: std::marker::Sized) :- FromEnv(Self: Foo). } - = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - = note: forall { WellFormed(Self: Foo) :- Implemented(Self: Foo), WellFormed(S: std::marker::Sized), WellFormed(>::Assoc: Bar). } - -error: program clause dump - --> $DIR/lower_trait.rs:7:5 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall { ProjectionEq(>::Assoc == ^3) :- Normalize(>::Assoc -> ^3). } - = note: forall { FromEnv(Self: Foo) :- FromEnv(Unnormalized(>::Assoc)). } - = note: forall { ProjectionEq(>::Assoc == Unnormalized(>::Assoc)). } - = note: forall { WellFormed(Unnormalized(>::Assoc)) :- WellFormed(Self: Foo). } - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.rs b/src/test/ui/chalkify/lower_trait_higher_rank.rs deleted file mode 100644 index 715f09632bd..00000000000 --- a/src/test/ui/chalkify/lower_trait_higher_rank.rs +++ /dev/null @@ -1,10 +0,0 @@ -#![feature(rustc_attrs)] - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo where for<'a> F: Fn(&'a (u8, u16)) -> &'a u8 -{ -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait_higher_rank.stderr b/src/test/ui/chalkify/lower_trait_higher_rank.stderr deleted file mode 100644 index 79bbc9fa6b3..00000000000 --- a/src/test/ui/chalkify/lower_trait_higher_rank.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait_higher_rank.rs:3:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, Self, F> { FromEnv(F: std::ops::Fn<(&'a (u8, u16),)>) :- FromEnv(Self: Foo). } - = note: forall<'a, Self, F> { ProjectionEq(>::Output == &'a u8) :- FromEnv(Self: Foo). } - = note: forall { Implemented(Self: Foo) :- FromEnv(Self: Foo). } - = note: forall { WellFormed(Self: Foo) :- Implemented(Self: Foo), forall<'a> { WellFormed(F: std::ops::Fn<(&'a (u8, u16),)>) }, forall<'a> { ProjectionEq(>::Output == &'a u8) }. } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/lower_trait_where_clause.rs b/src/test/ui/chalkify/lower_trait_where_clause.rs deleted file mode 100644 index 78fa39f1dc1..00000000000 --- a/src/test/ui/chalkify/lower_trait_where_clause.rs +++ /dev/null @@ -1,17 +0,0 @@ -#![feature(rustc_attrs)] - -use std::borrow::Borrow; - -#[rustc_dump_program_clauses] //~ ERROR program clause dump -trait Foo<'a, 'b, T, U> -where - T: Borrow + ?Sized, - U: ?Sized + 'b, - 'a: 'b, - Box:, // NOTE(#53696) this checks an empty list of bounds. -{ -} - -fn main() { - println!("hello"); -} diff --git a/src/test/ui/chalkify/lower_trait_where_clause.stderr b/src/test/ui/chalkify/lower_trait_where_clause.stderr deleted file mode 100644 index 408f3712a70..00000000000 --- a/src/test/ui/chalkify/lower_trait_where_clause.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: program clause dump - --> $DIR/lower_trait_where_clause.rs:5:1 - | -LL | #[rustc_dump_program_clauses] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: forall<'a, 'b, Self, T, U> { FromEnv(T: std::borrow::Borrow) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { Implemented(Self: Foo<'a, 'b, T, U>) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { RegionOutlives('a: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { TypeOutlives(U: 'b) :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { TypeOutlives(std::boxed::Box: ') :- FromEnv(Self: Foo<'a, 'b, T, U>). } - = note: forall<'a, 'b, Self, T, U> { WellFormed(Self: Foo<'a, 'b, T, U>) :- Implemented(Self: Foo<'a, 'b, T, U>), WellFormed(T: std::borrow::Borrow), TypeOutlives(U: 'b), RegionOutlives('a: 'b), TypeOutlives(std::boxed::Box: '). } - -error: aborting due to previous error - diff --git a/src/test/ui/chalkify/projection.rs b/src/test/ui/chalkify/projection.rs deleted file mode 100644 index d6a8dd7a4a2..00000000000 --- a/src/test/ui/chalkify/projection.rs +++ /dev/null @@ -1,25 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } - -trait Bar { - type Item: Foo; -} - -impl Foo for i32 { } -impl Bar for i32 { - type Item = i32; -} - -fn only_foo() { } - -fn only_bar() { - // `T` implements `Bar` hence `::Item` must also implement `Bar` - only_foo::() -} - -fn main() { - only_bar::(); - only_foo::<::Item>(); -} diff --git a/src/test/ui/chalkify/super_trait.rs b/src/test/ui/chalkify/super_trait.rs deleted file mode 100644 index eeff9fd9b80..00000000000 --- a/src/test/ui/chalkify/super_trait.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } -trait Bar: Foo { } - -impl Foo for i32 { } -impl Bar for i32 { } - -fn only_foo() { } - -fn only_bar() { - // `T` implements `Bar` hence `T` must also implement `Foo` - only_foo::() -} - -fn main() { - only_bar::() -} diff --git a/src/test/ui/chalkify/trait_implied_bound.rs b/src/test/ui/chalkify/trait_implied_bound.rs deleted file mode 100644 index 8a2e1cf5990..00000000000 --- a/src/test/ui/chalkify/trait_implied_bound.rs +++ /dev/null @@ -1,18 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Foo { } -trait Bar where U: Foo { } - -impl Foo for i32 { } -impl Bar for i32 { } - -fn only_foo() { } - -fn only_bar>() { - only_foo::() -} - -fn main() { - only_bar::() -} diff --git a/src/test/ui/chalkify/type_implied_bound.rs b/src/test/ui/chalkify/type_implied_bound.rs deleted file mode 100644 index 8673f5319bd..00000000000 --- a/src/test/ui/chalkify/type_implied_bound.rs +++ /dev/null @@ -1,29 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -trait Eq { } -trait Hash: Eq { } - -impl Eq for i32 { } -impl Hash for i32 { } - -struct Set { - _x: T, -} - -fn only_eq() { } - -fn take_a_set(_: &Set) { - // `Set` is an input type of `take_a_set`, hence we know that - // `T` must implement `Hash`, and we know in turn that `T` must - // implement `Eq`. - only_eq::() -} - -fn main() { - let set = Set { - _x: 5, - }; - - take_a_set(&set); -} diff --git a/src/test/ui/chalkify/type_inference.rs b/src/test/ui/chalkify/type_inference.rs deleted file mode 100644 index 62a53ec0317..00000000000 --- a/src/test/ui/chalkify/type_inference.rs +++ /dev/null @@ -1,26 +0,0 @@ -// compile-flags: -Z chalk - -trait Foo { } -impl Foo for i32 { } - -trait Bar { } -impl Bar for i32 { } -impl Bar for u32 { } - -fn only_foo(_x: T) { } - -fn only_bar(_x: T) { } - -fn main() { - let x = 5.0; - - // The only type which implements `Foo` is `i32`, so the chalk trait solver - // is expecting a variable of type `i32`. This behavior differs from the - // old-style trait solver. I guess this will change, that's why I'm - // adding that test. - only_foo(x); //~ ERROR mismatched types - - // Here we have two solutions so we get back the behavior of the old-style - // trait solver. - only_bar(x); //~ ERROR the trait bound `{float}: Bar` is not satisfied -} diff --git a/src/test/ui/chalkify/type_inference.stderr b/src/test/ui/chalkify/type_inference.stderr deleted file mode 100644 index b8152caf3d2..00000000000 --- a/src/test/ui/chalkify/type_inference.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/type_inference.rs:21:14 - | -LL | only_foo(x); - | ^ expected `i32`, found floating-point number - -error[E0277]: the trait bound `{float}: Bar` is not satisfied - --> $DIR/type_inference.rs:25:5 - | -LL | fn only_bar(_x: T) { } - | -------- --- required by this bound in `only_bar` -... -LL | only_bar(x); - | ^^^^^^^^ the trait `Bar` is not implemented for `{float}` - | - = help: the following implementations were found: - - - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0308. -For more information about an error, try `rustc --explain E0277`. diff --git a/src/test/ui/const-generics/issues/issue-65675.rs b/src/test/ui/const-generics/issues/issue-65675.rs deleted file mode 100644 index 3ca527313f9..00000000000 --- a/src/test/ui/const-generics/issues/issue-65675.rs +++ /dev/null @@ -1,10 +0,0 @@ -// run-pass -// compile-flags: -Z chalk - -#![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash - -pub struct Foo([T; N]); -impl Foo {} - -fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-65675.stderr b/src/test/ui/const-generics/issues/issue-65675.stderr deleted file mode 100644 index 60b388e6278..00000000000 --- a/src/test/ui/const-generics/issues/issue-65675.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash - --> $DIR/issue-65675.rs:4:12 - | -LL | #![feature(const_generics)] - | ^^^^^^^^^^^^^^ - | - = note: `#[warn(incomplete_features)]` on by default - From e364c283fd15e5bc43ed1b7c0e8c86b0c8bd44d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 18:43:05 +0100 Subject: [PATCH 0702/1250] Use let instead of match to get value of enum with single variant. --- src/librustc_mir/monomorphize/collector.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index f6a93363dc1..862a7ef1e73 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -824,11 +824,8 @@ fn find_vtable_types_for_unsizing<'tcx>( (&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => { assert_eq!(source_adt_def, target_adt_def); - let kind = monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty); - - let coerce_index = match kind { - CustomCoerceUnsized::Struct(i) => i, - }; + let CustomCoerceUnsized::Struct(coerce_index) = + monomorphize::custom_coerce_unsize_info(tcx, source_ty, target_ty); let source_fields = &source_adt_def.non_enum_variant().fields; let target_fields = &target_adt_def.non_enum_variant().fields; From 5abaeb3d6712b54f3309df968ebee39e544d0fcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 18:53:56 +0100 Subject: [PATCH 0703/1250] Simplify conditions like x + 1 <= y to x < y --- src/liballoc/collections/btree/node.rs | 2 +- src/librustc/mir/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index c1bd68a020a..362755f8b7f 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -1191,7 +1191,7 @@ impl<'a, K, V> Handle, K, V, marker::Internal>, marker:: let right_len = right_node.len(); // necessary for correctness, but in a private module - assert!(left_len + right_len + 1 <= CAPACITY); + assert!(left_len + right_len < CAPACITY); unsafe { ptr::write( diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 668240ab42b..36818020569 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -189,7 +189,7 @@ impl<'tcx> Body<'tcx> { ) -> Self { // We need `arg_count` locals, and one for the return place. assert!( - local_decls.len() >= arg_count + 1, + local_decls.len() > arg_count, "expected at least {} locals, got {}", arg_count + 1, local_decls.len() From c287d86d2c535425cdf830e3be11e00fa32c909f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 19:36:12 +0100 Subject: [PATCH 0704/1250] Use .nth(x) instead of .skip(x).next() on iterators. --- src/librustc_codegen_ssa/back/link.rs | 2 +- src/librustc_infer/traits/error_reporting/suggestions.rs | 8 ++------ 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 90601521b19..61ca7c859ab 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -186,7 +186,7 @@ pub fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> (PathB 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() { + if let Some(ref root_lib_path) = original_path.ancestors().nth(4) { let arch = match t.arch.as_str() { "x86_64" => Some("x64".to_string()), "x86" => Some("x86".to_string()), diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index ed6cfa51cdf..d05955fb858 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -401,9 +401,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); - if let Some('\'') = - snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next() - { + if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. return; } @@ -464,9 +462,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { let refs_number = snippet.chars().filter(|c| !c.is_whitespace()).take_while(|c| *c == '&').count(); - if let Some('\'') = - snippet.chars().filter(|c| !c.is_whitespace()).skip(refs_number).next() - { + if let Some('\'') = snippet.chars().filter(|c| !c.is_whitespace()).nth(refs_number) { // Do not suggest removal of borrow from type arguments. return; } From ae34b9d996716994de1ce185fa23fc5427905d57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 20:01:03 +0100 Subject: [PATCH 0705/1250] Use .any(x) instead of .find(x).is_some() on iterators. --- src/librustc_typeck/check/demand.rs | 3 +-- .../coherence/inherent_impls_overlap.rs | 13 +++++-------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 0c5f3d3e99d..bdf587dc321 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -236,8 +236,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // FIXME? Other potential candidate methods: `as_ref` and // `as_mut`? - .find(|a| a.check_name(sym::rustc_conversion_suggestion)) - .is_some() + .any(|a| a.check_name(sym::rustc_conversion_suggestion)) }); methods diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index fcded27463e..778eee3586b 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -23,14 +23,11 @@ impl InherentOverlapChecker<'tcx> { let impl_items2 = self.tcx.associated_items(impl2); for item1 in impl_items1.in_definition_order() { - let collision = impl_items2 - .filter_by_name_unhygienic(item1.ident.name) - .find(|item2| { - // Symbols and namespace match, compare hygienically. - item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() - }) - .is_some(); + let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| { + // Symbols and namespace match, compare hygienically. + item1.kind.namespace() == item2.kind.namespace() + && item1.ident.modern() == item2.ident.modern() + }); if collision { return true; From 10183851fbfa68241a5eeaf9b3cc575172731a6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Mar 2020 20:17:10 +0100 Subject: [PATCH 0706/1250] Improve weird formatting by moving comment inside else-code block. --- src/librustc_expand/mbe/transcribe.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 80bf02b1366..d12dedf9e0c 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -119,9 +119,9 @@ pub(super) fn transcribe( let tree = if let Some(tree) = stack.last_mut().unwrap().next() { // If it still has a TokenTree we have not looked at yet, use that tree. tree - } - // The else-case never produces a value for `tree` (it `continue`s or `return`s). - else { + } else { + // This else-case never produces a value for `tree` (it `continue`s or `return`s). + // Otherwise, if we have just reached the end of a sequence and we can keep repeating, // go back to the beginning of the sequence. if let Frame::Sequence { idx, sep, .. } = stack.last_mut().unwrap() { From 7859f0eac3b70fea1f129665d0b9f4c56769fa4c Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 2 Mar 2020 21:47:33 -0300 Subject: [PATCH 0707/1250] Make PlaceRef lifetimes of Place::as_ref be both 'tcx --- src/librustc/mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 668240ab42b..0d429d8879b 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1864,7 +1864,7 @@ impl<'tcx> Place<'tcx> { self.as_ref().as_local() } - pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> { + pub fn as_ref(&self) -> PlaceRef<'tcx, 'tcx> { PlaceRef { local: self.local, projection: &self.projection } } } From 812e62f14609fe80c49664f8b4ee5678c126c4a3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 2 Mar 2020 22:02:52 -0300 Subject: [PATCH 0708/1250] Make PlaceRef lifetimes of LocalAnalyzer::process_place be both 'tcx --- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 7bf222f4701..6214aa84b81 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -97,7 +97,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn process_place( &mut self, - place_ref: &mir::PlaceRef<'_, 'tcx>, + place_ref: &mir::PlaceRef<'tcx, 'tcx>, context: PlaceContext, location: Location, ) { From d3e5177f816d723cbce31ae7a7779feca8a69724 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 3 Mar 2020 01:19:00 +0100 Subject: [PATCH 0709/1250] Use .next() instead of .nth(0) on iterators. --- src/librustc/mir/mod.rs | 2 +- src/librustc/ty/util.rs | 2 +- src/librustc_mir/transform/simplify.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_mir_build/hair/pattern/_match.rs | 2 +- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_parse/parser/pat.rs | 2 +- src/librustc_parse/parser/ty.rs | 2 +- src/librustc_span/source_map.rs | 6 +++--- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/tools/unicode-table-generator/src/main.rs | 2 +- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 668240ab42b..bb2d57c856d 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1446,7 +1446,7 @@ impl<'tcx> Debug for TerminatorKind<'tcx> { match successor_count { 0 => Ok(()), - 1 => write!(fmt, " -> {:?}", self.successors().nth(0).unwrap()), + 1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()), _ => { write!(fmt, " -> [")?; diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7b1f821877b..87dcc617fa2 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -357,7 +357,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut dtor_did = None; let ty = self.type_of(adt_did); self.for_each_relevant_impl(drop_trait, ty, |impl_did| { - if let Some(item) = self.associated_items(impl_did).in_definition_order().nth(0) { + if let Some(item) = self.associated_items(impl_did).in_definition_order().next() { if validate(self, impl_did).is_ok() { dtor_did = Some(item.def_id); } diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index ddf8d73e548..597d3f0237a 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -230,7 +230,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> { }; let first_succ = { - if let Some(&first_succ) = terminator.successors().nth(0) { + if let Some(&first_succ) = terminator.successors().next() { if terminator.successors().all(|s| *s == first_succ) { let count = terminator.successors().count(); self.pred_count[first_succ] -= (count - 1) as u32; diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f7239ae55fa..a928ab6a009 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -549,7 +549,7 @@ where debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); let drop_trait = tcx.lang_items().drop_trait().unwrap(); - let drop_fn = tcx.associated_items(drop_trait).in_definition_order().nth(0).unwrap(); + let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap(); let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 90e4f536478..64960a0da9c 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -1000,7 +1000,7 @@ impl<'tcx> Constructor<'tcx> { PatKind::Leaf { subpatterns } } } - ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.nth(0).unwrap() }, + ty::Ref(..) => PatKind::Deref { subpattern: subpatterns.next().unwrap() }, ty::Slice(_) | ty::Array(..) => bug!("bad slice pattern {:?} {:?}", self, ty), _ => PatKind::Wild, }, diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 18ddd23588e..14366eb4e87 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -955,7 +955,7 @@ impl<'a> Parser<'a> { }; let kind = if es.len() == 1 && !trailing_comma { // `(e)` is parenthesized `e`. - ExprKind::Paren(es.into_iter().nth(0).unwrap()) + ExprKind::Paren(es.into_iter().next().unwrap()) } else { // `(e,)` is a tuple with only one field, `e`. ExprKind::Tup(es) diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 45d1aacdd3c..4c041fd669d 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -479,7 +479,7 @@ impl<'a> Parser<'a> { // 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()) + PatKind::Paren(fields.into_iter().next().unwrap()) } else { PatKind::Tuple(fields) }) diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index 3d2b0c014ac..c4469331b66 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -198,7 +198,7 @@ impl<'a> Parser<'a> { })?; if ts.len() == 1 && !trailing { - let ty = ts.into_iter().nth(0).unwrap().into_inner(); + let ty = ts.into_iter().next().unwrap().into_inner(); let maybe_bounds = allow_plus == AllowPlus::Yes && self.token.is_like_plus(); match ty.kind { // `(TY_BOUND_NOPAREN) + BOUND + ...`. diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 39601ad7622..798600fc682 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -620,7 +620,7 @@ impl SourceMap { /// if no character could be found or if an error occurred while retrieving the code snippet. pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(c).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && !prev_source.contains('\n') { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -640,7 +640,7 @@ impl SourceMap { for ws in &[" ", "\t", "\n"] { let pat = pat.to_owned() + ws; if let Ok(prev_source) = self.span_to_prev_source(sp) { - let prev_source = prev_source.rsplit(&pat).nth(0).unwrap_or("").trim_start(); + let prev_source = prev_source.rsplit(&pat).next().unwrap_or("").trim_start(); if !prev_source.is_empty() && (!prev_source.contains('\n') || accept_newlines) { return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); } @@ -655,7 +655,7 @@ impl SourceMap { pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { Ok(snippet) => { - let snippet = snippet.split(c).nth(0).unwrap_or("").trim_end(); + let snippet = snippet.split(c).next().unwrap_or("").trim_end(); if !snippet.is_empty() && !snippet.contains('\n') { sp.with_hi(BytePos(sp.lo().0 + snippet.len() as u32)) } else { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 816de5dadbc..8689db1b1eb 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -675,7 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // The `Future` trait has only one associted item, `Output`, // so check that this is what we see. let output_assoc_item = - self.tcx.associated_items(future_trait).in_definition_order().nth(0).unwrap().def_id; + self.tcx.associated_items(future_trait).in_definition_order().next().unwrap().def_id; if output_assoc_item != predicate.projection_ty.item_def_id { span_bug!( cause_span, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b7353c6af26..f00476fb991 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5244,7 +5244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_items(future_trait) .in_definition_order() - .nth(0) + .next() .unwrap() .def_id; let predicate = diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index be8508e3973..839d914baa9 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -147,7 +147,7 @@ fn main() { eprintln!("Must provide path to write unicode tables to"); eprintln!( "e.g. {} src/libcore/unicode/unicode_data.rs", - std::env::args().nth(0).unwrap_or_default() + std::env::args().next().unwrap_or_default() ); std::process::exit(1); }); From df716b0e37ed087b8bce20bc04c23efd0fa5b645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Tue, 3 Mar 2020 02:07:15 +0100 Subject: [PATCH 0710/1250] use conditions directly --- src/librustc_codegen_llvm/va_arg.rs | 3 +-- src/librustc_span/source_map.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs index 9bc3eec60ae..a552f2cdb78 100644 --- a/src/librustc_codegen_llvm/va_arg.rs +++ b/src/librustc_codegen_llvm/va_arg.rs @@ -117,8 +117,7 @@ pub(super) fn emit_va_arg( // Windows x86_64 ("x86_64", true) => { let target_ty_size = bx.cx.size_of(target_ty).bytes(); - let indirect = - if target_ty_size > 8 || !target_ty_size.is_power_of_two() { true } else { false }; + let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two(); emit_ptr_va_arg(bx, addr, target_ty, indirect, Align::from_bytes(8).unwrap(), false) } // For all other architecture/OS combinations fall back to using diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 39601ad7622..e0bbaf730a5 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -689,7 +689,7 @@ impl SourceMap { whitespace_found = true; } - if whitespace_found && !c.is_whitespace() { false } else { true } + !whitespace_found || c.is_whitespace() }) } From 2a29726fcd09fac350e0a8c0d1dd78a8ae6de0ed Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Mon, 2 Mar 2020 21:17:58 -0800 Subject: [PATCH 0711/1250] Implement From<&mut str> for String --- src/liballoc/string.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f5afea15d65..43217ae9364 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2225,6 +2225,14 @@ impl From<&str> for String { } } +#[stable(feature = "???", since = "1.43.0")] +impl From<&mut str> for String { + #[inline] + fn from(s: &mut str) -> String { + s.to_owned() + } +} + #[stable(feature = "from_ref_string", since = "1.35.0")] impl From<&String> for String { #[inline] From a61e13423e57380a08ea1475db57fc30cb7deb15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 Mar 2020 00:00:00 +0000 Subject: [PATCH 0712/1250] Invoke OptimizerLastEPCallbacks in PreLinkThinLTO The default ThinLTO pre-link pipeline does not include optimizer last extension points. Thus, when using the new LLVM pass manager & ThinLTO & sanitizers on any opt-level different from zero, the sanitizer function passes would be omitted from the pipeline. Add optimizer last extensions points manually to the pipeline, but guard registration with stage check in the case this behaviour changes in the future. --- src/rustllvm/PassWrapper.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 65071c3ed86..90d24d20737 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -868,8 +868,10 @@ LLVMRustOptimizeWithNewPassManager( } else { for (const auto &C : PipelineStartEPCallbacks) PB.registerPipelineStartEPCallback(C); - for (const auto &C : OptimizerLastEPCallbacks) - PB.registerOptimizerLastEPCallback(C); + if (OptStage != LLVMRustOptStage::PreLinkThinLTO) { + for (const auto &C : OptimizerLastEPCallbacks) + PB.registerOptimizerLastEPCallback(C); + } switch (OptStage) { case LLVMRustOptStage::PreLinkNoLTO: @@ -877,6 +879,12 @@ LLVMRustOptimizeWithNewPassManager( break; case LLVMRustOptStage::PreLinkThinLTO: MPM = PB.buildThinLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); + if (!OptimizerLastEPCallbacks.empty()) { + FunctionPassManager FPM(DebugPassManager); + for (const auto &C : OptimizerLastEPCallbacks) + C(FPM, OptLevel); + MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); + } break; case LLVMRustOptStage::PreLinkFatLTO: MPM = PB.buildLTOPreLinkDefaultPipeline(OptLevel, DebugPassManager); From 52c5f2a577bdc5181af96eb6a2f82cd502f92f20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 Mar 2020 00:00:00 +0000 Subject: [PATCH 0713/1250] Add test for -Znew-llvm-pass-manager -Clto=thin -Zsanitizer=... Additionally verify that the current implementation of LLVM version check (which uses lexicographic ordering) is good enough to exclude versions before LLVM 9, where the new LLVM pass manager is unsupported. --- .../new-llvm-pass-manager-thin-lto.rs | 27 +++++++++++++++++++ src/tools/compiletest/src/header/tests.rs | 18 +++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs new file mode 100644 index 00000000000..61d5d51cfd2 --- /dev/null +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -0,0 +1,27 @@ +// Regression test for sanitizer function instrumentation passes not +// being run when compiling with new LLVM pass manager and ThinLTO. +// Note: The issue occured only on non-zero opt-level. +// +// min-llvm-version 9.0 +// needs-sanitizer-support +// only-x86_64 +// +// no-prefer-dynamic +// revisions: opt0 opt1 +// compile-flags: -Znew-llvm-pass-manager=yes -Zsanitizer=address -Clto=thin +//[opt0]compile-flags: -Copt-level=0 +//[opt1]compile-flags: -Copt-level=1 +// run-fail +// error-pattern: ERROR: AddressSanitizer: stack-use-after-scope + +static mut P: *mut usize = std::ptr::null_mut(); + +fn main() { + unsafe { + { + let mut x = 0; + P = &mut x; + } + std::ptr::write_volatile(P, 123); + } +} diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 38fa778219d..6c478f7e29d 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -109,6 +109,24 @@ fn no_system_llvm() { assert!(parse_rs(&config, "// no-system-llvm").ignore); } +#[test] +fn llvm_version() { + let mut config = config(); + + config.llvm_version = Some("8.1.2-rust".to_owned()); + assert!(parse_rs(&config, "// min-llvm-version 9.0").ignore); + + config.llvm_version = Some("9.0.1-rust-1.43.0-dev".to_owned()); + assert!(parse_rs(&config, "// min-llvm-version 9.2").ignore); + + config.llvm_version = Some("9.3.1-rust-1.43.0-dev".to_owned()); + assert!(!parse_rs(&config, "// min-llvm-version 9.2").ignore); + + // FIXME. + // config.llvm_version = Some("10.0.0-rust".to_owned()); + // assert!(!parse_rs(&config, "// min-llvm-version 9.0").ignore); +} + #[test] fn ignore_target() { let mut config = config(); From b0e288d9f1d8b0f4038bb955a68308b892d54ea3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 Mar 2020 00:00:00 +0000 Subject: [PATCH 0714/1250] Fix check for __msan_keep_going in sanitizer-recover test Match `@__msan_keep_going = weak_odr constant i32 1`. --- src/test/codegen/sanitizer-recover.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/codegen/sanitizer-recover.rs b/src/test/codegen/sanitizer-recover.rs index 9a583725b0b..05b4ab5653c 100644 --- a/src/test/codegen/sanitizer-recover.rs +++ b/src/test/codegen/sanitizer-recover.rs @@ -14,8 +14,8 @@ //[MSAN-RECOVER-LTO] compile-flags: -Zsanitizer=memory -Zsanitizer-recover=memory -C lto=fat // // MSAN-NOT: @__msan_keep_going -// MSAN-RECOVER: @__msan_keep_going = weak_odr {{.*}} constant i32 1 -// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}} constant i32 1 +// MSAN-RECOVER: @__msan_keep_going = weak_odr {{.*}}constant i32 1 +// MSAN-RECOVER-LTO: @__msan_keep_going = weak_odr {{.*}}constant i32 1 // ASAN-LABEL: define i32 @penguin( // ASAN: call void @__asan_report_load4(i64 %0) From 7ca1b2f504a77fd6d82c981242c577dae05f0b9e Mon Sep 17 00:00:00 2001 From: 12101111 Date: Tue, 3 Mar 2020 16:17:15 +0800 Subject: [PATCH 0715/1250] Don't use static crt by default when build proc-macro. --- src/librustc_codegen_ssa/back/link.rs | 10 +++--- src/librustc_codegen_utils/link.rs | 2 +- src/librustc_interface/util.rs | 2 +- src/librustc_metadata/dependency_format.rs | 4 +-- src/librustc_session/session.rs | 41 +++++++++++++++++----- src/test/ui/proc-macro/musl-proc-macro.rs | 15 ++++++++ 6 files changed, 57 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/proc-macro/musl-proc-macro.rs diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 90601521b19..387312addfa 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -497,7 +497,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.args(args); } if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) { - if sess.crt_static() { + if sess.crt_static(Some(crate_type)) { cmd.args(args); } } @@ -523,7 +523,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( cmd.arg(get_file_path(sess, obj)); } - if crate_type == config::CrateType::Executable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) { for obj in &sess.target.target.options.pre_link_objects_exe_crt { cmd.arg(get_file_path(sess, obj)); } @@ -558,7 +558,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( for obj in &sess.target.target.options.post_link_objects { cmd.arg(get_file_path(sess, obj)); } - if sess.crt_static() { + if sess.crt_static(Some(crate_type)) { for obj in &sess.target.target.options.post_link_objects_crt { cmd.arg(get_file_path(sess, obj)); } @@ -1288,7 +1288,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( let more_args = &sess.opts.cg.link_arg; let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); - if is_pic(sess) && !sess.crt_static() && !args.any(|x| *x == "-static") { + if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static") { position_independent_executable = true; } } @@ -1373,7 +1373,7 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( if crate_type != config::CrateType::Executable { cmd.build_dylib(out_filename); } - if crate_type == config::CrateType::Executable && sess.crt_static() { + if crate_type == config::CrateType::Executable && sess.crt_static(Some(crate_type)) { cmd.build_static_executable(); } diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index 524fb0a59c2..f80c19a79e2 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -167,7 +167,7 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) if !sess.target.target.options.dynamic_linking { return true; } - if sess.crt_static() && !sess.target.target.options.crt_static_allows_dylibs { + if sess.crt_static(Some(crate_type)) && !sess.target.target.options.crt_static_allows_dylibs { return true; } } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 10a8c0a63f1..ce0665a00ec 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -49,7 +49,7 @@ pub fn add_configuration( cfg.extend(codegen_backend.target_features(sess).into_iter().map(|feat| (tf, Some(feat)))); - if sess.crt_static_feature() { + if sess.crt_static_feature(None) { cfg.insert((tf, Some(Symbol::intern("crt-static")))); } } diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 9e71839dbfd..13cda397f24 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -97,7 +97,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // If the global prefer_dynamic switch is turned off, or the final // executable will be statically linked, prefer static crate linkage. - config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static() => { + config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => { Linkage::Static } config::CrateType::Executable => Linkage::Dynamic, @@ -129,7 +129,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // If any are not found, generate some nice pretty errors. if ty == config::CrateType::Staticlib || (ty == config::CrateType::Executable - && sess.crt_static() + && sess.crt_static(Some(ty)) && !sess.target.target.options.crt_static_allows_dylibs) { for &cnum in tcx.crates().iter() { diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 2fb7977dce9..dcd9ae44e88 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -540,25 +540,50 @@ impl Session { .unwrap_or(self.opts.debug_assertions) } - pub fn crt_static(&self) -> bool { + /// Check whether this compile session and crate type use static crt. + pub fn crt_static(&self, crate_type: Option) -> bool { // If the target does not opt in to crt-static support, use its default. if self.target.target.options.crt_static_respected { - self.crt_static_feature() + self.crt_static_feature(crate_type) } else { self.target.target.options.crt_static_default } } - pub fn crt_static_feature(&self) -> bool { + /// Check whether this compile session and crate type use `crt-static` feature. + pub fn crt_static_feature(&self, crate_type: Option) -> bool { let requested_features = self.opts.cg.target_feature.split(','); let found_negative = requested_features.clone().any(|r| r == "-crt-static"); let found_positive = requested_features.clone().any(|r| r == "+crt-static"); - // If the target we're compiling for requests a static crt by default, - // then see if the `-crt-static` feature was passed to disable that. - // Otherwise if we don't have a static crt by default then see if the - // `+crt-static` feature was passed. - if self.target.target.options.crt_static_default { !found_negative } else { found_positive } + if self.target.target.options.crt_static_default { + // `proc-macro` always required to be compiled to dylibs. + // We don't use a static crt unless the `+crt-static` feature was passed. + if !self.target.target.options.crt_static_allows_dylibs { + match crate_type { + Some(config::CrateType::ProcMacro) => found_positive, + Some(_) => !found_negative, + None => { + // FIXME: When crate_type is not available, + // we use compiler options to determine the crate_type. + // We can't check `#![crate_type = "proc-macro"]` here. + if self.opts.crate_types.contains(&config::CrateType::ProcMacro) { + found_positive + } else { + !found_negative + } + } + } + } else { + // If the target we're compiling for requests a static crt by default, + // then see if the `-crt-static` feature was passed to disable that. + !found_negative + } + } else { + // If the target we're compiling for don't have a static crt by default then see if the + // `+crt-static` feature was passed. + found_positive + } } pub fn must_not_eliminate_frame_pointers(&self) -> bool { diff --git a/src/test/ui/proc-macro/musl-proc-macro.rs b/src/test/ui/proc-macro/musl-proc-macro.rs new file mode 100644 index 00000000000..44abfcf129b --- /dev/null +++ b/src/test/ui/proc-macro/musl-proc-macro.rs @@ -0,0 +1,15 @@ +// Test proc-macro crate can be built without addtional RUSTFLAGS +// on musl target + +// run-pass +// compile-flags: --target=x86_64-unknown-linux-musl +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(Foo)] +pub fn derive_foo(input: TokenStream) -> TokenStream { + input +} From 7996df992fba0b7e09215843fcfabc0c53828c57 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Tue, 3 Mar 2020 16:29:44 +0800 Subject: [PATCH 0716/1250] Run format. --- src/librustc_codegen_ssa/back/link.rs | 3 ++- src/librustc_codegen_utils/link.rs | 4 +++- src/librustc_metadata/dependency_format.rs | 4 +++- src/librustc_session/session.rs | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 387312addfa..b6cf3a30211 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1288,7 +1288,8 @@ fn link_args<'a, B: ArchiveBuilder<'a>>( let more_args = &sess.opts.cg.link_arg; let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter()); - if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static") { + if is_pic(sess) && !sess.crt_static(Some(crate_type)) && !args.any(|x| *x == "-static") + { position_independent_executable = true; } } diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index f80c19a79e2..2850a29148e 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -167,7 +167,9 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: config::CrateType) if !sess.target.target.options.dynamic_linking { return true; } - if sess.crt_static(Some(crate_type)) && !sess.target.target.options.crt_static_allows_dylibs { + if sess.crt_static(Some(crate_type)) + && !sess.target.target.options.crt_static_allows_dylibs + { return true; } } diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 13cda397f24..4a9a9ddc4bd 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -97,7 +97,9 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: config::CrateType) -> DependencyList { // If the global prefer_dynamic switch is turned off, or the final // executable will be statically linked, prefer static crate linkage. - config::CrateType::Executable if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => { + config::CrateType::Executable + if !sess.opts.cg.prefer_dynamic || sess.crt_static(Some(ty)) => + { Linkage::Static } config::CrateType::Executable => Linkage::Dynamic, diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index dcd9ae44e88..619fbdcf7f8 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -564,7 +564,7 @@ impl Session { Some(config::CrateType::ProcMacro) => found_positive, Some(_) => !found_negative, None => { - // FIXME: When crate_type is not available, + // FIXME: When crate_type is not available, // we use compiler options to determine the crate_type. // We can't check `#![crate_type = "proc-macro"]` here. if self.opts.crate_types.contains(&config::CrateType::ProcMacro) { From 321d90e1d659c502ad633575866e6d972cf0cc5e Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 29 Feb 2020 04:34:50 +0900 Subject: [PATCH 0717/1250] Remove the `no_debug` feature --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 4 ---- src/librustc_codegen_llvm/debuginfo/mod.rs | 9 +-------- src/librustc_feature/active.rs | 3 --- src/librustc_feature/builtin_attrs.rs | 10 ---------- src/librustc_feature/removed.rs | 2 ++ src/librustc_typeck/collect.rs | 2 -- src/test/ui/lint/suggestions.rs | 4 ---- 7 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3916653eb1d..b6c2b141bd9 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -2269,10 +2269,6 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global let tcx = cx.tcx; let attrs = tcx.codegen_fn_attrs(def_id); - if attrs.flags.contains(CodegenFnAttrFlags::NO_DEBUG) { - return; - } - let no_mangle = attrs.flags.contains(CodegenFnAttrFlags::NO_MANGLE); // We may want to remove the namespace scope if we're in an extern block (see // https://github.com/rust-lang/rust/pull/46457#issuecomment-351750952). diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index 6515d5e3bec..a68441f14cb 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -12,7 +12,6 @@ use crate::llvm; use crate::llvm::debuginfo::{ DIArray, DIBuilder, DIFile, DIFlags, DILexicalBlock, DISPFlags, DIScope, DIType, DIVariable, }; -use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; @@ -22,7 +21,7 @@ use crate::common::CodegenCx; use crate::value::Value; use rustc::mir; use rustc::session::config::{self, DebugInfo}; -use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty}; +use rustc::ty::{self, Instance, ParamEnv, Ty}; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -241,12 +240,6 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { return None; } - if let InstanceDef::Item(def_id) = instance.def { - if self.tcx().codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_DEBUG) { - return None; - } - } - let span = mir.span; // This can be the case for functions inlined from another crate diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 0082f4f1a6e..c5bffd4a413 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -289,9 +289,6 @@ declare_features! ( /// Permits specifying whether a function should permit unwinding or abort on unwind. (active, unwind_attributes, "1.4.0", Some(58760), None), - /// Allows `#[no_debug]`. - (active, no_debug, "1.5.0", Some(29721), None), - /// Allows attributes on expressions and non-item statements. (active, stmt_expr_attributes, "1.6.0", Some(15701), None), diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e2e061c185c..735cd226b06 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -503,16 +503,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ cfg_fn!(rustc_attrs), ), ), - ( - sym::no_debug, Whitelisted, template!(Word), - Gated( - Stability::Deprecated("https://github.com/rust-lang/rust/issues/29721", None), - sym::no_debug, - "the `#[no_debug]` attribute was an experimental feature that has been \ - deprecated due to lack of demand", - cfg_fn!(no_debug) - ) - ), gated!( // Used in resolve: prelude_import, Whitelisted, template!(Word), diff --git a/src/librustc_feature/removed.rs b/src/librustc_feature/removed.rs index e6ea093fe89..4e348054fbd 100644 --- a/src/librustc_feature/removed.rs +++ b/src/librustc_feature/removed.rs @@ -111,6 +111,8 @@ declare_features! ( /// Allows overlapping impls of marker traits. (removed, overlapping_marker_traits, "1.42.0", Some(29864), None, Some("removed in favor of `#![feature(marker_trait_attr)]`")), + /// Allows `#[no_debug]`. + (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")), // ------------------------------------------------------------------------- // feature-group-end: removed features // ------------------------------------------------------------------------- diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2dad3d1d6d7..87179e2b69d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -2341,8 +2341,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_MANGLE; } else if attr.check_name(sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; - } else if attr.check_name(sym::no_debug) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::NO_DEBUG; } else if attr.check_name(sym::used) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; } else if attr.check_name(sym::thread_local) { diff --git a/src/test/ui/lint/suggestions.rs b/src/test/ui/lint/suggestions.rs index 29297d08dca..518b5f211e5 100644 --- a/src/test/ui/lint/suggestions.rs +++ b/src/test/ui/lint/suggestions.rs @@ -1,7 +1,6 @@ // ignore-tidy-tab #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 -#![feature(no_debug)] #[no_mangle] const DISCOVERY: usize = 1; //~^ ERROR const items should never be `#[no_mangle]` @@ -39,9 +38,6 @@ struct Equinox { warp_factor: f32, } -#[no_debug] // should suggest removal of deprecated attribute -//~^ WARN deprecated -//~| HELP remove this attribute fn main() { while true { //~^ WARN denote infinite loops From 45a30cdf1d2109655ff02683b6a6e41255cbeebe Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 29 Feb 2020 04:58:09 +0900 Subject: [PATCH 0718/1250] Update tests --- src/test/debuginfo/no-debug-attribute.rs | 37 ------------------- .../feature-gates/feature-gate-no-debug-2.rs | 5 --- .../feature-gate-no-debug-2.stderr | 14 ------- .../ui/feature-gates/feature-gate-no-debug.rs | 4 -- .../feature-gate-no-debug.stderr | 12 ------ src/test/ui/lint/suggestions.stderr | 30 ++++++--------- 6 files changed, 11 insertions(+), 91 deletions(-) delete mode 100644 src/test/debuginfo/no-debug-attribute.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-no-debug-2.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-no-debug-2.stderr delete mode 100644 src/test/ui/feature-gates/feature-gate-no-debug.rs delete mode 100644 src/test/ui/feature-gates/feature-gate-no-debug.stderr diff --git a/src/test/debuginfo/no-debug-attribute.rs b/src/test/debuginfo/no-debug-attribute.rs deleted file mode 100644 index db9ac4af629..00000000000 --- a/src/test/debuginfo/no-debug-attribute.rs +++ /dev/null @@ -1,37 +0,0 @@ -// ignore-lldb - -// compile-flags:-g - -// gdb-command:run - -// gdb-command:info locals -// gdb-check:No locals. -// gdb-command:continue - -// gdb-command:info locals -// gdb-check:abc = 10 -// gdb-command:continue - -#![allow(unused_variables)] -#![feature(no_debug)] -#![feature(omit_gdb_pretty_printer_section)] -#![omit_gdb_pretty_printer_section] - -#[inline(never)] -fn id(x: T) -> T {x} - -fn function_with_debuginfo() { - let abc = 10_usize; - id(abc); // #break -} - -#[no_debug] -fn function_without_debuginfo() { - let abc = -57i32; - id(abc); // #break -} - -fn main() { - function_without_debuginfo(); - function_with_debuginfo(); -} diff --git a/src/test/ui/feature-gates/feature-gate-no-debug-2.rs b/src/test/ui/feature-gates/feature-gate-no-debug-2.rs deleted file mode 100644 index b399bd2cc0f..00000000000 --- a/src/test/ui/feature-gates/feature-gate-no-debug-2.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![deny(deprecated)] -#![feature(no_debug)] - -#[no_debug] //~ ERROR use of deprecated attribute `no_debug` -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr b/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr deleted file mode 100644 index 9a6f898f2a5..00000000000 --- a/src/test/ui/feature-gates/feature-gate-no-debug-2.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721 - --> $DIR/feature-gate-no-debug-2.rs:4:1 - | -LL | #[no_debug] - | ^^^^^^^^^^^ help: remove this attribute - | -note: the lint level is defined here - --> $DIR/feature-gate-no-debug-2.rs:1:9 - | -LL | #![deny(deprecated)] - | ^^^^^^^^^^ - -error: aborting due to previous error - diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.rs b/src/test/ui/feature-gates/feature-gate-no-debug.rs deleted file mode 100644 index a472c4c7663..00000000000 --- a/src/test/ui/feature-gates/feature-gate-no-debug.rs +++ /dev/null @@ -1,4 +0,0 @@ -#![allow(deprecated)] - -#[no_debug] //~ ERROR the `#[no_debug]` attribute was -fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-no-debug.stderr b/src/test/ui/feature-gates/feature-gate-no-debug.stderr deleted file mode 100644 index e146d643bcb..00000000000 --- a/src/test/ui/feature-gates/feature-gate-no-debug.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand - --> $DIR/feature-gate-no-debug.rs:3:1 - | -LL | #[no_debug] - | ^^^^^^^^^^^ - | - = note: see issue #29721 for more information - = help: add `#![feature(no_debug)]` 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/lint/suggestions.stderr b/src/test/ui/lint/suggestions.stderr index 4e218ed0f1a..0ef5d72609a 100644 --- a/src/test/ui/lint/suggestions.stderr +++ b/src/test/ui/lint/suggestions.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/suggestions.rs:46:5 + --> $DIR/suggestions.rs:42:5 | LL | while true { | ^^^^^^^^^^ help: use `loop` @@ -7,7 +7,7 @@ LL | while true { = note: `#[warn(while_true)]` on by default warning: unnecessary parentheses around assigned value - --> $DIR/suggestions.rs:49:31 + --> $DIR/suggestions.rs:45:31 | LL | let mut registry_no = (format!("NX-{}", 74205)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses @@ -18,16 +18,8 @@ note: the lint level is defined here LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issue #43896 | ^^^^^^^^^^^^^ -warning: use of deprecated attribute `no_debug`: the `#[no_debug]` attribute was an experimental feature that has been deprecated due to lack of demand. See https://github.com/rust-lang/rust/issues/29721 - --> $DIR/suggestions.rs:42:1 - | -LL | #[no_debug] // should suggest removal of deprecated attribute - | ^^^^^^^^^^^ help: remove this attribute - | - = note: `#[warn(deprecated)]` on by default - warning: variable does not need to be mutable - --> $DIR/suggestions.rs:49:13 + --> $DIR/suggestions.rs:45:13 | LL | let mut registry_no = (format!("NX-{}", 74205)); | ----^^^^^^^^^^^ @@ -41,7 +33,7 @@ LL | #![warn(unused_mut, unused_parens)] // UI tests pass `-A unused`—see Issu | ^^^^^^^^^^ warning: variable does not need to be mutable - --> $DIR/suggestions.rs:55:13 + --> $DIR/suggestions.rs:51:13 | LL | let mut | _____________^ @@ -53,7 +45,7 @@ LL | || b = 1; | help: remove this `mut` error: const items should never be `#[no_mangle]` - --> $DIR/suggestions.rs:6:14 + --> $DIR/suggestions.rs:5:14 | LL | #[no_mangle] const DISCOVERY: usize = 1; | -----^^^^^^^^^^^^^^^^^^^^^^ @@ -63,7 +55,7 @@ LL | #[no_mangle] const DISCOVERY: usize = 1; = note: `#[deny(no_mangle_const_items)]` on by default warning: functions generic over types or consts must be mangled - --> $DIR/suggestions.rs:12:1 + --> $DIR/suggestions.rs:11:1 | LL | #[no_mangle] | ------------ help: remove this attribute @@ -74,7 +66,7 @@ LL | pub fn defiant(_t: T) {} = note: `#[warn(no_mangle_generic_items)]` on by default warning: the `warp_factor:` in this pattern is redundant - --> $DIR/suggestions.rs:61:23 + --> $DIR/suggestions.rs:57:23 | LL | Equinox { warp_factor: warp_factor } => {} | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use shorthand field pattern: `warp_factor` @@ -82,7 +74,7 @@ LL | Equinox { warp_factor: warp_factor } => {} = note: `#[warn(non_shorthand_field_patterns)]` on by default error: const items should never be `#[no_mangle]` - --> $DIR/suggestions.rs:22:18 + --> $DIR/suggestions.rs:21:18 | LL | #[no_mangle] pub const DAUNTLESS: bool = true; | ---------^^^^^^^^^^^^^^^^^^^^^^^^ @@ -90,7 +82,7 @@ LL | #[no_mangle] pub const DAUNTLESS: bool = true; | help: try a static value: `pub static` warning: functions generic over types or consts must be mangled - --> $DIR/suggestions.rs:25:18 + --> $DIR/suggestions.rs:24:18 | LL | #[no_mangle] pub fn val_jean() {} | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +90,7 @@ LL | #[no_mangle] pub fn val_jean() {} | help: remove this attribute error: const items should never be `#[no_mangle]` - --> $DIR/suggestions.rs:30:18 + --> $DIR/suggestions.rs:29:18 | LL | #[no_mangle] pub(crate) const VETAR: bool = true; | ----------------^^^^^^^^^^^^^^^^^^^^ @@ -106,7 +98,7 @@ LL | #[no_mangle] pub(crate) const VETAR: bool = true; | help: try a static value: `pub static` warning: functions generic over types or consts must be mangled - --> $DIR/suggestions.rs:33:18 + --> $DIR/suggestions.rs:32:18 | LL | #[no_mangle] pub(crate) fn crossfield() {} | ------------ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ecae6e4260311fac40ef76a84273f6bc865e63d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sun, 1 Mar 2020 22:04:42 +0100 Subject: [PATCH 0719/1250] use question mark operator in a few places. --- src/libcore/iter/adapters/mod.rs | 8 ++------ src/librustc/hir/map/mod.rs | 5 ++--- src/librustc/ty/instance.rs | 4 +--- src/librustc_incremental/persist/work_product.rs | 4 +--- 4 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs index 58606531a1a..02dc9b8f82e 100644 --- a/src/libcore/iter/adapters/mod.rs +++ b/src/libcore/iter/adapters/mod.rs @@ -1894,9 +1894,7 @@ where let to_skip = self.n; self.n = 0; // nth(n) skips n+1 - if self.iter.nth(to_skip - 1).is_none() { - return None; - } + self.iter.nth(to_skip - 1)?; } self.iter.nth(n) } @@ -1916,9 +1914,7 @@ where fn last(mut self) -> Option { if self.n > 0 { // nth(n) skips n+1 - if self.iter.nth(self.n - 1).is_none() { - return None; - } + self.iter.nth(self.n - 1)?; } self.iter.last() } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4f7c4153ea1..bd26e02efb7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -338,9 +338,8 @@ impl<'hir> Map<'hir> { Node::Variant(_) => DefKind::Variant, Node::Ctor(variant_data) => { // FIXME(eddyb) is this even possible, if we have a `Node::Ctor`? - if variant_data.ctor_hir_id().is_none() { - return None; - } + variant_data.ctor_hir_id()?; + let ctor_of = match self.find(self.get_parent_node(hir_id)) { Some(Node::Item(..)) => def::CtorOf::Struct, Some(Node::Variant(..)) => def::CtorOf::Variant, diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index f65822aba4c..4014d1d8ae2 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -115,9 +115,7 @@ impl<'tcx> Instance<'tcx> { } // If this a non-generic instance, it cannot be a shared monomorphization. - if self.substs.non_erasable_generics().next().is_none() { - return None; - } + self.substs.non_erasable_generics().next()?; match self.def { InstanceDef::Item(def_id) => tcx diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index 65a742a202d..b1861acec04 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -13,9 +13,7 @@ pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( files: &[(WorkProductFileKind, PathBuf)], ) -> Option<(WorkProductId, WorkProduct)> { debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files); - if sess.opts.incremental.is_none() { - return None; - } + sess.opts.incremental.as_ref()?; let saved_files = files .iter() From 89aebbdd7b6cea56284d53ab5aff5e62f1e67b67 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Tue, 3 Mar 2020 19:17:24 +0800 Subject: [PATCH 0720/1250] Only run this test on musl --- src/test/ui/proc-macro/musl-proc-macro.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/proc-macro/musl-proc-macro.rs b/src/test/ui/proc-macro/musl-proc-macro.rs index 44abfcf129b..f025a92c43e 100644 --- a/src/test/ui/proc-macro/musl-proc-macro.rs +++ b/src/test/ui/proc-macro/musl-proc-macro.rs @@ -1,8 +1,8 @@ // Test proc-macro crate can be built without addtional RUSTFLAGS // on musl target -// run-pass -// compile-flags: --target=x86_64-unknown-linux-musl +// build-pass +// only-musl #![crate_type = "proc-macro"] extern crate proc_macro; From 84349cc56492d70b37ec288f6f3e887858635fa4 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Tue, 3 Mar 2020 19:42:27 +0800 Subject: [PATCH 0721/1250] Remove trailing whitespace. --- src/test/ui/proc-macro/musl-proc-macro.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/proc-macro/musl-proc-macro.rs b/src/test/ui/proc-macro/musl-proc-macro.rs index f025a92c43e..223f00eb043 100644 --- a/src/test/ui/proc-macro/musl-proc-macro.rs +++ b/src/test/ui/proc-macro/musl-proc-macro.rs @@ -2,7 +2,7 @@ // on musl target // build-pass -// only-musl +// only-musl #![crate_type = "proc-macro"] extern crate proc_macro; From 3ab596514a34cf3f5ef75ec4ac9ddf2f0b4d268f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 22 Feb 2020 00:00:00 +0000 Subject: [PATCH 0722/1250] Improve linking of crates with circular dependencies Previously, the code responsible for handling the cycles between crates introduces through weak lang items, would keep a set of missing language items: * extending it with items missing from the current crate, * removing items provided by the current crate, * grouping the crates when the set changed from non-empty back to empty. This could produce incorrect results, if a lang item was missing from a crate that comes after the crate that provides it (in the loop iteration order). In that case the grouping would not take place. The changes here address this specific failure scenario by keeping track of two separate sets of crates. Those that are required to link successfully, and those that are available for linking. Verified using test case from 69368. --- src/librustc_codegen_ssa/back/link.rs | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 90601521b19..847b5b81d5a 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1519,17 +1519,25 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( // for the current implementation of the standard library. let mut group_end = None; let mut group_start = None; - let mut end_with = FxHashSet::default(); + // Crates available for linking thus far. + let mut available = FxHashSet::default(); + // Crates required to satisfy dependencies discovered so far. + let mut required = FxHashSet::default(); + let info = &codegen_results.crate_info; for &(cnum, _) in deps.iter().rev() { if let Some(missing) = info.missing_lang_items.get(&cnum) { - end_with.extend(missing.iter().cloned()); - if !end_with.is_empty() && group_end.is_none() { - group_end = Some(cnum); - } + let missing_crates = missing.iter().map(|i| info.lang_item_to_crate.get(i).copied()); + required.extend(missing_crates); + } + + required.insert(Some(cnum)); + available.insert(Some(cnum)); + + if required.len() > available.len() && group_end.is_none() { + group_end = Some(cnum); } - end_with.retain(|item| info.lang_item_to_crate.get(item) != Some(&cnum)); - if end_with.is_empty() && group_end.is_some() { + if required.len() == available.len() && group_end.is_some() { group_start = Some(cnum); break; } From 44dba79124c73585812fa781e425c8a0644c01ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 3 Mar 2020 00:00:00 +0000 Subject: [PATCH 0723/1250] Add regression test for linking issue with start-group / end-group --- .../run-make-fulldeps/issue-69368/Makefile | 18 ++++++++++ src/test/run-make-fulldeps/issue-69368/a.rs | 16 +++++++++ src/test/run-make-fulldeps/issue-69368/b.rs | 8 +++++ src/test/run-make-fulldeps/issue-69368/c.rs | 34 +++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 src/test/run-make-fulldeps/issue-69368/Makefile create mode 100644 src/test/run-make-fulldeps/issue-69368/a.rs create mode 100644 src/test/run-make-fulldeps/issue-69368/b.rs create mode 100644 src/test/run-make-fulldeps/issue-69368/c.rs diff --git a/src/test/run-make-fulldeps/issue-69368/Makefile b/src/test/run-make-fulldeps/issue-69368/Makefile new file mode 100644 index 00000000000..dbb044d8f5d --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/Makefile @@ -0,0 +1,18 @@ +-include ../tools.mk + +# Test that previously triggered a linker failure with root cause +# similar to one found in the issue #69368. +# +# The crate that provides oom lang item is missing some other lang +# items. Necessary to prevent the use of start-group / end-group. +# +# The weak lang items are defined in a separate compilation units, +# so that linker could omit them if not used. +# +# The crates that need those weak lang items are dependencies of +# crates that provide them. + +all: + $(RUSTC) a.rs + $(RUSTC) b.rs + $(RUSTC) c.rs diff --git a/src/test/run-make-fulldeps/issue-69368/a.rs b/src/test/run-make-fulldeps/issue-69368/a.rs new file mode 100644 index 00000000000..726db874637 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/a.rs @@ -0,0 +1,16 @@ +#![crate_type = "rlib"] +#![feature(lang_items)] +#![feature(panic_unwind)] +#![no_std] + +extern crate panic_unwind; + +#[panic_handler] +pub fn panic_handler(_: &core::panic::PanicInfo) -> ! { + loop {} +} + +#[no_mangle] +extern "C" fn __rust_drop_panic() -> ! { + loop {} +} diff --git a/src/test/run-make-fulldeps/issue-69368/b.rs b/src/test/run-make-fulldeps/issue-69368/b.rs new file mode 100644 index 00000000000..4d6af026656 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/b.rs @@ -0,0 +1,8 @@ +#![crate_type = "rlib"] +#![feature(alloc_error_handler)] +#![no_std] + +#[alloc_error_handler] +pub fn error_handler(_: core::alloc::Layout) -> ! { + panic!(); +} diff --git a/src/test/run-make-fulldeps/issue-69368/c.rs b/src/test/run-make-fulldeps/issue-69368/c.rs new file mode 100644 index 00000000000..729c4249a05 --- /dev/null +++ b/src/test/run-make-fulldeps/issue-69368/c.rs @@ -0,0 +1,34 @@ +#![crate_type = "bin"] +#![feature(start)] +#![no_std] + +extern crate alloc; +extern crate a; +extern crate b; + +use alloc::vec::Vec; +use core::alloc::*; + +struct Allocator; + +unsafe impl GlobalAlloc for Allocator { + unsafe fn alloc(&self, _: Layout) -> *mut u8 { + loop {} + } + + unsafe fn dealloc(&self, _: *mut u8, _: Layout) { + loop {} + } +} + +#[global_allocator] +static ALLOCATOR: Allocator = Allocator; + +#[start] +fn main(argc: isize, _argv: *const *const u8) -> isize { + let mut v = Vec::new(); + for i in 0..argc { + v.push(i); + } + v.iter().sum() +} From c92267a86393df927feccd3d03894a6cfe92dea8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Mar 2020 13:30:17 +0100 Subject: [PATCH 0724/1250] Add explanation for E0379 --- src/librustc_error_codes/error_codes/E0379.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/librustc_error_codes/error_codes/E0379.md b/src/librustc_error_codes/error_codes/E0379.md index 3503da6ac2f..930204847ec 100644 --- a/src/librustc_error_codes/error_codes/E0379.md +++ b/src/librustc_error_codes/error_codes/E0379.md @@ -1,3 +1,15 @@ +A trait method was declared const. + +Erroneous code example: + +```compile_fail,E0379 +#![feature(const_fn)] + +trait Foo { + const fn bar() -> u32; // error! +} +``` + Trait methods cannot be declared `const` by design. For more information, see [RFC 911]. From 98c7ed67fb00c3eac8f1baa3ea24bc903f83e550 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 3 Mar 2020 12:29:07 -0600 Subject: [PATCH 0725/1250] DefKind::Method -> DefKind::AssocFn --- src/librustc/hir/map/mod.rs | 4 ++-- src/librustc/middle/stability.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc/ty/mod.rs | 6 +++--- src/librustc_ast_lowering/path.rs | 2 +- src/librustc_hir/def.rs | 7 ++++--- src/librustc_infer/infer/error_reporting/need_type_info.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 2 +- src/librustc_mir/util/pretty.rs | 2 +- src/librustc_mir_build/hair/cx/expr.rs | 4 ++-- src/librustc_privacy/lib.rs | 4 ++-- src/librustc_resolve/build_reduced_graph.rs | 6 +++--- src/librustc_resolve/late.rs | 4 ++-- src/librustc_resolve/late/diagnostics.rs | 2 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/generator_interior.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 ++-- src/librustc_typeck/check/pat.rs | 6 +++--- src/librustc_typeck/mem_categorization.rs | 2 +- src/librustdoc/passes/collect_intra_doc_links.rs | 4 ++-- 23 files changed, 38 insertions(+), 37 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4f7c4153ea1..2374d47ae8e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -326,12 +326,12 @@ impl<'hir> Map<'hir> { }, Node::TraitItem(item) => match item.kind { TraitItemKind::Const(..) => DefKind::AssocConst, - TraitItemKind::Method(..) => DefKind::Method, + TraitItemKind::Method(..) => DefKind::AssocFn, TraitItemKind::Type(..) => DefKind::AssocTy, }, Node::ImplItem(item) => match item.kind { ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Method(..) => DefKind::Method, + ImplItemKind::Method(..) => DefKind::AssocFn, ImplItemKind::TyAlias(..) => DefKind::AssocTy, ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, }, diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 9d3df9623bd..1f6725fb395 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -250,7 +250,7 @@ pub enum EvalResult { fn skip_stability_check_due_to_privacy(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool { // Check if `def_id` is a trait method. match tcx.def_kind(def_id) { - Some(DefKind::Method) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => { + Some(DefKind::AssocFn) | Some(DefKind::AssocTy) | Some(DefKind::AssocConst) => { if let ty::TraitContainer(trait_def_id) = tcx.associated_item(def_id).container { // Trait methods do not declare visibility (even // for visibility info in cstore). Use containing diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 20736b50831..ec9ff55ffe4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -611,7 +611,7 @@ impl<'tcx> TypeckTables<'tcx> { } match self.type_dependent_defs().get(expr.hir_id) { - Some(Ok((DefKind::Method, _))) => true, + Some(Ok((DefKind::AssocFn, _))) => true, _ => false, } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b25fd3c61fd..546686c20ca 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -230,7 +230,7 @@ impl AssocItem { pub fn def_kind(&self) -> DefKind { match self.kind { AssocKind::Const => DefKind::AssocConst, - AssocKind::Method => DefKind::Method, + AssocKind::Method => DefKind::AssocFn, AssocKind::Type => DefKind::AssocTy, AssocKind::OpaqueTy => DefKind::AssocOpaqueTy, } @@ -2872,7 +2872,7 @@ impl<'tcx> TyCtxt<'tcx> { } } else { match self.def_kind(def_id).expect("no def for `DefId`") { - DefKind::AssocConst | DefKind::Method | DefKind::AssocTy => true, + DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => true, _ => false, } }; @@ -3051,7 +3051,7 @@ impl<'tcx> TyCtxt<'tcx> { /// `DefId` of the impl that the method belongs to; otherwise, returns `None`. pub fn impl_of_method(self, def_id: DefId) -> Option { let item = if def_id.krate != LOCAL_CRATE { - if let Some(DefKind::Method) = self.def_kind(def_id) { + if let Some(DefKind::AssocFn) = self.def_kind(def_id) { Some(self.associated_item(def_id)) } else { None diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index 80d7e3d0d46..db8517bfbf0 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -75,7 +75,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ParenthesizedGenericArgs::Ok } // `a::b::Trait(Args)::TraitItem` - Res::Def(DefKind::Method, _) + Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocTy, _) if i + 2 == proj_start => diff --git a/src/librustc_hir/def.rs b/src/librustc_hir/def.rs index 595543eaf53..5b2c1453de6 100644 --- a/src/librustc_hir/def.rs +++ b/src/librustc_hir/def.rs @@ -72,7 +72,7 @@ pub enum DefKind { Static, /// Refers to the struct or enum variant's constructor. Ctor(CtorOf, CtorKind), - Method, + AssocFn, AssocConst, // Macro namespace @@ -107,7 +107,8 @@ impl DefKind { DefKind::Union => "union", DefKind::Trait => "trait", DefKind::ForeignTy => "foreign type", - DefKind::Method => "method", + // FIXME: Update the description to "assoc fn" + DefKind::AssocFn => "method", DefKind::Const => "constant", DefKind::AssocConst => "associated constant", DefKind::TyParam => "type parameter", @@ -150,7 +151,7 @@ impl DefKind { | DefKind::ConstParam | DefKind::Static | DefKind::Ctor(..) - | DefKind::Method + | DefKind::AssocFn | DefKind::AssocConst => ns == Namespace::ValueNS, DefKind::Macro(..) => ns == Namespace::MacroNS, diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index a1e6a0a325a..56f8c8c2b9c 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -468,7 +468,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &segment.args, ) { let borrow = tables.borrow(); - if let Some((DefKind::Method, did)) = borrow.type_dependent_def(e.hir_id) { + if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) { let generics = self.tcx.generics_of(did); if !generics.params.is_empty() { err.span_suggestion( diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 02f04b23459..49d05819c5e 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -54,7 +54,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { match callee.kind { hir::ExprKind::Path(ref qpath) => { match cx.tables.qpath_res(qpath, callee.hir_id) { - Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::Method, def_id) => { + Res::Def(DefKind::Fn, def_id) | Res::Def(DefKind::AssocFn, def_id) => { Some(def_id) } // `Res::Local` if it was a closure, for which we diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a72ee0cbe47..d0a35c61564 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -504,7 +504,7 @@ impl EntryKind { EntryKind::Struct(_, _) => DefKind::Struct, EntryKind::Union(_, _) => DefKind::Union, EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn, - EntryKind::Method(_) => DefKind::Method, + EntryKind::Method(_) => DefKind::AssocFn, EntryKind::Type => DefKind::TyAlias, EntryKind::TypeParam => DefKind::TyParam, EntryKind::ConstParam => DefKind::ConstParam, diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6fd8f06fe8f..ee8de0e6b93 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -545,7 +545,7 @@ fn write_mir_sig( trace!("write_mir_sig: {:?}", src.instance); let kind = tcx.def_kind(src.def_id()); let is_function = match kind { - Some(DefKind::Fn) | Some(DefKind::Method) | Some(DefKind::Ctor(..)) => true, + Some(DefKind::Fn) | Some(DefKind::AssocFn) | Some(DefKind::Ctor(..)) => true, _ => tcx.is_closure(src.def_id()), }; match (kind, src.promoted) { diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 46d49b6b493..9f04bc1dc76 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -600,7 +600,7 @@ fn user_substs_applied_to_res<'tcx>( // a tuple-struct or tuple-variant. This has the type of a // `Fn` but with the user-given substitutions. Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { @@ -703,7 +703,7 @@ fn convert_path_expr<'a, 'tcx>( match res { // A regular function, constructor function or a constant. Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(..) => { let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 24696b20332..175b2390d30 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -620,7 +620,7 @@ impl EmbargoVisitor<'tcx> { | DefKind::ForeignTy | DefKind::Fn | DefKind::OpaqueTy - | DefKind::Method + | DefKind::AssocFn | DefKind::Trait | DefKind::TyParam | DefKind::Variant => (), @@ -1298,7 +1298,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { _ => None, }; let def = def.filter(|(kind, _)| match kind { - DefKind::Method + DefKind::AssocFn | DefKind::AssocConst | DefKind::AssocTy | DefKind::AssocOpaqueTy diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 86816fd9f3a..1fc99e40d83 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -887,7 +887,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { | Res::PrimTy(..) | Res::ToolMod => self.r.define(parent, ident, TypeNS, (res, vis, span, expansion)), Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Static, _) | Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) @@ -911,7 +911,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let field_names = cstore.struct_field_names_untracked(def_id, self.r.session); self.insert_field_names(def_id, field_names); } - Res::Def(DefKind::Method, def_id) => { + Res::Def(DefKind::AssocFn, def_id) => { if cstore.associated_item_cloned_untracked(def_id).method_has_self_argument { self.r.has_self.insert(def_id); } @@ -1257,7 +1257,7 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { if sig.decl.has_self() { self.r.has_self.insert(item_def_id); } - (Res::Def(DefKind::Method, item_def_id), ValueNS) + (Res::Def(DefKind::AssocFn, item_def_id), ValueNS) } AssocItemKind::TyAlias(..) => (Res::Def(DefKind::AssocTy, item_def_id), TypeNS), AssocItemKind::Macro(_) => bug!(), // handled above diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index e5aa9c7d896..640b07d3d62 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -266,7 +266,7 @@ impl<'a> PathSource<'a> { | Res::Def(DefKind::Static, _) | Res::Local(..) | Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocConst, _) | Res::SelfCtor(..) | Res::Def(DefKind::ConstParam, _) => true, @@ -293,7 +293,7 @@ impl<'a> PathSource<'a> { _ => false, }, PathSource::TraitItem(ns) => match res { - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) + Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) if ns == ValueNS => { true diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 817a276ff3e..a9463d970ce 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -124,7 +124,7 @@ impl<'a> LateResolutionVisitor<'a, '_, '_> { .unwrap_or(false) } Res::Def(DefKind::Ctor(..), _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) | Res::SelfCtor(_) diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 44eba0d533d..3a393314463 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -742,7 +742,7 @@ impl<'a> NameBinding<'a> { fn is_importable(&self) -> bool { match self.res() { Res::Def(DefKind::AssocConst, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocTy, _) => false, _ => true, } diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index c68289adb10..2bd335421e0 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -716,7 +716,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { | Res::Def(HirDefKind::Ctor(..), _) => { Some(Ref { kind: RefKind::Variable, span, ref_id: id_from_def_id(res.def_id()) }) } - Res::Def(HirDefKind::Method, decl_id) => { + Res::Def(HirDefKind::AssocFn, decl_id) => { let def_id = if decl_id.is_local() { let ti = self.tcx.associated_item(decl_id); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 199b476cb9a..d59923a0019 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -2588,7 +2588,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } // Case 4. Reference to a method or associated const. - DefKind::Method | DefKind::AssocConst => { + DefKind::AssocFn | DefKind::AssocConst => { if segments.len() >= 2 { let generics = tcx.generics_of(def_id); path_segs.push(PathSeg(generics.parent.unwrap(), last - 1)); diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 50692e0f104..7e526573773 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -237,7 +237,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { // ZST in a temporary, so skip its type, just in case it // can significantly complicate the generator type. Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { // NOTE(eddyb) this assumes a path expression has // no nested expressions to keep track of. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b7353c6af26..fd5cac5b24b 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2976,7 +2976,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn write_method_call(&self, hir_id: hir::HirId, method: MethodCallee<'tcx>) { debug!("write_method_call(hir_id={:?}, method={:?})", hir_id, method); - self.write_resolution(hir_id, Ok((DefKind::Method, method.def_id))); + self.write_resolution(hir_id, Ok((DefKind::AssocFn, method.def_id))); self.write_substs(hir_id, method.substs); // When the method is confirmed, the `method.substs` includes @@ -5364,7 +5364,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { is_alias_variant_ctor = true; } } - Res::Def(DefKind::Method, def_id) | Res::Def(DefKind::AssocConst, def_id) => { + Res::Def(DefKind::AssocFn, def_id) | Res::Def(DefKind::AssocConst, def_id) => { let container = tcx.associated_item(def_id).container; debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container); match container { diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b7aac707a98..c50274d19e3 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -682,7 +682,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.set_tainted_by_errors(); return tcx.types.err; } - Res::Def(DefKind::Method, _) + Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Ctor(_, CtorKind::Fictive), _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) => { report_unexpected_variant_res(tcx, res, pat.span, qpath); @@ -729,7 +729,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); let mut err = struct_span_err!(tcx.sess, pat.span, E0164, "{}", msg); match (res, &pat.kind) { - (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::Method, _), _) => { + (Res::Def(DefKind::Fn, _), _) | (Res::Def(DefKind::AssocFn, _), _) => { err.span_label(pat.span, "`fn` calls are not allowed in patterns"); err.help( "for more information, visit \ @@ -766,7 +766,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { on_error(); return tcx.types.err; } - Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Method, _) => { + Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::AssocFn, _) => { report_unexpected_res(res); return tcx.types.err; } diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index a4569a14756..8e06948a109 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -425,7 +425,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { | Res::Def(DefKind::ConstParam, _) | Res::Def(DefKind::AssocConst, _) | Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::Method, _) + | Res::Def(DefKind::AssocFn, _) | Res::SelfCtor(..) => Ok(self.cat_rvalue(hir_id, span, expr_ty)), Res::Def(DefKind::Static, _) => Ok(Place { diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 7aa90d66781..75355b84fee 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { // In case this is a trait item, skip the // early return and try looking for the trait. let value = match res { - Res::Def(DefKind::Method, _) | Res::Def(DefKind::AssocConst, _) => true, + Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::AssocConst, _) => true, Res::Def(DefKind::AssocTy, _) => false, Res::Def(DefKind::Variant, _) => { return handle_variant(cx, res, extra_fragment); @@ -813,7 +813,7 @@ fn ambiguity_error( for (res, ns) in candidates { let (action, mut suggestion) = match res { - Res::Def(DefKind::Method, _) | Res::Def(DefKind::Fn, _) => { + Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Fn, _) => { ("add parentheses", format!("{}()", path_str)) } Res::Def(DefKind::Macro(..), _) => { From 3aeb9f0fafd33a425a67b7ee44f30f98dde64642 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 3 Mar 2020 12:46:22 -0600 Subject: [PATCH 0726/1250] rename TraitItemKind::Method -> Fn --- src/librustc/hir/map/blocks.rs | 4 ++-- src/librustc/hir/map/mod.rs | 14 +++++++------- src/librustc_ast_lowering/item.rs | 4 ++-- src/librustc_hir/hir.rs | 6 +++--- src/librustc_hir/intravisit.rs | 4 ++-- src/librustc_hir/print.rs | 4 ++-- src/librustc_hir/target.rs | 4 ++-- src/librustc_incremental/persist/dirty_clean.rs | 2 +- src/librustc_infer/infer/error_reporting/mod.rs | 2 +- .../nice_region_error/find_anon_type.rs | 2 +- .../traits/error_reporting/on_unimplemented.rs | 2 +- .../traits/error_reporting/suggestions.rs | 6 +++--- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/nonstandard_style.rs | 2 +- src/librustc_metadata/rmeta/encoder.rs | 2 +- .../borrow_check/diagnostics/mutability_errors.rs | 4 ++-- src/librustc_mir_build/build/mod.rs | 2 +- src/librustc_passes/dead.rs | 6 +++--- src/librustc_passes/reachable.rs | 8 ++++---- src/librustc_resolve/late/lifetimes.rs | 9 +++------ src/librustc_traits/lowering/environment.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 10 +++++----- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 10 +++++----- src/librustc_typeck/check/wfcheck.rs | 4 ++-- src/librustc_typeck/collect.rs | 8 ++++---- src/librustc_typeck/collect/type_of.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustc_typeck/variance/mod.rs | 2 +- src/librustc_typeck/variance/terms.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- 31 files changed, 67 insertions(+), 70 deletions(-) diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 618f9a018d1..d9ffe4582e7 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -60,7 +60,7 @@ impl MaybeFnLike for hir::ImplItem<'_> { impl MaybeFnLike for hir::TraitItem<'_> { fn is_fn_like(&self) -> bool { match self.kind { - hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, _ => false, } } @@ -239,7 +239,7 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, Node::TraitItem(ti) => match ti.kind { - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 2374d47ae8e..9d2cc1877e4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -51,7 +51,7 @@ impl<'hir> Entry<'hir> { }, Node::TraitItem(ref item) => match item.kind { - TraitItemKind::Method(ref sig, _) => Some(&sig.decl), + TraitItemKind::Fn(ref sig, _) => Some(&sig.decl), _ => None, }, @@ -77,7 +77,7 @@ impl<'hir> Entry<'hir> { }, Node::TraitItem(item) => match &item.kind { - TraitItemKind::Method(sig, _) => Some(sig), + TraitItemKind::Fn(sig, _) => Some(sig), _ => None, }, @@ -101,7 +101,7 @@ impl<'hir> Entry<'hir> { Node::TraitItem(item) => match item.kind { TraitItemKind::Const(_, Some(body)) - | TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), + | TraitItemKind::Fn(_, TraitMethod::Provided(body)) => Some(body), _ => None, }, @@ -326,7 +326,7 @@ impl<'hir> Map<'hir> { }, Node::TraitItem(item) => match item.kind { TraitItemKind::Const(..) => DefKind::AssocConst, - TraitItemKind::Method(..) => DefKind::AssocFn, + TraitItemKind::Fn(..) => DefKind::AssocFn, TraitItemKind::Type(..) => DefKind::AssocTy, }, Node::ImplItem(item) => match item.kind { @@ -473,7 +473,7 @@ impl<'hir> Map<'hir> { | Node::AnonConst(_) => BodyOwnerKind::Const, Node::Ctor(..) | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) - | Node::TraitItem(&TraitItem { kind: TraitItemKind::Method(..), .. }) + | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn, Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, @@ -801,7 +801,7 @@ impl<'hir> Map<'hir> { _ => false, }, Node::TraitItem(ti) => match ti.kind { - TraitItemKind::Method(..) => true, + TraitItemKind::Fn(..) => true, _ => false, }, Node::ImplItem(ii) => match ii.kind { @@ -1312,7 +1312,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::TraitItem(ti)) => { let kind = match ti.kind { TraitItemKind::Const(..) => "assoc constant", - TraitItemKind::Method(..) => "trait method", + TraitItemKind::Fn(..) => "trait method", TraitItemKind::Type(..) => "assoc type", }; diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 13148d97a67..f732f645dc0 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -767,13 +767,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Required(names))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Required(names))) } AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Method(sig, hir::TraitMethod::Provided(body_id))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Provided(body_id))) } AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index f948e22e84b..5a83c65204c 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1863,8 +1863,8 @@ pub enum TraitMethod<'hir> { pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option), - /// A method with an optional body. - Method(FnSig<'hir>, TraitMethod<'hir>), + /// An associated function with an optional body. + Fn(FnSig<'hir>, TraitMethod<'hir>), /// An associated type with (possibly empty) bounds and optional concrete /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), @@ -2699,7 +2699,7 @@ impl Node<'_> { pub fn fn_decl(&self) -> Option<&FnDecl<'_>> { match self { - Node::TraitItem(TraitItem { kind: TraitItemKind::Method(fn_sig, _), .. }) + Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 45257b04d79..e92192c8b1f 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -911,14 +911,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_ty(ty); walk_list!(visitor, visit_nested_body, default); } - TraitItemKind::Method(ref sig, TraitMethod::Required(param_names)) => { + TraitItemKind::Fn(ref sig, TraitMethod::Required(param_names)) => { visitor.visit_id(trait_item.hir_id); visitor.visit_fn_decl(&sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } - TraitItemKind::Method(ref sig, TraitMethod::Provided(body_id)) => { + TraitItemKind::Fn(ref sig, TraitMethod::Provided(body_id)) => { visitor.visit_fn( FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs), &sig.decl, diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 8cbbef959ce..7738548dade 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -886,13 +886,13 @@ impl<'a> State<'a> { Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_associated_const(ti.ident, &ty, default, &vis); } - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref arg_names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref arg_names)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); self.s.word(";"); } - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.head(""); diff --git a/src/librustc_hir/target.rs b/src/librustc_hir/target.rs index 501976fc3cb..b7bc555d7b4 100644 --- a/src/librustc_hir/target.rs +++ b/src/librustc_hir/target.rs @@ -105,10 +105,10 @@ impl Target { pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target { match trait_item.kind { TraitItemKind::Const(..) => Target::AssocConst, - TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { + TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { Target::Method(MethodKind::Trait { body: false }) } - TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { + TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { Target::Method(MethodKind::Trait { body: true }) } TraitItemKind::Type(..) => Target::AssocTy, diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index f304292d922..86c3fbcf8c7 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -328,7 +328,7 @@ impl DirtyCleanVisitor<'tcx> { } } HirNode::TraitItem(item) => match item.kind { - TraitItemKind::Method(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT), + TraitItemKind::Fn(..) => ("Node::TraitItem", LABELS_FN_IN_TRAIT), TraitItemKind::Const(..) => ("NodeTraitConst", LABELS_CONST_IN_TRAIT), TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), }, diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index bd133738db7..9185c467023 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -269,7 +269,7 @@ fn item_scope_tag(item: &hir::Item<'_>) -> &'static str { fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { match item.kind { - hir::TraitItemKind::Method(..) => "method body", + hir::TraitItemKind::Fn(..) => "method body", hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item", } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index 2ae7f4cc04f..7346cb0a033 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -33,7 +33,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { let fndecl = match self.tcx().hir().get(hir_id) { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(ref m, ..), .. }) | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Method(ref m, ..), + kind: hir::TraitItemKind::Fn(ref m, ..), .. }) | Node::ImplItem(&hir::ImplItem { diff --git a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs index 87c1107bd42..eb34a487596 100644 --- a/src/librustc_infer/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_infer/traits/error_reporting/on_unimplemented.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) } hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)), .. }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")), hir::Node::ImplItem(hir::ImplItem { diff --git a/src/librustc_infer/traits/error_reporting/suggestions.rs b/src/librustc_infer/traits/error_reporting/suggestions.rs index ed6cfa51cdf..e8575cd2c47 100644 --- a/src/librustc_infer/traits/error_reporting/suggestions.rs +++ b/src/librustc_infer/traits/error_reporting/suggestions.rs @@ -62,7 +62,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { match node { hir::Node::TraitItem(hir::TraitItem { generics, - kind: hir::TraitItemKind::Method(..), + kind: hir::TraitItemKind::Fn(..), .. }) if param_ty && self_ty == self.tcx.types.self_param => { // Restricting `Self` for a single method. @@ -73,7 +73,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(_, generics, _), .. }) | hir::Node::TraitItem(hir::TraitItem { generics, - kind: hir::TraitItemKind::Method(..), + kind: hir::TraitItemKind::Fn(..), .. }) | hir::Node::ImplItem(hir::ImplItem { @@ -807,7 +807,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { }) | Node::TraitItem(&hir::TraitItem { span, - kind: hir::TraitItemKind::Method(ref sig, _), + kind: hir::TraitItemKind::Fn(ref sig, _), .. }) => ( self.tcx.sess.source_map().def_span(span), diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3eecd2a54e3..c8bffc4d445 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -465,7 +465,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let desc = match trait_item.kind { hir::TraitItemKind::Const(..) => "an associated constant", - hir::TraitItemKind::Method(..) => "a trait method", + hir::TraitItemKind::Fn(..) => "a trait method", hir::TraitItemKind::Type(..) => "an associated type", }; diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index b0560dc9fdf..37fefe680d7 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -343,7 +343,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Method(_, hir::TraitMethod::Required(pnames)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { self.check_snake_case(cx, "variable", param_name); diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ea0cc2f0c8b..b89cd0792b8 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -805,7 +805,7 @@ impl EncodeContext<'tcx> { ) } ty::AssocKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(m_sig, m) = &ast_item.kind { + let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind { let param_names = match *m { hir::TraitMethod::Required(ref names) => { self.encode_fn_param_names(names) diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index d91f6edc980..7ebc164e49c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -478,7 +478,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { })) | Some(hir::Node::TraitItem(hir::TraitItem { ident, - kind: hir::TraitItemKind::Method(sig, _), + kind: hir::TraitItemKind::Fn(sig, _), .. })) | Some(hir::Node::ImplItem(hir::ImplItem { @@ -520,7 +520,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hir::Node::Item(hir::Item { ident, kind: hir::ItemKind::Fn(sig, ..), .. }) | hir::Node::TraitItem(hir::TraitItem { ident, - kind: hir::TraitItemKind::Method(sig, _), + kind: hir::TraitItemKind::Fn(sig, _), .. }) | hir::Node::ImplItem(hir::ImplItem { diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 830877f713e..4cd1efe4ef9 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -44,7 +44,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { }) | Node::TraitItem(hir::TraitItem { kind: - hir::TraitItemKind::Method(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)), + hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)), .. }) => (*body_id, decl.output.span()), Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. }) diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index bcf9fd5a535..4a0ffc23365 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -391,7 +391,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.kind { hir::TraitItemKind::Const(_, Some(_)) - | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { if has_allow_dead_code_or_lang_attr( self.tcx, trait_item.hir_id, @@ -682,11 +682,11 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { match trait_item.kind { hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { self.visit_nested_body(body_id) } hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) + | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Type(..) => {} } } diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 888f4370dd5..79a9f226030 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -162,8 +162,8 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { }, Some(Node::TraitItem(trait_method)) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), - hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(_)) => true, - hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) + hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) | hir::TraitItemKind::Type(..) => false, }, Some(Node::ImplItem(impl_item)) => { @@ -278,11 +278,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::TraitItem(trait_method) => { match trait_method.kind { hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Method(_, hir::TraitMethod::Required(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { // Keep going, nothing to get exported } hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Method(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { self.visit_nested_body(body_id); } hir::TraitItemKind::Type(..) => {} diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 193b6d75935..280acfe8c48 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -713,7 +713,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::TraitItemKind::*; self.missing_named_lifetime_spots.push((&trait_item.generics).into()); match trait_item.kind { - Method(ref sig, _) => { + Fn(ref sig, _) => { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(trait_item.hir_id)), @@ -1816,8 +1816,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { match self.tcx.hir().get(fn_id) { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) | Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Method(..), - .. + kind: hir::TraitItemKind::Fn(..), .. }) | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. @@ -2093,9 +2092,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // `fn` definitions and methods. Node::Item(&hir::Item { kind: hir::ItemKind::Fn(.., body), .. }) => Some(body), - Node::TraitItem(&hir::TraitItem { - kind: hir::TraitItemKind::Method(_, ref m), .. - }) => { + Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(_, ref m), .. }) => { if let hir::ItemKind::Trait(.., ref trait_items) = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index 0e26e9461f4..db392ede432 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -185,7 +185,7 @@ crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> { let node_kind = match node { Node::TraitItem(item) => match item.kind { - TraitItemKind::Method(..) => NodeKind::Fn, + TraitItemKind::Fn(..) => NodeKind::Fn, _ => NodeKind::Other, }, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 8b54b534375..0c8dec8f8d4 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -412,8 +412,8 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( TypeError::Mutability => { if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) { let trait_m_iter = match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Method(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(), - _ => bug!("{:?} is not a TraitItemKind::Method", trait_m), + TraitItemKind::Fn(ref trait_m_sig, _) => trait_m_sig.decl.inputs.iter(), + _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), }; impl_m_iter @@ -440,10 +440,10 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( if let Some(trait_m_hir_id) = tcx.hir().as_local_hir_id(trait_m.def_id) { let (trait_m_output, trait_m_iter) = match tcx.hir().expect_trait_item(trait_m_hir_id).kind { - TraitItemKind::Method(ref trait_m_sig, _) => { + TraitItemKind::Fn(ref trait_m_sig, _) => { (&trait_m_sig.decl.output, trait_m_sig.decl.inputs.iter()) } - _ => bug!("{:?} is not a TraitItemKind::Method", trait_m), + _ => bug!("{:?} is not a TraitItemKind::Fn", trait_m), }; let impl_iter = impl_sig.inputs().iter(); @@ -708,7 +708,7 @@ fn compare_number_of_method_arguments<'tcx>( let trait_m_hir_id = tcx.hir().as_local_hir_id(trait_m.def_id); let trait_span = if let Some(trait_id) = trait_m_hir_id { match tcx.hir().expect_trait_item(trait_id).kind { - TraitItemKind::Method(ref trait_m_sig, _) => { + TraitItemKind::Fn(ref trait_m_sig, _) => { let pos = if trait_number_args > 0 { trait_number_args - 1 } else { 0 }; if let Some(arg) = trait_m_sig.decl.inputs.get(pos) { Some(if pos == 0 { diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 95faa353e9b..9e3b4a7be72 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -930,7 +930,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let ty::AssocKind::Method = item.kind { let id = self.tcx.hir().as_local_hir_id(item.def_id); if let Some(hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Method(fn_sig, method), + kind: hir::TraitItemKind::Fn(fn_sig, method), .. })) = id.map(|id| self.tcx.hir().get(id)) { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fd5cac5b24b..3388a70b4cf 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -811,7 +811,7 @@ fn primary_body_of( }, Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)), - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { Some((body, None, Some(&sig.header), Some(&sig.decl))) } _ => None, @@ -1733,7 +1733,7 @@ pub fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, it: &'tcx hir::Item<'tcx>) { for item in items.iter() { let item = tcx.hir().trait_item(item.id); - if let hir::TraitItemKind::Method(sig, _) = &item.kind { + if let hir::TraitItemKind::Fn(sig, _) = &item.kind { let abi = sig.header.abi; fn_maybe_err(tcx, item.ident.span, abi); } @@ -4769,7 +4769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } Node::TraitItem(&hir::TraitItem { ident, - kind: hir::TraitItemKind::Method(ref sig, ..), + kind: hir::TraitItemKind::Fn(ref sig, ..), .. }) => Some((&sig.decl, ident, true)), Node::ImplItem(&hir::ImplItem { @@ -4863,7 +4863,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .. })) | Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Provided(body_id)), .. })) => { let body = hir.body(*body_id); @@ -4934,7 +4934,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .join(", ") } Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Method(.., hir::TraitMethod::Required(idents)), + kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Required(idents)), .. })) => { sugg_call = idents diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index e8e34a4e8f0..335b4a28501 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -173,7 +173,7 @@ pub fn check_trait_item(tcx: TyCtxt<'_>, def_id: DefId) { let trait_item = tcx.hir().expect_trait_item(hir_id); let method_sig = match trait_item.kind { - hir::TraitItemKind::Method(ref sig, _) => Some(sig), + hir::TraitItemKind::Fn(ref sig, _) => Some(sig), _ => None, }; check_object_unsafe_self_trait_by_name(tcx, &trait_item); @@ -207,7 +207,7 @@ fn check_object_unsafe_self_trait_by_name(tcx: TyCtxt<'_>, item: &hir::TraitItem { trait_should_be_self.push(ty.span) } - hir::TraitItemKind::Method(sig, _) => { + hir::TraitItemKind::Fn(sig, _) => { for ty in sig.decl.inputs { if could_be_self(trait_def_id, ty) { trait_should_be_self.push(ty.span); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2dad3d1d6d7..d6262b35248 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -715,7 +715,7 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { tcx.generics_of(def_id); match trait_item.kind { - hir::TraitItemKind::Method(..) => { + hir::TraitItemKind::Fn(..) => { tcx.type_of(def_id); tcx.fn_sig(def_id); } @@ -1121,7 +1121,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option match item.kind { - hir::TraitItemKind::Method(ref sig, _) => { + hir::TraitItemKind::Fn(ref sig, _) => { has_late_bound_regions(tcx, &item.generics, &sig.decl) } _ => None, @@ -1437,7 +1437,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match tcx.hir().get(hir_id) { TraitItem(hir::TraitItem { - kind: TraitItemKind::Method(sig, TraitMethod::Provided(_)), + kind: TraitItemKind::Fn(sig, TraitMethod::Provided(_)), ident, generics, .. @@ -1474,7 +1474,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { } TraitItem(hir::TraitItem { - kind: TraitItemKind::Method(FnSig { header, decl }, _), + kind: TraitItemKind::Fn(FnSig { header, decl }, _), ident, generics, .. diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index ec87112b7a8..815235adc71 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -27,7 +27,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { match tcx.hir().get(hir_id) { Node::TraitItem(item) => match item.kind { - TraitItemKind::Method(..) => { + TraitItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs) } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 6f5caea250b..fc3b7201a1e 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -105,7 +105,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Method(..) = trait_item.kind { + if let hir::TraitItemKind::Fn(..) = trait_item.kind { self.visit_node_helper(trait_item.hir_id); } } diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index ddde11b3844..412b90a9acf 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -54,7 +54,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { }, Node::TraitItem(item) => match item.kind { - hir::TraitItemKind::Method(..) => {} + hir::TraitItemKind::Fn(..) => {} _ => unsupported(), }, diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index dd593a6abb4..f79f8c4bb95 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -164,7 +164,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { } fn visit_trait_item(&mut self, trait_item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Method(..) = trait_item.kind { + if let hir::TraitItemKind::Fn(..) = trait_item.kind { self.add_inferreds_for_item(trait_item.hir_id); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7c845a9b66b..569faf73a21 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1084,10 +1084,10 @@ impl Clean for hir::TraitItem<'_> { hir::TraitItemKind::Const(ref ty, default) => { AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e))) } - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { MethodItem((sig, &self.generics, body, None).clean(cx)) } - hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) }); From e82ec2315e5adb1c291c3702cd2ac1f46ecd0fcf Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 3 Mar 2020 11:26:51 -0800 Subject: [PATCH 0727/1250] Use correct place for `enum_place` PR #69562, which fixed a bug that was causing clippy to ICE, passed the place for the *result* of `Rvalue::Discriminant` instead of the *operand* to `apply_discriminant_switch_effect`. As a result, no effect was applied at all, and we lost the perf benefits from marking inactive enum variants as uninitialized. --- src/librustc_mir/dataflow/generic/engine.rs | 48 ++++++++++++--------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index 1487129f6c7..8d800f2d0ba 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -239,23 +239,26 @@ where } SwitchInt { ref targets, ref values, ref discr, .. } => { - // If this is a switch on an enum discriminant, a custom effect may be applied - // along each outgoing edge. - if let Some(place) = discr.place() { - let enum_def = switch_on_enum_discriminant(self.tcx, self.body, bb_data, place); - if let Some(enum_def) = enum_def { + let Engine { tcx, body, .. } = *self; + let enum_ = discr + .place() + .and_then(|discr| switch_on_enum_discriminant(tcx, body, bb_data, discr)); + match enum_ { + // If this is a switch on an enum discriminant, a custom effect may be applied + // along each outgoing edge. + Some((enum_place, enum_def)) => { self.propagate_bits_into_enum_discriminant_switch_successors( - in_out, bb, enum_def, place, dirty_list, &*values, &*targets, + in_out, bb, enum_def, enum_place, dirty_list, &*values, &*targets, ); - - return; } - } - // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same - // exit state. - for target in targets.iter().copied() { - self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list); + // Otherwise, it's just a normal `SwitchInt`, and every successor sees the same + // exit state. + None => { + for target in targets.iter().copied() { + self.propagate_bits_into_entry_set_for(&in_out, target, dirty_list); + } + } } } @@ -342,22 +345,27 @@ where } } -/// Look at the last statement of a block that ends with to see if it is an assignment of an enum -/// discriminant to the local that determines the target of a `SwitchInt` like so: -/// _42 = discriminant(..) +/// Inspect a `SwitchInt`-terminated basic block to see if the condition of that `SwitchInt` is +/// an enum discriminant. +/// +/// We expect such blocks to have a call to `discriminant` as their last statement like so: +/// _42 = discriminant(_1) /// SwitchInt(_42, ..) +/// +/// If the basic block matches this pattern, this function returns the place corresponding to the +/// enum (`_1` in the example above) as well as the `AdtDef` of that enum. fn switch_on_enum_discriminant( tcx: TyCtxt<'tcx>, - body: &mir::Body<'tcx>, - block: &mir::BasicBlockData<'tcx>, + body: &'mir mir::Body<'tcx>, + block: &'mir mir::BasicBlockData<'tcx>, switch_on: &mir::Place<'tcx>, -) -> Option<&'tcx ty::AdtDef> { +) -> Option<(&'mir mir::Place<'tcx>, &'tcx ty::AdtDef)> { match block.statements.last().map(|stmt| &stmt.kind) { Some(mir::StatementKind::Assign(box (lhs, mir::Rvalue::Discriminant(discriminated)))) if lhs == switch_on => { match &discriminated.ty(body, tcx).ty.kind { - ty::Adt(def, _) => Some(def), + ty::Adt(def, _) => Some((discriminated, def)), // `Rvalue::Discriminant` is also used to get the active yield point for a // generator, but we do not need edge-specific effects in that case. This may From 1a1dcfad6fa13f1b2b69b0e111dcad10326d36ea Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 3 Mar 2020 16:55:01 -0300 Subject: [PATCH 0728/1250] Make PlaceRef lifetimes of codegen_place be both 'tcx --- src/librustc_codegen_ssa/mir/operand.rs | 4 ++-- src/librustc_codegen_ssa/mir/place.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index af95450935c..96c1351de41 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn maybe_codegen_consume_direct( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'tcx, 'tcx>, ) -> Option> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); @@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_consume( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'tcx, 'tcx>, ) -> OperandRef<'tcx, Bx::Value> { debug!("codegen_consume(place_ref={:?})", place_ref); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index fa82daa0f7d..0d2749d3f5f 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_place( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'_, 'tcx>, + place_ref: mir::PlaceRef<'tcx, 'tcx>, ) -> PlaceRef<'tcx, Bx::Value> { debug!("codegen_place(place_ref={:?})", place_ref); let cx = self.cx; From 2af5e87b4b3ef9c7210e4b40ad86a14ff32932f1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 3 Mar 2020 17:00:57 -0300 Subject: [PATCH 0729/1250] Make PlaceRef lifetimes of monomorphized_place_ty be both 'tcx --- src/librustc_codegen_ssa/mir/place.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 0d2749d3f5f..3ff0c8dd2aa 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { result } - pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'_, 'tcx>) -> Ty<'tcx> { + pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx, 'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx); self.monomorphize(&place_ty.ty) From a20d54f00cb4b5386e1b307bc1c990eac02184da Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 3 Mar 2020 17:22:54 -0300 Subject: [PATCH 0730/1250] Make PlaceRef lifetimes of RootPlace be both 'tcx --- src/librustc_mir/borrow_check/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 28974dcd08b..4e21ba86d09 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -841,9 +841,9 @@ enum InitializationRequiringAction { PartialAssignment, } -struct RootPlace<'d, 'tcx> { +struct RootPlace<'tcx> { place_local: Local, - place_projection: &'d [PlaceElem<'tcx>], + place_projection: &'tcx [PlaceElem<'tcx>], is_local_mutation_allowed: LocalMutationIsAllowed, } @@ -2029,7 +2029,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// Adds the place into the used mutable variables set - fn add_used_mut<'d>(&mut self, root_place: RootPlace<'d, 'tcx>, flow_state: &Flows<'cx, 'tcx>) { + fn add_used_mut(&mut self, root_place: RootPlace<'tcx>, flow_state: &Flows<'cx, 'tcx>) { match root_place { RootPlace { place_local: local, place_projection: [], is_local_mutation_allowed } => { // If the local may have been initialized, and it is now currently being @@ -2063,11 +2063,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Whether this value can be written or borrowed mutably. /// Returns the root place if the place passed in is a projection. - fn is_mutable<'d>( + fn is_mutable( &self, - place: PlaceRef<'d, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, is_local_mutation_allowed: LocalMutationIsAllowed, - ) -> Result, PlaceRef<'d, 'tcx>> { + ) -> Result, PlaceRef<'tcx, 'tcx>> { match place { PlaceRef { local, projection: [] } => { let local = &self.body.local_decls[local]; From a9259fb7c7f9f6138b6b774679295084f18a24a3 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 2 Mar 2020 19:28:18 -0500 Subject: [PATCH 0731/1250] Try to ensure usize marker does not get merged --- src/libcore/fmt/mod.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 993b1073493..a9dd098ab0f 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -264,8 +264,18 @@ pub struct ArgumentV1<'a> { // could have been miscompiled. In practice, we never call as_usize on non-usize // containing data (as a matter of static generation of the formatting // arguments), so this is merely an additional check. +// +// We primarily want to ensure that the function pointer at `USIZE_MARKER` has +// an address corresponding *only* to functions that also take `&usize` as their +// first argument. The read_volatile here ensures that we can safely ready out a +// usize from the passed reference and that this address does not point at a +// non-usize taking function. #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] -static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |_, _| loop {}; +static USIZE_MARKER: fn(&usize, &mut Formatter<'_>) -> Result = |ptr, _| { + // SAFETY: ptr is a reference + let _v: usize = unsafe { crate::ptr::read_volatile(ptr) }; + loop {} +}; impl<'a> ArgumentV1<'a> { #[doc(hidden)] From cc9aad452a315d953cebb57547a988aff6aeb563 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 4 Mar 2020 03:58:52 +0100 Subject: [PATCH 0732/1250] resolve, inconsistent binding mode: tweak wording. --- src/librustc_resolve/diagnostics.rs | 3 +- src/test/ui/mismatched_types/E0409.stderr | 2 +- src/test/ui/or-patterns/inconsistent-modes.rs | 16 ++--- .../ui/or-patterns/inconsistent-modes.stderr | 24 +++---- .../resolve-inconsistent-binding-mode.rs | 33 +++++----- .../resolve-inconsistent-binding-mode.stderr | 62 +++++++++---------- .../ui/resolve/resolve-inconsistent-names.rs | 2 +- .../resolve/resolve-inconsistent-names.stderr | 2 +- .../issue-44912-or.rs | 2 +- .../issue-44912-or.stderr | 2 +- 10 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 18192a18cef..f8695061266 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -249,8 +249,7 @@ impl<'a> Resolver<'a> { self.session, span, E0409, - "variable `{}` is bound in inconsistent \ - ways within the same match arm", + "variable `{}` is bound inconsistently across alternatives separated by `|`", variable_name ); err.span_label(span, "bound in different ways"); diff --git a/src/test/ui/mismatched_types/E0409.stderr b/src/test/ui/mismatched_types/E0409.stderr index f5c8b02ae27..ef03b67b1b0 100644 --- a/src/test/ui/mismatched_types/E0409.stderr +++ b/src/test/ui/mismatched_types/E0409.stderr @@ -1,4 +1,4 @@ -error[E0409]: variable `y` is bound in inconsistent ways within the same match arm +error[E0409]: variable `y` is bound inconsistently across alternatives separated by `|` --> $DIR/E0409.rs:5:23 | LL | (0, ref y) | (y, 0) => {} diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs index 28b5f0c02fe..fd5cb01ab42 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.rs +++ b/src/test/ui/or-patterns/inconsistent-modes.rs @@ -5,22 +5,22 @@ fn main() { // One level: let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); - //~^ ERROR variable `a` is bound in inconsistent ways + //~^ ERROR variable `a` is bound inconsistently let Ok(ref mut a) | Err(a): Result = Ok(0); - //~^ ERROR variable `a` is bound in inconsistent ways + //~^ ERROR variable `a` is bound inconsistently let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); - //~^ ERROR variable `a` is bound in inconsistent ways + //~^ ERROR variable `a` is bound inconsistently //~| ERROR mismatched types let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - //~^ ERROR variable `a` is bound in inconsistent ways - //~| ERROR variable `b` is bound in inconsistent ways + //~^ ERROR variable `a` is bound inconsistently + //~| ERROR variable `b` is bound inconsistently //~| ERROR mismatched types // Two levels: let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); - //~^ ERROR variable `a` is bound in inconsistent ways + //~^ ERROR variable `a` is bound inconsistently // Three levels: - let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1); - //~^ ERROR variable `a` is bound in inconsistent ways + let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); + //~^ ERROR variable `a` is bound inconsistently } diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr index 8c01e00bae3..c5dcef36e05 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.stderr +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -1,4 +1,4 @@ -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:7:25 | LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); @@ -6,7 +6,7 @@ LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); | | | first binding -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:9:29 | LL | let Ok(ref mut a) | Err(a): Result = Ok(0); @@ -14,25 +14,25 @@ LL | let Ok(ref mut a) | Err(a): Result = Ok(0); | | | first binding -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:11:33 | LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); | - first binding ^ bound in different ways -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:14:39 | LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); | - first binding ^ bound in different ways -error[E0409]: variable `b` is bound in inconsistent ways within the same match arm +error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:14:46 | LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); | - first binding ^ bound in different ways -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` --> $DIR/inconsistent-modes.rs:20:38 | LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); @@ -40,13 +40,13 @@ LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); | | | first binding -error[E0409]: variable `a` is bound in inconsistent ways within the same match arm - --> $DIR/inconsistent-modes.rs:24:34 +error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` + --> $DIR/inconsistent-modes.rs:24:33 | -LL | let Ok([ Ok((Ok(ref a) | Err(a),)) | Err(a) ]) | Err(a) = Err(&1); - | - ^ bound in different ways - | | - | first binding +LL | let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); + | - ^ bound in different ways + | | + | first binding error[E0308]: mismatched types --> $DIR/inconsistent-modes.rs:11:25 diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs b/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs index e9c4e47f887..43e9378b7d0 100644 --- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs +++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.rs @@ -1,39 +1,40 @@ enum Opts { - A(isize), B(isize), C(isize) + A(isize), + B(isize), + C(isize), } fn matcher1(x: Opts) { match x { - Opts::A(ref i) | Opts::B(i) => {} - //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm - //~^^ ERROR mismatched types - Opts::C(_) => {} + Opts::A(ref i) | Opts::B(i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} } } fn matcher2(x: Opts) { match x { - Opts::A(ref i) | Opts::B(i) => {} - //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm - //~^^ ERROR mismatched types - Opts::C(_) => {} + Opts::A(ref i) | Opts::B(i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} } } fn matcher4(x: Opts) { match x { - Opts::A(ref mut i) | Opts::B(ref i) => {} - //~^ ERROR variable `i` is bound in inconsistent ways within the same match arm - //~^^ ERROR mismatched types - Opts::C(_) => {} + Opts::A(ref mut i) | Opts::B(ref i) => {} + //~^ ERROR variable `i` is bound inconsistently + //~^^ ERROR mismatched types + Opts::C(_) => {} } } - fn matcher5(x: Opts) { match x { - Opts::A(ref i) | Opts::B(ref i) => {} - Opts::C(_) => {} + Opts::A(ref i) | Opts::B(ref i) => {} + Opts::C(_) => {} } } diff --git a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr index 749ed131b20..c14dfa3601a 100644 --- a/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr +++ b/src/test/ui/resolve/resolve-inconsistent-binding-mode.stderr @@ -1,58 +1,58 @@ -error[E0409]: variable `i` is bound in inconsistent ways within the same match arm - --> $DIR/resolve-inconsistent-binding-mode.rs:7:32 +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:9:34 | -LL | Opts::A(ref i) | Opts::B(i) => {} - | - ^ bound in different ways - | | - | first binding +LL | Opts::A(ref i) | Opts::B(i) => {} + | - ^ bound in different ways + | | + | first binding -error[E0409]: variable `i` is bound in inconsistent ways within the same match arm - --> $DIR/resolve-inconsistent-binding-mode.rs:16:32 +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:18:34 | -LL | Opts::A(ref i) | Opts::B(i) => {} - | - ^ bound in different ways - | | - | first binding +LL | Opts::A(ref i) | Opts::B(i) => {} + | - ^ bound in different ways + | | + | first binding -error[E0409]: variable `i` is bound in inconsistent ways within the same match arm - --> $DIR/resolve-inconsistent-binding-mode.rs:25:40 +error[E0409]: variable `i` is bound inconsistently across alternatives separated by `|` + --> $DIR/resolve-inconsistent-binding-mode.rs:27:42 | -LL | Opts::A(ref mut i) | Opts::B(ref i) => {} - | - first binding ^ bound in different ways +LL | Opts::A(ref mut i) | Opts::B(ref i) => {} + | - first binding ^ bound in different ways error[E0308]: mismatched types - --> $DIR/resolve-inconsistent-binding-mode.rs:7:32 + --> $DIR/resolve-inconsistent-binding-mode.rs:9:34 | LL | match x { | - this expression has type `Opts` -LL | Opts::A(ref i) | Opts::B(i) => {} - | ----- ^ expected `&isize`, found `isize` - | | - | first introduced with type `&isize` here +LL | Opts::A(ref i) | Opts::B(i) => {} + | ----- ^ expected `&isize`, found `isize` + | | + | first introduced with type `&isize` here | = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/resolve-inconsistent-binding-mode.rs:16:32 + --> $DIR/resolve-inconsistent-binding-mode.rs:18:34 | LL | match x { | - this expression has type `Opts` -LL | Opts::A(ref i) | Opts::B(i) => {} - | ----- ^ expected `&isize`, found `isize` - | | - | first introduced with type `&isize` here +LL | Opts::A(ref i) | Opts::B(i) => {} + | ----- ^ expected `&isize`, found `isize` + | | + | first introduced with type `&isize` here | = note: in the same arm, a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/resolve-inconsistent-binding-mode.rs:25:36 + --> $DIR/resolve-inconsistent-binding-mode.rs:27:38 | LL | match x { | - this expression has type `Opts` -LL | Opts::A(ref mut i) | Opts::B(ref i) => {} - | --------- ^^^^^ types differ in mutability - | | - | first introduced with type `&mut isize` here +LL | Opts::A(ref mut i) | Opts::B(ref i) => {} + | --------- ^^^^^ types differ in mutability + | | + | first introduced with type `&mut isize` here | = note: expected type `&mut isize` found type `&isize` diff --git a/src/test/ui/resolve/resolve-inconsistent-names.rs b/src/test/ui/resolve/resolve-inconsistent-names.rs index 2fb803c4b2a..b9202f556d1 100644 --- a/src/test/ui/resolve/resolve-inconsistent-names.rs +++ b/src/test/ui/resolve/resolve-inconsistent-names.rs @@ -19,7 +19,7 @@ fn main() { (A, B) | (ref B, c) | (c, A) => () //~^ ERROR variable `A` is not bound in all patterns //~| ERROR variable `B` is not bound in all patterns - //~| ERROR variable `B` is bound in inconsistent ways + //~| ERROR variable `B` is bound inconsistently //~| ERROR mismatched types //~| ERROR variable `c` is not bound in all patterns //~| HELP consider making the path in the pattern qualified: `?::A` diff --git a/src/test/ui/resolve/resolve-inconsistent-names.stderr b/src/test/ui/resolve/resolve-inconsistent-names.stderr index 1d3079c90ba..70e9c2e5bf5 100644 --- a/src/test/ui/resolve/resolve-inconsistent-names.stderr +++ b/src/test/ui/resolve/resolve-inconsistent-names.stderr @@ -47,7 +47,7 @@ LL | (A, B) | (ref B, c) | (c, A) => () | | variable not in all patterns | pattern doesn't bind `c` -error[E0409]: variable `B` is bound in inconsistent ways within the same match arm +error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|` --> $DIR/resolve-inconsistent-names.rs:19:23 | LL | (A, B) | (ref B, c) | (c, A) => () diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs index aa013d4bf35..b4a0d8145c1 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs +++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.rs @@ -4,7 +4,7 @@ pub fn main() { let x = &Some((3, 3)); let _: &i32 = match x { Some((x, 3)) | &Some((ref x, 5)) => x, - //~^ ERROR is bound in inconsistent ways + //~^ ERROR is bound inconsistently _ => &5i32, }; } diff --git a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr index ff8dce32b2a..e1e1bf7f6d9 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/issue-44912-or.stderr @@ -1,4 +1,4 @@ -error[E0409]: variable `x` is bound in inconsistent ways within the same match arm +error[E0409]: variable `x` is bound inconsistently across alternatives separated by `|` --> $DIR/issue-44912-or.rs:6:35 | LL | Some((x, 3)) | &Some((ref x, 5)) => x, From 54561148581f002793ab42893de4e3f7c26bd7ed Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 01:09:53 -0600 Subject: [PATCH 0733/1250] test(pattern): add tests for combinations of pattern features Reference issue #67311 Tests combinations of the following pattern features: - bindings_after_at - or_patterns - slice_patterns - box_patterns --- src/test/ui/or-patterns/box-patterns.rs | 37 +++++++++++++++ src/test/ui/or-patterns/slice-patterns.rs | 42 +++++++++++++++++ .../pattern/bindings-after-at/box-patterns.rs | 36 +++++++++++++++ .../or-patterns-box-patterns.rs | 45 +++++++++++++++++++ .../or-patterns-slice-patterns.rs | 43 ++++++++++++++++++ .../pattern/bindings-after-at/or-patterns.rs | 40 +++++++++++++++++ .../bindings-after-at/slice-patterns.rs | 40 +++++++++++++++++ 7 files changed, 283 insertions(+) create mode 100644 src/test/ui/or-patterns/box-patterns.rs create mode 100644 src/test/ui/or-patterns/slice-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/box-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/or-patterns.rs create mode 100644 src/test/ui/pattern/bindings-after-at/slice-patterns.rs diff --git a/src/test/ui/or-patterns/box-patterns.rs b/src/test/ui/or-patterns/box-patterns.rs new file mode 100644 index 00000000000..aafd4799383 --- /dev/null +++ b/src/test/ui/or-patterns/box-patterns.rs @@ -0,0 +1,37 @@ +// Test or-patterns with box-patterns + +// run-pass + +#![feature(or_patterns)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(x: Option>) -> MatchArm { + match x { + Some(box Test::Foo | box Test::Bar) => MatchArm::Arm(0), + Some(box Test::Baz) => MatchArm::Arm(1), + Some(_) => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(2)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs new file mode 100644 index 00000000000..2f2e865d985 --- /dev/null +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -0,0 +1,42 @@ +// Test or-patterns with slice-patterns + +// run-pass + +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + [.., Some(Test::Foo | Test::Qux)] => MatchArm::Arm(0), + [Some(Test::Foo), .., Some(Test::Bar | Test::Baz)] => MatchArm::Arm(1), + [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2), + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); + assert_eq!(test(&foo[4..]), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/box-patterns.rs b/src/test/ui/pattern/bindings-after-at/box-patterns.rs new file mode 100644 index 00000000000..ef9669a6b9e --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/box-patterns.rs @@ -0,0 +1,36 @@ +// Test bindings-after-at with box-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(x: Option>) -> MatchArm { + match x { + ref bar @ Some(box n) if n > 0 => { + // bar is a &Option> + assert_eq!(bar, &x); + + MatchArm::Arm(0) + }, + Some(ref bar @ box n) if n < 0 => { + // bar is a &Box here + assert_eq!(**bar, n); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(2))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(-1))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(0))), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs new file mode 100644 index 00000000000..ca8826f03f1 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-box-patterns.rs @@ -0,0 +1,45 @@ +// Test bindings-after-at with or-patterns and box-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] +#![feature(box_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option>) -> MatchArm { + match foo { + ref bar @ Some(box Test::Foo | box Test::Bar) => { + assert_eq!(bar, &foo); + + MatchArm::Arm(0) + }, + Some(ref bar @ box Test::Baz | ref bar @ box Test::Qux) => { + assert!(**bar == Test::Baz || **bar == Test::Qux); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Box::new(Test::Foo))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Bar))), MatchArm::Arm(0)); + assert_eq!(test(Some(Box::new(Test::Baz))), MatchArm::Arm(1)); + assert_eq!(test(Some(Box::new(Test::Qux))), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs new file mode 100644 index 00000000000..154df74cc33 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -0,0 +1,43 @@ +// Test bindings-after-at with or-patterns and slice-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: &[Option]) -> MatchArm { + match foo { + bar @ [Some(Test::Foo), .., Some(Test::Foo | Test::Qux)] => { + assert_eq!(bar, foo); + + MatchArm::Arm(0) + }, + [.., bar @ Some(Test::Bar | Test::Qux), _] => { + assert!(bar == &Some(Test::Bar) || bar == &Some(Test::Qux)); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![Some(Test::Foo), Some(Test::Bar), Some(Test::Baz), Some(Test::Qux)]; + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + assert_eq!(test(&foo[1..2]), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns.rs new file mode 100644 index 00000000000..a0e14004ab1 --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/or-patterns.rs @@ -0,0 +1,40 @@ +// Test bindings-after-at with or-patterns + +// run-pass + +#![feature(bindings_after_at)] +#![feature(or_patterns)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum Test { + Foo, + Bar, + Baz, + Qux, +} + +fn test(foo: Option) -> MatchArm { + match foo { + bar @ Some(Test::Foo | Test::Bar) => { + assert!(bar == Some(Test::Foo) || bar == Some(Test::Bar)); + + MatchArm::Arm(0) + }, + Some(_) => MatchArm::Arm(1), + _ => MatchArm::Wild, + } +} + +fn main() { + assert_eq!(test(Some(Test::Foo)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Bar)), MatchArm::Arm(0)); + assert_eq!(test(Some(Test::Baz)), MatchArm::Arm(1)); + assert_eq!(test(Some(Test::Qux)), MatchArm::Arm(1)); + assert_eq!(test(None), MatchArm::Wild); +} diff --git a/src/test/ui/pattern/bindings-after-at/slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/slice-patterns.rs new file mode 100644 index 00000000000..7e50527af0b --- /dev/null +++ b/src/test/ui/pattern/bindings-after-at/slice-patterns.rs @@ -0,0 +1,40 @@ +// Test bindings-after-at with slice-patterns + +// run-pass + +#![feature(bindings_after_at)] + +#[derive(Debug, PartialEq)] +enum MatchArm { + Arm(usize), + Wild, +} + +fn test(foo: &[i32]) -> MatchArm { + match foo { + [bar @ .., n] if n == &5 => { + for i in bar { + assert!(i < &5); + } + + MatchArm::Arm(0) + }, + bar @ [x0, .., xn] => { + assert_eq!(x0, &1); + assert_eq!(x0, &1); + assert_eq!(xn, &4); + assert_eq!(bar, &[1, 2, 3, 4]); + + MatchArm::Arm(1) + }, + _ => MatchArm::Wild, + } +} + +fn main() { + let foo = vec![1, 2, 3, 4, 5]; + + assert_eq!(test(&foo), MatchArm::Arm(0)); + assert_eq!(test(&foo[..4]), MatchArm::Arm(1)); + assert_eq!(test(&foo[0..1]), MatchArm::Wild); +} From b4788a739b5dd040a969135bf46dc633c39fce16 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 01:33:32 -0600 Subject: [PATCH 0734/1250] test(pattern): harden tests for or-patterns with slice-patterns Some of the nested OR paths were being missed --- src/test/ui/or-patterns/slice-patterns.rs | 14 ++++++++++++-- .../or-patterns-slice-patterns.rs | 17 +++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs index 2f2e865d985..2526f048655 100644 --- a/src/test/ui/or-patterns/slice-patterns.rs +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -20,8 +20,8 @@ enum Test { fn test(foo: &[Option]) -> MatchArm { match foo { - [.., Some(Test::Foo | Test::Qux)] => MatchArm::Arm(0), - [Some(Test::Foo), .., Some(Test::Bar | Test::Baz)] => MatchArm::Arm(1), + [.., Some(Test::Qux | Test::Foo)] => MatchArm::Arm(0), + [Some(Test::Foo), .., Some(Test::Baz | Test::Bar)] => MatchArm::Arm(1), [.., Some(Test::Bar | Test::Baz), _] => MatchArm::Arm(2), _ => MatchArm::Wild, } @@ -35,8 +35,18 @@ fn main() { Some(Test::Qux), ]; + // path 1a assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Foo), Some(Test::Bar)]), MatchArm::Arm(1)); + // path 3a assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); + // path 3b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), MatchArm::Arm(2)); + // path 4 assert_eq!(test(&foo[4..]), MatchArm::Wild); } diff --git a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs index 154df74cc33..65c2b3741b3 100644 --- a/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs +++ b/src/test/ui/pattern/bindings-after-at/or-patterns-slice-patterns.rs @@ -21,7 +21,7 @@ enum Test { fn test(foo: &[Option]) -> MatchArm { match foo { - bar @ [Some(Test::Foo), .., Some(Test::Foo | Test::Qux)] => { + bar @ [Some(Test::Foo), .., Some(Test::Qux | Test::Foo)] => { assert_eq!(bar, foo); MatchArm::Arm(0) @@ -36,8 +36,21 @@ fn test(foo: &[Option]) -> MatchArm { } fn main() { - let foo = vec![Some(Test::Foo), Some(Test::Bar), Some(Test::Baz), Some(Test::Qux)]; + let foo = vec![ + Some(Test::Foo), + Some(Test::Bar), + Some(Test::Baz), + Some(Test::Qux), + ]; + + // path 1a assert_eq!(test(&foo), MatchArm::Arm(0)); + // path 1b + assert_eq!(test(&[Some(Test::Foo), Some(Test::Bar), Some(Test::Foo)]), MatchArm::Arm(0)); + // path 2a assert_eq!(test(&foo[..3]), MatchArm::Arm(1)); + // path 2b + assert_eq!(test(&[Some(Test::Bar), Some(Test::Qux), Some(Test::Baz)]), MatchArm::Arm(1)); + // path 3 assert_eq!(test(&foo[1..2]), MatchArm::Wild); } From ea7b3c3c7bfbde2fc900f686b2dcd6ef03fcc510 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Wed, 4 Mar 2020 02:05:23 -0600 Subject: [PATCH 0735/1250] fix tidy error --- src/test/ui/or-patterns/slice-patterns.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/or-patterns/slice-patterns.rs b/src/test/ui/or-patterns/slice-patterns.rs index 2526f048655..05c907e8246 100644 --- a/src/test/ui/or-patterns/slice-patterns.rs +++ b/src/test/ui/or-patterns/slice-patterns.rs @@ -46,7 +46,8 @@ fn main() { // path 3a assert_eq!(test(&foo[1..3]), MatchArm::Arm(2)); // path 3b - assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), MatchArm::Arm(2)); + assert_eq!(test(&[Some(Test::Bar), Some(Test::Baz), Some(Test::Baz), Some(Test::Bar)]), + MatchArm::Arm(2)); // path 4 assert_eq!(test(&foo[4..]), MatchArm::Wild); } From 0a6f45e2e5057fa47c4687edb493e9ce02a5db9a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 22:43:31 +0100 Subject: [PATCH 0736/1250] point cargo-miri to the right xargo binary --- src/bootstrap/test.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 4cfda606c4b..1b9e9a88948 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -391,7 +391,7 @@ impl Step for Miri { // Overwrite bootstrap's `rustc` wrapper overwriting our flags. cargo.env("RUSTC_DEBUG_ASSERTIONS", "true"); // Let cargo-miri know where xargo ended up. - cargo.env("XARGO", builder.out.join("bin").join("xargo")); + cargo.env("XARGO_CHECK", builder.out.join("bin").join("xargo-check")); let mut cargo = Command::from(cargo); if !try_run(builder, &mut cargo) { From faf3a5ea72eab113232b79d4ad4bab6a11513780 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 11:03:08 +0100 Subject: [PATCH 0737/1250] update miri --- Cargo.lock | 1 + src/tools/miri | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index f639095fae7..5fe55d82767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2156,6 +2156,7 @@ dependencies = [ "rustc-workspace-hack", "rustc_version", "serde", + "serde_json", "shell-escape", "vergen", ] diff --git a/src/tools/miri b/src/tools/miri index 3c444bf6a6c..974c8be95ec 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 3c444bf6a6cff3b9014005f21cc44995b34862ce +Subproject commit 974c8be95ec17cd986251d7700cd432a39576939 From c745b4a1841bc5bea8dd50cad85921b36ca47242 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 4 Mar 2020 13:01:19 +0100 Subject: [PATCH 0738/1250] Add explanation for E0380 --- src/librustc_error_codes/error_codes/E0380.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0380.md b/src/librustc_error_codes/error_codes/E0380.md index fe5de569339..638f0c8ecc6 100644 --- a/src/librustc_error_codes/error_codes/E0380.md +++ b/src/librustc_error_codes/error_codes/E0380.md @@ -1,4 +1,14 @@ -Auto traits cannot have methods or associated items. -For more information see the [opt-in builtin traits RFC][RFC 19]. +An auto trait was declared with a method or an associated item. + +Erroneous code example: + +```compile_fail,E0380 +unsafe auto trait Trait { + type Output; // error! +} +``` + +Auto traits cannot have methods or associated items. For more information see +the [opt-in builtin traits RFC][RFC 19]. [RFC 19]: https://github.com/rust-lang/rfcs/blob/master/text/0019-opt-in-builtin-traits.md From 6db7e34ab526abdadbff4e85701f55ce707687b8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 13:12:04 +0100 Subject: [PATCH 0739/1250] use integer assoc consts instead of methods --- src/librustc/mir/interpret/allocation.rs | 14 +++++++------- src/librustc/mir/interpret/pointer.rs | 4 ++-- src/librustc_mir/interpret/intrinsics.rs | 6 +++--- src/librustc_mir/interpret/validity.rs | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index d3efe62e8c1..c8d35db0ade 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -818,9 +818,9 @@ impl UndefMask { // First set all bits except the first `bita`, // then unset the last `64 - bitb` bits. let range = if bitb == 0 { - u64::max_value() << bita + u64::MAX << bita } else { - (u64::max_value() << bita) & (u64::max_value() >> (64 - bitb)) + (u64::MAX << bita) & (u64::MAX >> (64 - bitb)) }; if new_state { self.blocks[blocka] |= range; @@ -832,21 +832,21 @@ impl UndefMask { // across block boundaries if new_state { // Set `bita..64` to `1`. - self.blocks[blocka] |= u64::max_value() << bita; + self.blocks[blocka] |= u64::MAX << bita; // Set `0..bitb` to `1`. if bitb != 0 { - self.blocks[blockb] |= u64::max_value() >> (64 - bitb); + self.blocks[blockb] |= u64::MAX >> (64 - bitb); } // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1)..blockb { - self.blocks[block] = u64::max_value(); + self.blocks[block] = u64::MAX; } } else { // Set `bita..64` to `0`. - self.blocks[blocka] &= !(u64::max_value() << bita); + self.blocks[blocka] &= !(u64::MAX << bita); // Set `0..bitb` to `0`. if bitb != 0 { - self.blocks[blockb] &= !(u64::max_value() >> (64 - bitb)); + self.blocks[blockb] &= !(u64::MAX >> (64 - bitb)); } // Fill in all the other blocks (much faster than one bit at a time). for block in (blocka + 1)..blockb { diff --git a/src/librustc/mir/interpret/pointer.rs b/src/librustc/mir/interpret/pointer.rs index a4974fb541b..cc3c50b7899 100644 --- a/src/librustc/mir/interpret/pointer.rs +++ b/src/librustc/mir/interpret/pointer.rs @@ -78,9 +78,9 @@ pub trait PointerArithmetic: layout::HasDataLayout { fn overflowing_signed_offset(&self, val: u64, i: i128) -> (u64, bool) { // FIXME: is it possible to over/underflow here? if i < 0 { - // Trickery to ensure that `i64::min_value()` works fine: compute `n = -i`. + // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`. // This formula only works for true negative values; it overflows for zero! - let n = u64::max_value() - (i as u64) + 1; + let n = u64::MAX - (i as u64) + 1; let res = val.overflowing_sub(n); self.truncate_to_ptr(res) } else { diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index d63abdc3562..891afbf437f 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -203,7 +203,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if is_add { // max unsigned Scalar::from_uint( - u128::max_value() >> (128 - num_bits), + u128::MAX >> (128 - num_bits), Size::from_bits(num_bits), ) } else { @@ -381,11 +381,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { dest: PlaceTy<'tcx, M::PointerTag>, ) -> InterpResult<'tcx> { // Performs an exact division, resulting in undefined behavior where - // `x % y != 0` or `y == 0` or `x == T::min_value() && y == -1`. + // `x % y != 0` or `y == 0` or `x == T::MIN && y == -1`. // First, check x % y != 0 (or if that computation overflows). let (res, overflow, _ty) = self.overflowing_binary_op(BinOp::Rem, a, b)?; if overflow || res.assert_bits(a.layout.size) != 0 { - // Then, check if `b` is -1, which is the "min_value / -1" case. + // Then, check if `b` is -1, which is the "MIN / -1" case. let minus1 = Scalar::from_int(-1, dest.layout.size); let b_scalar = b.to_scalar().unwrap(); if b_scalar == minus1 { diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 731dcc6a25f..4f99bfe8a85 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -463,7 +463,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M let (lo, hi) = valid_range.clone().into_inner(); // Determine the allowed range // `max_hi` is as big as the size fits - let max_hi = u128::max_value() >> (128 - op.layout.size.bits()); + let max_hi = u128::MAX >> (128 - op.layout.size.bits()); assert!(hi <= max_hi); // We could also write `(hi + 1) % (max_hi + 1) == lo` but `max_hi + 1` overflows for `u128` if (lo == 0 && hi == max_hi) || (hi + 1 == lo) { From f0c3cf2b1b7bc3f6a81f91d7552f54dab667bc26 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 13:18:08 +0100 Subject: [PATCH 0740/1250] cover some more nearby cases --- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/ty/layout.rs | 5 ++--- src/librustc/ty/print/pretty.rs | 2 +- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/librustc/ty/util.rs | 6 +++--- src/librustc_mir/dataflow/mod.rs | 1 - 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 33902fe913a..d5cde703411 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -524,7 +524,7 @@ impl DepGraph { edge_list_indices.push((start, end)); } - debug_assert!(edge_list_data.len() <= ::std::u32::MAX as usize); + debug_assert!(edge_list_data.len() <= u32::MAX as usize); debug_assert_eq!(edge_list_data.len(), total_edge_count); SerializedDepGraph { nodes, fingerprints, edge_list_indices, edge_list_data } diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index f1b4b828c71..7a5a417919d 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -7,7 +7,6 @@ use rustc_span::DUMMY_SP; use std::cmp; use std::fmt; -use std::i128; use std::iter; use std::mem; use std::ops::Bound; @@ -1001,7 +1000,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } - let (mut min, mut max) = (i128::max_value(), i128::min_value()); + let (mut min, mut max) = (i128::MAX, i128::MIN); let discr_type = def.repr.discr_type(); let bits = Integer::from_attr(self, discr_type).size().bits(); for (i, discr) in def.discriminants(tcx) { @@ -1021,7 +1020,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { } } // We might have no inhabited variants, so pretend there's at least one. - if (min, max) == (i128::max_value(), i128::min_value()) { + if (min, max) == (i128::MAX, i128::MIN) { min = 0; max = 0; } diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 3bf92552c86..4829955cb70 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -920,7 +920,7 @@ pub trait PrettyPrinter<'tcx>: } (ConstValue::Scalar(Scalar::Raw { data, .. }), ty::Uint(ui)) => { let bit_size = Integer::from_attr(&self.tcx(), UnsignedInt(*ui)).size(); - let max = truncate(u128::max_value(), bit_size); + let max = truncate(u128::MAX, bit_size); let ui_str = ui.name_str(); if data == max { diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 109ac97fe62..5e36e4df698 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -92,7 +92,7 @@ struct AbsoluteBytePos(u32); impl AbsoluteBytePos { fn new(pos: usize) -> AbsoluteBytePos { - debug_assert!(pos <= ::std::u32::MAX as usize); + debug_assert!(pos <= u32::MAX as usize); AbsoluteBytePos(pos as u32) } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7b1f821877b..62d2b4ae203 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -50,11 +50,11 @@ fn signed_min(size: Size) -> i128 { } fn signed_max(size: Size) -> i128 { - i128::max_value() >> (128 - size.bits()) + i128::MAX >> (128 - size.bits()) } fn unsigned_max(size: Size) -> u128 { - u128::max_value() >> (128 - size.bits()) + u128::MAX >> (128 - size.bits()) } fn int_size_and_signed<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> (Size, bool) { @@ -77,7 +77,7 @@ impl<'tcx> Discr<'tcx> { let min = signed_min(size); let max = signed_max(size); let val = sign_extend(self.val, size) as i128; - assert!(n < (i128::max_value() as u128)); + assert!(n < (i128::MAX as u128)); let n = n as i128; let oflo = val > max - n; let val = if oflo { min + (n - (max - val) - 1) } else { val + n }; diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 25463f31867..b4e33b9502e 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -16,7 +16,6 @@ use std::borrow::Borrow; use std::fmt; use std::io; use std::path::PathBuf; -use std::usize; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; pub(crate) use self::drop_flag_effects::*; From 842af362685979e011e0360984dc1ec96ba5b7e9 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 11:21:01 -0300 Subject: [PATCH 0741/1250] Make PlaceRef lifetimes of borrow_conflict_place be both 'tcx --- src/librustc_mir/borrow_check/mod.rs | 5 +++-- src/librustc_mir/borrow_check/places_conflict.rs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 4e21ba86d09..84c9f733be0 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -86,6 +86,8 @@ crate struct Upvar { mutability: Mutability, } +const DEREF_PROJECTION: &[PlaceElem<'_>; 1] = &[ProjectionElem::Deref]; + pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { mir_borrowck, ..*providers }; } @@ -1413,7 +1415,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) { debug!("check_for_invalidation_at_exit({:?})", borrow); let place = &borrow.borrowed_place; - let deref = [ProjectionElem::Deref]; let mut root_place = PlaceRef { local: place.local, projection: &[] }; // FIXME(nll-rfc#40): do more precise destructor tracking here. For now @@ -1427,7 +1428,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Thread-locals might be dropped after the function exits // We have to dereference the outer reference because // borrows don't conflict behind shared references. - root_place.projection = &deref; + root_place.projection = DEREF_PROJECTION; (true, true) } else { (false, self.locals_are_invalidated_at_exit) diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 984de021ca1..1f90b94cfcd 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( body: &Body<'tcx>, borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, - access_place: PlaceRef<'_, 'tcx>, + access_place: PlaceRef<'tcx, 'tcx>, access: AccessDepth, bias: PlaceConflictBias, ) -> bool { @@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>( body: &Body<'tcx>, borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, - access_place: PlaceRef<'_, 'tcx>, + access_place: PlaceRef<'tcx, 'tcx>, access: AccessDepth, bias: PlaceConflictBias, ) -> bool { From f54e8634e1394d3436037ff54e0f87739709a916 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 13:00:08 -0300 Subject: [PATCH 0742/1250] Make PlaceRef lifetimes of move_error_reported be both 'tcx --- .../borrow_check/diagnostics/conflict_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 11 ++++++----- src/librustc_mir/borrow_check/prefixes.rs | 6 +++--- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index ca51d16f9f2..9d609411a54 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'cx, 'tcx>, Span), + (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span), mpi: MovePathIndex, ) { debug!( diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 84c9f733be0..2d73d96ec8b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -468,7 +468,8 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary /// when errors in the map are being re-added to the error buffer so that errors with the /// same primary span come out in a consistent order. - move_error_reported: BTreeMap, (PlaceRef<'cx, 'tcx>, DiagnosticBuilder<'cx>)>, + move_error_reported: + BTreeMap, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>, /// This field keeps track of errors reported in the checking of uninitialized variables, /// so that we don't report seemingly duplicate errors. uninitialized_error_reported: FxHashSet>, @@ -1527,7 +1528,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'cx, 'tcx>, Span), + place_span: (PlaceRef<'tcx, 'tcx>, Span), flow_state: &Flows<'cx, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1593,7 +1594,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'cx, 'tcx>, Span), + place_span: (PlaceRef<'tcx, 'tcx>, Span), maybe_uninits: &BitSet, from: u32, to: u32, @@ -1632,7 +1633,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'cx, 'tcx>, Span), + place_span: (PlaceRef<'tcx, 'tcx>, Span), flow_state: &Flows<'cx, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1817,7 +1818,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn check_parent_of_field<'cx, 'tcx>( this: &mut MirBorrowckCtxt<'cx, 'tcx>, location: Location, - base: PlaceRef<'cx, 'tcx>, + base: PlaceRef<'tcx, 'tcx>, span: Span, flow_state: &Flows<'cx, 'tcx>, ) { diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 31bee460fa0..b66fd42d9c0 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> { body: ReadOnlyBodyAndCache<'cx, 'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, - next: Option>, + next: Option>, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// terminating the iteration early based on `kind`. pub(super) fn prefixes( &self, - place_ref: PlaceRef<'cx, 'tcx>, + place_ref: PlaceRef<'tcx, 'tcx>, kind: PrefixSet, ) -> Prefixes<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx } @@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { - type Item = PlaceRef<'cx, 'tcx>; + type Item = PlaceRef<'tcx, 'tcx>; fn next(&mut self) -> Option { let mut cursor = self.next?; From 6200f5c362172431279cd4feed4bd20beb7e2c7e Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 13:09:32 -0300 Subject: [PATCH 0743/1250] Make PlaceRef lifetimes of uninitialized_error_reported be both 'tcx --- src/librustc_mir/borrow_check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 2d73d96ec8b..fb3338f998d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -472,7 +472,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { BTreeMap, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>, /// This field keeps track of errors reported in the checking of uninitialized variables, /// so that we don't report seemingly duplicate errors. - uninitialized_error_reported: FxHashSet>, + uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, /// This field keeps track of all the local variables that are declared mut and are mutated. From 8ea676eccaa3596c56b5bf665a1adb155b634ff3 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 2 Mar 2020 10:00:05 -0800 Subject: [PATCH 0744/1250] Update books --- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/embedded-book b/src/doc/embedded-book index b2e1092bf67..b81ffb7a6f4 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit b2e1092bf67bd4d7686c4553f186edbb7f5f92db +Subproject commit b81ffb7a6f4c5aaed92786e770e99db116aa4ebd diff --git a/src/doc/nomicon b/src/doc/nomicon index 3e6e1001dc6..9f797e65e6b 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 3e6e1001dc6e095dbd5c88005e80969f60e384e1 +Subproject commit 9f797e65e6bcc79419975b17aff8e21c9adc039f diff --git a/src/doc/reference b/src/doc/reference index 64239df6d17..559e09caa96 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 64239df6d173562b9deb4f012e4c3e6e960c4754 +Subproject commit 559e09caa9661043744cf7af7bd88432d966f743 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 32facd5522d..db57f899ea2 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 32facd5522ddbbf37baf01e4e4b6562bc55c071a +Subproject commit db57f899ea2a56a544c8d280cbf033438666273d From 0e1cd5935faf9240850c07afb2b7fd8d582c5e25 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Mar 2020 08:23:12 -0800 Subject: [PATCH 0745/1250] Toolstate: remove redundant beta-week check. --- src/bootstrap/toolstate.rs | 39 +++++++++----------------------------- 1 file changed, 9 insertions(+), 30 deletions(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 7cffc472930..7b41ba371a8 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -215,6 +215,9 @@ impl Step for ToolStateCheck { tool, old_state, state ); } else { + // This warning only appears in the logs, which most + // people won't read. It's mostly here for testing and + // debugging. eprintln!( "warning: Tool `{}` is not test-pass (is `{}`), \ this should be fixed before beta is branched.", @@ -222,6 +225,8 @@ impl Step for ToolStateCheck { ); } } + // publish_toolstate.py will be responsible for creating + // comments/issues warning people if there is a regression. } } @@ -230,7 +235,7 @@ impl Step for ToolStateCheck { } if builder.config.channel == "nightly" && env::var_os("TOOLSTATE_PUBLISH").is_some() { - commit_toolstate_change(&toolstates, in_beta_week); + commit_toolstate_change(&toolstates); } } @@ -373,14 +378,12 @@ fn read_old_toolstate() -> Vec { /// /// * See /// if a private email by GitHub is wanted. -fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool) { - let old_toolstate = read_old_toolstate(); - +fn commit_toolstate_change(current_toolstate: &ToolstateData) { let message = format!("({} CI update)", OS.expect("linux/windows only")); let mut success = false; for _ in 1..=5 { // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo. - change_toolstate(¤t_toolstate, &old_toolstate, in_beta_week); + change_toolstate(¤t_toolstate); // `git commit` failing means nothing to commit. let status = t!(Command::new("git") @@ -429,31 +432,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData, in_beta_week: bool } } -fn change_toolstate( - current_toolstate: &ToolstateData, - old_toolstate: &[RepoState], - in_beta_week: bool, -) { - let mut regressed = false; - for repo_state in old_toolstate { - let tool = &repo_state.tool; - let state = repo_state.state(); - let new_state = current_toolstate[tool.as_str()]; - - if new_state != state { - eprintln!("The state of `{}` has changed from `{}` to `{}`", tool, state, new_state); - if new_state < state { - if !NIGHTLY_TOOLS.iter().any(|(name, _path)| name == tool) { - regressed = true; - } - } - } - } - - if regressed && in_beta_week { - std::process::exit(1); - } - +fn change_toolstate(current_toolstate: &ToolstateData) { let commit = t!(std::process::Command::new("git").arg("rev-parse").arg("HEAD").output()); let commit = t!(String::from_utf8(commit.stdout)); From a6d8c9c5ebea585304df74bdf56cff186ad8ef1a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 10:17:15 +0100 Subject: [PATCH 0746/1250] more toolstate comments --- src/bootstrap/toolstate.rs | 8 +++++--- src/ci/publish_toolstate.sh | 4 +++- src/tools/publish_toolstate.py | 9 ++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 7b41ba371a8..c8d8a29ac4e 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -330,11 +330,11 @@ fn prepare_toolstate_config(token: &str) { Err(_) => false, }; if !success { - panic!("git config key={} value={} successful (status: {:?})", key, value, status); + panic!("git config key={} value={} failed (status: {:?})", key, value, status); } } - // If changing anything here, then please check that src/ci/publish_toolstate.sh is up to date + // If changing anything here, then please check that `src/ci/publish_toolstate.sh` is up to date // as well. git_config("user.email", "7378925+rust-toolstate-update@users.noreply.github.com"); git_config("user.name", "Rust Toolstate Update"); @@ -382,7 +382,9 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData) { let message = format!("({} CI update)", OS.expect("linux/windows only")); let mut success = false; for _ in 1..=5 { - // Update the toolstate results (the new commit-to-toolstate mapping) in the toolstate repo. + // Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo. + // This does *not* change the "current toolstate"; that only happens post-landing + // via `src/ci/docker/publish_toolstate.sh`. change_toolstate(¤t_toolstate); // `git commit` failing means nothing to commit. diff --git a/src/ci/publish_toolstate.sh b/src/ci/publish_toolstate.sh index 7c43d034d8b..691df04e754 100755 --- a/src/ci/publish_toolstate.sh +++ b/src/ci/publish_toolstate.sh @@ -23,7 +23,9 @@ GIT_COMMIT_MSG="$(git log --format=%s -n1 HEAD)" cd rust-toolstate FAILURE=1 for RETRY_COUNT in 1 2 3 4 5; do - # The purpose is to publish the new "current" toolstate in the toolstate repo. + # The purpose of this is to publish the new "current" toolstate in the toolstate repo. + # This happens post-landing, on master. + # (Publishing the per-commit test results happens pre-landing in src/bootstrap/toolstate.rs). "$(ciCheckoutPath)/src/tools/publish_toolstate.py" "$GIT_COMMIT" \ "$GIT_COMMIT_MSG" \ "$MESSAGE_FILE" \ diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py index 5fbb986286a..b389cd0373c 100755 --- a/src/tools/publish_toolstate.py +++ b/src/tools/publish_toolstate.py @@ -1,11 +1,10 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- -# This script publishes the new "current" toolstate in the toolstate repo (not to be -# confused with publishing the test results, which happens in -# `src/ci/docker/x86_64-gnu-tools/checktools.sh`). -# It is set as callback for `src/ci/docker/x86_64-gnu-tools/repo.sh` by the CI scripts -# when a new commit lands on `master` (i.e., after it passed all checks on `auto`). +# This script computes the new "current" toolstate for the toolstate repo (not to be +# confused with publishing the test results, which happens in `src/bootstrap/toolstate.rs`). +# It gets called from `src/ci/publish_toolstate.sh` when a new commit lands on `master` +# (i.e., after it passed all checks on `auto`). from __future__ import print_function From e32ee55a365712ef2cca97c0e37a8e56efecafd2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 14:02:11 -0300 Subject: [PATCH 0747/1250] Make PlaceRef lifetimes of move_path_closest_to be both 'tcx --- src/librustc_mir/borrow_check/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index fb3338f998d..49c499fb62d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1713,8 +1713,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// static variable, as we do not track those in the MoveData. fn move_path_closest_to( &mut self, - place: PlaceRef<'_, 'tcx>, - ) -> (PlaceRef<'cx, 'tcx>, MovePathIndex) { + place: PlaceRef<'tcx, 'tcx>, + ) -> (PlaceRef<'tcx, 'tcx>, MovePathIndex) { match self.move_data.rev_lookup.find(place) { LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => { (self.move_data.move_paths[mpi].place.as_ref(), mpi) From 634a167e0594330fb50bf9bd742fdafeb73ed963 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 14:06:20 -0300 Subject: [PATCH 0748/1250] Make PlaceRef lifetimes of move_path_for_place be both 'tcx --- src/librustc_mir/borrow_check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 49c499fb62d..77129a5ef9e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1723,7 +1723,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn move_path_for_place(&mut self, place: PlaceRef<'_, 'tcx>) -> Option { + fn move_path_for_place(&mut self, place: PlaceRef<'tcx, 'tcx>) -> Option { // If returns None, then there is no move path corresponding // to a direct owner of `place` (which means there is nothing // that borrowck tracks for its analysis). From a41f1f128ee9fbe595a588b9b91d545a895f5c39 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 4 Mar 2020 09:49:55 -0800 Subject: [PATCH 0749/1250] Further clarifications and comments on toolstate operation. --- src/bootstrap/toolstate.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index c8d8a29ac4e..f0e0f92af55 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -225,8 +225,11 @@ impl Step for ToolStateCheck { ); } } - // publish_toolstate.py will be responsible for creating - // comments/issues warning people if there is a regression. + // `publish_toolstate.py` is responsible for updating + // `latest.json` and creating comments/issues warning people + // if there is a regression. That all happens in a separate CI + // job on the master branch once the PR has passed all tests + // on the `auto` branch. } } @@ -385,7 +388,7 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData) { // Upload the test results (the new commit-to-toolstate mapping) to the toolstate repo. // This does *not* change the "current toolstate"; that only happens post-landing // via `src/ci/docker/publish_toolstate.sh`. - change_toolstate(¤t_toolstate); + publish_test_results(¤t_toolstate); // `git commit` failing means nothing to commit. let status = t!(Command::new("git") @@ -434,7 +437,12 @@ fn commit_toolstate_change(current_toolstate: &ToolstateData) { } } -fn change_toolstate(current_toolstate: &ToolstateData) { +/// Updates the "history" files with the latest results. +/// +/// These results will later be promoted to `latest.json` by the +/// `publish_toolstate.py` script if the PR passes all tests and is merged to +/// master. +fn publish_test_results(current_toolstate: &ToolstateData) { let commit = t!(std::process::Command::new("git").arg("rev-parse").arg("HEAD").output()); let commit = t!(String::from_utf8(commit.stdout)); From 53be0ccbc913f05c81f1762fd60512e3f57ab5c7 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 4 Mar 2020 10:34:24 -0800 Subject: [PATCH 0750/1250] Use subslice patterns in slice methods For all of the methods that pick off the first or last element, we can use subslice patterns to implement them directly, rather than relying on deeper indexing function calls. At a minimum, this means the generated code will rely less on inlining for performance, but in some cases it also optimizes better. --- src/libcore/slice/mod.rs | 30 ++++++++---------------------- 1 file changed, 8 insertions(+), 22 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 1670c841842..0e12e6360da 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -103,7 +103,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn first(&self) -> Option<&T> { - self.get(0) + if let [first, ..] = self { Some(first) } else { None } } /// Returns a mutable pointer to the first element of the slice, or `None` if it is empty. @@ -121,7 +121,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn first_mut(&mut self) -> Option<&mut T> { - self.get_mut(0) + if let [first, ..] = self { Some(first) } else { None } } /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. @@ -139,7 +139,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_first(&self) -> Option<(&T, &[T])> { - if self.is_empty() { None } else { Some((&self[0], &self[1..])) } + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } /// Returns the first and all the rest of the elements of the slice, or `None` if it is empty. @@ -159,12 +159,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> { - if self.is_empty() { - None - } else { - let split = self.split_at_mut(1); - Some((&mut split.0[0], split.1)) - } + if let [first, tail @ ..] = self { Some((first, tail)) } else { None } } /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. @@ -182,8 +177,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_last(&self) -> Option<(&T, &[T])> { - let len = self.len(); - if len == 0 { None } else { Some((&self[len - 1], &self[..(len - 1)])) } + if let [init @ .., last] = self { Some((last, init)) } else { None } } /// Returns the last and all the rest of the elements of the slice, or `None` if it is empty. @@ -203,13 +197,7 @@ impl [T] { #[stable(feature = "slice_splits", since = "1.5.0")] #[inline] pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> { - let len = self.len(); - if len == 0 { - None - } else { - let split = self.split_at_mut(len - 1); - Some((&mut split.1[0], split.0)) - } + if let [init @ .., last] = self { Some((last, init)) } else { None } } /// Returns the last element of the slice, or `None` if it is empty. @@ -226,8 +214,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn last(&self) -> Option<&T> { - let last_idx = self.len().checked_sub(1)?; - self.get(last_idx) + if let [.., last] = self { Some(last) } else { None } } /// Returns a mutable pointer to the last item in the slice. @@ -245,8 +232,7 @@ impl [T] { #[stable(feature = "rust1", since = "1.0.0")] #[inline] pub fn last_mut(&mut self) -> Option<&mut T> { - let last_idx = self.len().checked_sub(1)?; - self.get_mut(last_idx) + if let [.., last] = self { Some(last) } else { None } } /// Returns a reference to an element or subslice depending on the type of From c3bceb1bac29d5a445d576f006165629b2508121 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 19:56:10 +0100 Subject: [PATCH 0751/1250] submodules: update clippy from 8b7f7e66 to 329923ed Changes: ```` Apply suggestions from code review Simplify if_chain. Move NumericLiteral to its own module. Included binary and octal cases. Resolve false positives for hex int cast. Test for unnecessary_cast of hex int literal. run-rustfix Lint `if let Some` in question_mark lint Add restrictive pat use in full binded struct Update test case answers to match cargo dev fmt Ran cargo dev fmt Rustup to rust-lang/rust#69506 Recommended changes from flip1995 Revive rls integration test use question mark operator Add regression test Use `try_eval_usize` over `eval_usize` Add path for display trait Use lang items instead of get_trait_def_id where possible Update stderr Don't lint debug formatting in debug impl Whitelist unused attribute for use items. Fix one last test issue Refactor suggested by krishna-veerareddy Fixed compile error from merging Changed test output to reflect cargo fmt Run cargo dev fmt Finished checking for cases of absolute values add test for #5238 Some bugfixing Created floating point abs lint and test, but not yet run ```` --- src/tools/clippy | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/clippy b/src/tools/clippy index 8b7f7e66726..329923edec4 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 8b7f7e667268921c278af94ae30a61e87a22b22b +Subproject commit 329923edec41d0ddbea7f30ab12fca0436d459ae From 81f435dd37c5ec828b621d37ec15bf41a33ff89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Mar 2020 15:07:33 -0800 Subject: [PATCH 0752/1250] On mismatched delimiters, only point at empty blocks that are in the same line --- src/librustc_parse/lexer/tokentrees.rs | 7 ++++++- .../parser/mismatched-delim-brace-empty-block.stderr | 10 ++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/lexer/tokentrees.rs b/src/librustc_parse/lexer/tokentrees.rs index 6c0acd0302f..b65b8941728 100644 --- a/src/librustc_parse/lexer/tokentrees.rs +++ b/src/librustc_parse/lexer/tokentrees.rs @@ -40,6 +40,7 @@ struct TokenTreesReader<'a> { /// Used only for error recovery when arriving to EOF with mismatched braces. matching_delim_spans: Vec<(token::DelimToken, Span, Span)>, last_unclosed_found_span: Option, + /// Collect empty block spans that might have been auto-inserted by editors. last_delim_empty_block_spans: FxHashMap, } @@ -138,7 +139,11 @@ impl<'a> TokenTreesReader<'a> { if tts.is_empty() { let empty_block_span = open_brace_span.to(close_brace_span); - self.last_delim_empty_block_spans.insert(delim, empty_block_span); + if !sm.is_multiline(empty_block_span) { + // Only track if the block is in the form of `{}`, otherwise it is + // likely that it was written on purpose. + self.last_delim_empty_block_spans.insert(delim, empty_block_span); + } } if self.open_braces.is_empty() { diff --git a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr index 311f1768d82..f1be5dc5ba7 100644 --- a/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr +++ b/src/test/ui/parser/mismatched-delim-brace-empty-block.stderr @@ -1,14 +1,8 @@ error: unexpected closing delimiter: `}` --> $DIR/mismatched-delim-brace-empty-block.rs:5:1 | -LL | fn main() { - | ___________- -LL | | -LL | | } - | |_- this block is empty, you might have not meant to close it -LL | let _ = (); -LL | } - | ^ unexpected closing delimiter +LL | } + | ^ unexpected closing delimiter error: aborting due to previous error From 51b93966240acffdbe3fbb898bb647a03b146e09 Mon Sep 17 00:00:00 2001 From: Andreas Molzer Date: Thu, 27 Feb 2020 21:24:14 +0100 Subject: [PATCH 0753/1250] Add unborrow to reset RefCell borrow state This method is complementary for the feature refcell_leak added in an earlier PR. It allows reverting the effects of leaking a borrow guard by statically proving that such a guard could not longer exist. This was not added to the existing `get_mut` out of concern of impacting the complexity of the otherwise pure pointer cast and because the name `get_mut` poorly communicates the intent of resetting remaining borrows. --- src/libcore/cell.rs | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b6d5c6ae27d..a20b7a872b8 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -958,6 +958,33 @@ impl RefCell { unsafe { &mut *self.value.get() } } + /// Undo the effect of leaked guards on the borrow state of the `RefCell`. + /// + /// This call is similar to [`get_mut`] but more specialized. It borrows `RefCell` mutably to + /// ensure no borrows exist and then resets the state tracking shared borrows. This is relevant + /// if some `Ref` or `RefMut` borrows have been leaked. + /// + /// [`get_mut`]: #method.get_mut + /// + /// # Examples + /// + /// ``` + /// #![feature(cell_leak)] + /// use std::cell::RefCell; + /// + /// let mut c = RefCell::new(0); + /// std::mem::forget(c.borrow_mut()); + /// + /// assert!(c.try_borrow().is_err()); + /// c.undo_leak(); + /// assert!(c.try_borrow().is_ok()); + /// ``` + #[unstable(feature = "cell_leak", issue = "69099")] + pub fn undo_leak(&mut self) -> &mut T { + *self.borrow.get_mut() = UNUSED; + self.get_mut() + } + /// Immutably borrows the wrapped value, returning an error if the value is /// currently mutably borrowed. /// @@ -1272,8 +1299,10 @@ impl<'b, T: ?Sized> Ref<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: Ref<'b, T>) -> &'b T { - // By forgetting this Ref we ensure that the borrow counter in the RefCell never goes back - // to UNUSED again. No further mutable references can be created from the original cell. + // By forgetting this Ref we ensure that the borrow counter in the RefCell can't go back to + // UNUSED within the lifetime `'b`. Resetting the reference tracking state would require a + // unique reference to the borrowed RefCell. No further mutable references can be created + // from the original cell. mem::forget(orig.borrow); orig.value } @@ -1387,9 +1416,11 @@ impl<'b, T: ?Sized> RefMut<'b, T> { /// ``` #[unstable(feature = "cell_leak", issue = "69099")] pub fn leak(orig: RefMut<'b, T>) -> &'b mut T { - // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell never - // goes back to UNUSED again. No further references can be created from the original cell, - // making the current borrow the only reference for the remaining lifetime. + // By forgetting this BorrowRefMut we ensure that the borrow counter in the RefCell can't + // go back to UNUSED within the lifetime `'b`. Resetting the reference tracking state would + // require a unique reference to the borrowed RefCell. No further references can be created + // from the original cell within that lifetime, making the current borrow the only + // reference for the remaining lifetime. mem::forget(orig.borrow); orig.value } From 729d49d7f2a19ffcac8897e6b9e1898fdc0ad0a0 Mon Sep 17 00:00:00 2001 From: Penelope Phippen Date: Wed, 4 Mar 2020 14:18:31 -0500 Subject: [PATCH 0754/1250] Update macros.rs: fix documentation typo. --- src/libstd/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs index 9e1ac8754d9..7fd7de56f46 100644 --- a/src/libstd/macros.rs +++ b/src/libstd/macros.rs @@ -185,7 +185,7 @@ macro_rules! eprintln { /// builds or when debugging in release mode is significantly faster. /// /// Note that the macro is intended as a debugging tool and therefore you -/// should avoid having uses of it in version control for longer periods. +/// should avoid having uses of it in version control for long periods. /// Use cases involving debug output that should be added to version control /// are better served by macros such as [`debug!`] from the [`log`] crate. /// From 07168f9cdcaae65550ea04395bef1258e8bbe9c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 13:36:49 +0100 Subject: [PATCH 0755/1250] Don't use .ok() before unwrapping via .expect() on a Result. The Result can be expect-unwrapped directly. (clippy::ok_expect) --- src/librustc_codegen_llvm/context.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 46f461b98c8..3466363ac79 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -174,7 +174,6 @@ pub unsafe fn create_module( let llvm_data_layout = llvm::LLVMGetDataLayout(llmod); let llvm_data_layout = str::from_utf8(CStr::from_ptr(llvm_data_layout).to_bytes()) - .ok() .expect("got a non-UTF8 data-layout from LLVM"); // Unfortunately LLVM target specs change over time, and right now we From 569676b9b05cd150da3dadcd886cbbf5b40c4fce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 15:13:19 +0100 Subject: [PATCH 0756/1250] Use .map() to modify data inside Options instead of using .and_then(|x| Some(y)) (clippy::option_and_then_some) --- src/librustc/traits/structural_impls.rs | 6 ++--- src/librustc_parse/parser/attr.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 27 ++++++++++------------- src/librustdoc/clean/utils.rs | 4 +--- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index f9c8b01571e..63d7124ee91 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -415,9 +415,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::ReferenceOutlivesReferent(ty) => { tcx.lift(&ty).map(super::ReferenceOutlivesReferent) } - super::ObjectTypeBound(ty, r) => tcx - .lift(&ty) - .and_then(|ty| tcx.lift(&r).and_then(|r| Some(super::ObjectTypeBound(ty, r)))), + super::ObjectTypeBound(ty, r) => { + tcx.lift(&ty).and_then(|ty| tcx.lift(&r).map(|r| super::ObjectTypeBound(ty, r))) + } super::ObjectCastObligation(ty) => tcx.lift(&ty).map(super::ObjectCastObligation), super::Coercion { source, target } => { Some(super::Coercion { source: tcx.lift(&source)?, target: tcx.lift(&target)? }) diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index c5f8b2dd862..2dccb04f6cc 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -37,7 +37,7 @@ impl<'a> Parser<'a> { let inner_parse_policy = InnerAttributeParsePolicy::NotPermitted { reason: inner_error_reason, saw_doc_comment: just_parsed_doc_comment, - prev_attr_sp: attrs.last().and_then(|a| Some(a.span)), + prev_attr_sp: attrs.last().map(|a| a.span), }; let attr = self.parse_attribute_with_inner_parse_policy(inner_parse_policy)?; attrs.push(attr); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a52cabd8894..58354c891a2 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1551,21 +1551,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let method_names = pcx.candidate_method_names(); pcx.allow_similar_names = false; - let applicable_close_candidates: Vec = - method_names - .iter() - .filter_map(|&method_name| { - pcx.reset(); - pcx.method_name = Some(method_name); - pcx.assemble_inherent_candidates(); - pcx.assemble_extension_candidates_for_traits_in_scope(hir::DUMMY_HIR_ID) - .map_or(None, |_| { - pcx.pick_core() - .and_then(|pick| pick.ok()) - .and_then(|pick| Some(pick.item)) - }) - }) - .collect(); + let applicable_close_candidates: Vec = method_names + .iter() + .filter_map(|&method_name| { + pcx.reset(); + pcx.method_name = Some(method_name); + pcx.assemble_inherent_candidates(); + pcx.assemble_extension_candidates_for_traits_in_scope(hir::DUMMY_HIR_ID) + .map_or(None, |_| { + pcx.pick_core().and_then(|pick| pick.ok()).map(|pick| pick.item) + }) + }) + .collect(); if applicable_close_candidates.is_empty() { Ok(None) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 99e3d731d0d..21e3d24cc96 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -121,9 +121,7 @@ pub fn external_generic_args( let args: Vec<_> = substs .iter() .filter_map(|kind| match kind.unpack() { - GenericArgKind::Lifetime(lt) => { - lt.clean(cx).and_then(|lt| Some(GenericArg::Lifetime(lt))) - } + GenericArgKind::Lifetime(lt) => lt.clean(cx).map(|lt| GenericArg::Lifetime(lt)), GenericArgKind::Type(_) if skip_self => { skip_self = false; None From 38f5db72681289f6ebbcb3c89081f021aa6fdc63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 15:16:27 +0100 Subject: [PATCH 0757/1250] Use .as_deref() instead of .as_ref().map(Deref::deref) (clippy::option_as_ref_deref) --- src/librustdoc/html/markdown.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ed007fe383c..788cc986615 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -296,7 +296,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { "" } )), - playground_button.as_ref().map(String::as_str), + playground_button.as_deref(), Some((s1.as_str(), s2)), )); Some(Event::Html(s.into())) @@ -315,7 +315,7 @@ impl<'a, I: Iterator>> Iterator for CodeBlocks<'_, 'a, I> { "" } )), - playground_button.as_ref().map(String::as_str), + playground_button.as_deref(), None, )); Some(Event::Html(s.into())) From d8d2004c6ffb8b66eac90e75aa23012130adf9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 15:53:14 +0100 Subject: [PATCH 0758/1250] Don't use "if let" bindings to only check a value and not actually bind anything. For example: `if let Some(_) = foo() {}` can be reduced to `if foo().is_some() {}` (clippy::redundant_pattern_matching) --- src/librustc_codegen_llvm/back/write.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_errors/lib.rs | 2 +- src/librustc_interface/util.rs | 2 +- src/librustc_lint/context.rs | 2 +- src/librustc_mir/borrow_check/type_check/mod.rs | 2 +- src/librustc_mir/borrow_check/type_check/relate_tys.rs | 2 +- src/librustc_mir/interpret/memory.rs | 2 +- src/librustc_passes/entry.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index a215ef81bc9..0c243128104 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -725,7 +725,7 @@ pub(crate) unsafe fn codegen( Err(_) => return 0, }; - if let Err(_) = write!(cursor, "{:#}", demangled) { + if write!(cursor, "{:#}", demangled).is_err() { // Possible only if provided buffer is not big enough return 0; } diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 76728e98406..b313bf57d4a 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -1257,7 +1257,7 @@ fn start_executing_work( if main_thread_worker_state == MainThreadWorkerState::Idle { if !queue_full_enough(work_items.len(), running, max_workers) { // The queue is not full enough, codegen more items: - if let Err(_) = codegen_worker_send.send(Message::CodegenItem) { + if codegen_worker_send.send(Message::CodegenItem).is_err() { panic!("Could not send Message::CodegenItem to main thread") } main_thread_worker_state = MainThreadWorkerState::Codegenning; diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 5b00087de6f..f0e388a597b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -163,7 +163,7 @@ impl CodeSuggestion { None => buf.push_str(&line[lo..]), } } - if let None = hi_opt { + if hi_opt.is_none() { buf.push('\n'); } } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 10a8c0a63f1..7866ddbd4cc 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -426,7 +426,7 @@ pub(crate) fn check_attr_crate_type(attrs: &[ast::Attribute], lint_buffer: &mut for a in attrs.iter() { if a.check_name(sym::crate_type) { if let Some(n) = a.value_str() { - if let Some(_) = categorize_crate_type(n) { + if categorize_crate_type(n).is_some() { return; } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 29a6b8c693f..a6e8a0ab930 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -335,7 +335,7 @@ impl LintStore { lint_name.to_string() }; // If the lint was scoped with `tool::` check if the tool lint exists - if let Some(_) = tool_name { + if tool_name.is_some() { match self.by_name.get(&complete_name) { None => match self.lint_groups.get(&*complete_name) { None => return CheckLintNameResult::Tool(Err((None, String::new()))), diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index f4e1bce462f..652de6c7b6f 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -1905,7 +1905,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // expressions evaluate through `as_temp` or `into` a return // slot or local, so to find all unsized rvalues it is enough // to check all temps, return slots and locals. - if let None = self.reported_errors.replace((ty, span)) { + if self.reported_errors.replace((ty, span)).is_none() { let mut diag = struct_span_err!( self.tcx().sess, span, diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index 31507a184d8..b0f048ff1a6 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -64,7 +64,7 @@ impl TypeRelatingDelegate<'tcx> for NllTypeRelatingDelegate<'_, '_, 'tcx> { } fn next_existential_region_var(&mut self, from_forall: bool) -> ty::Region<'tcx> { - if let Some(_) = &mut self.borrowck_context { + if self.borrowck_context.is_some() { let origin = NLLRegionVariableOrigin::Existential { from_forall }; self.infcx.next_nll_region_var(origin) } else { diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 6517ae5d0f3..3c4a1857f96 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -565,7 +565,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { // # Function pointers // (both global from `alloc_map` and local from `extra_fn_ptr_map`) - if let Some(_) = self.get_fn_alloc(id) { + if self.get_fn_alloc(id).is_some() { return if let AllocCheck::Dereferenceable = liveness { // The caller requested no function pointers. throw_unsup!(DerefFunctionPointer) diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index f2239ad16ee..86596e20556 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -196,7 +196,7 @@ fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { // The file may be empty, which leads to the diagnostic machinery not emitting this // note. This is a relatively simple way to detect that case and emit a span-less // note instead. - if let Ok(_) = tcx.sess.source_map().lookup_line(sp.lo()) { + if tcx.sess.source_map().lookup_line(sp.lo()).is_ok() { err.set_span(sp); err.span_label(sp, ¬e); } else { From 80ed505c41319f2fbbc7e97189e62b38c47b5a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 4 Mar 2020 20:47:05 +0100 Subject: [PATCH 0759/1250] Use single-char patter on {ends,starts}_with and remove clone on copy type. These were introduced since I last fixed most of these occurences. (clippy::clone_on_copy, clippy::single_char_pattern) --- src/librustc_errors/registry.rs | 2 +- src/librustc_resolve/late/diagnostics.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_errors/registry.rs b/src/librustc_errors/registry.rs index c92a9d04775..32700c6500b 100644 --- a/src/librustc_errors/registry.rs +++ b/src/librustc_errors/registry.rs @@ -27,6 +27,6 @@ impl Registry { if !self.long_descriptions.contains_key(code) { return Err(InvalidErrorCode); } - Ok(self.long_descriptions.get(code).unwrap().clone()) + Ok(*self.long_descriptions.get(code).unwrap()) } } diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 817a276ff3e..fd62c802934 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1086,7 +1086,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { for param in params { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(param.span) { - if snippet.starts_with("&") && !snippet.starts_with("&'") { + if snippet.starts_with('&') && !snippet.starts_with("&'") { introduce_suggestion .push((param.span, format!("&'a {}", &snippet[1..]))); } else if snippet.starts_with("&'_ ") { @@ -1118,7 +1118,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { (1, Some(name), Some("'_")) => { suggest_existing(err, name.to_string()); } - (1, Some(name), Some(snippet)) if !snippet.ends_with(">") => { + (1, Some(name), Some(snippet)) if !snippet.ends_with('>') => { suggest_existing(err, format!("{}<{}>", snippet, name)); } (0, _, Some("&")) => { @@ -1127,7 +1127,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { (0, _, Some("'_")) => { suggest_new(err, "'a"); } - (0, _, Some(snippet)) if !snippet.ends_with(">") => { + (0, _, Some(snippet)) if !snippet.ends_with('>') => { suggest_new(err, &format!("{}<'a>", snippet)); } _ => { From c6f12447193d3710a38ad2e069605fe1cc2847ba Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 17:00:15 -0300 Subject: [PATCH 0760/1250] Make PlaceRef lifetimes of is_upvar_field_projection be both 'tcx --- .../borrow_check/diagnostics/conflict_errors.rs | 4 ++-- src/librustc_mir/borrow_check/diagnostics/mod.rs | 6 +++--- src/librustc_mir/borrow_check/mod.rs | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 9d609411a54..3a743536052 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - (moved_place, used_place, span): (PlaceRef<'cx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span), + (moved_place, used_place, span): (PlaceRef<'tcx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span), mpi: MovePathIndex, ) { debug!( @@ -647,7 +647,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // borrowed place and look for a access to a different field of the same union. let Place { local, projection } = second_borrowed_place; - let mut cursor = projection.as_ref(); + let mut cursor = &projection[..]; while let [proj_base @ .., elem] = cursor { cursor = proj_base; diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index cd6834a5a4d..01c022ac2c1 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -139,7 +139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// End-user visible description of `place` if one can be found. If the /// place is a temporary for instance, None will be returned. - pub(super) fn describe_place(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option { + pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option { self.describe_place_with_options(place_ref, IncludingDowncast(false)) } @@ -149,7 +149,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// `Downcast` and `IncludingDowncast` is true pub(super) fn describe_place_with_options( &self, - place: PlaceRef<'cx, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, including_downcast: IncludingDowncast, ) -> Option { let mut buf = String::new(); @@ -162,7 +162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Appends end-user visible description of `place` to `buf`. fn append_place_to_string( &self, - place: PlaceRef<'cx, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, buf: &mut String, mut autoderef: bool, including_downcast: &IncludingDowncast, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 77129a5ef9e..89a81945a27 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -2220,7 +2220,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. - pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'cx, 'tcx>) -> Option { + pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option { let mut place_projection = place_ref.projection; let mut by_ref = false; From 6f236504570de4210eeae6e883cf8ed6196e0d98 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 17:12:31 -0300 Subject: [PATCH 0761/1250] Make PlaceRef lifetimes of add_moved_or_invoked_closure_note be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 01c022ac2c1..ed95c0419e9 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(super) fn add_moved_or_invoked_closure_note( &self, location: Location, - place: PlaceRef<'cx, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, diag: &mut DiagnosticBuilder<'_>, ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); From eb67eca74af8765dc4f5579655783b51f0270b49 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 17:22:28 -0300 Subject: [PATCH 0762/1250] Make PlaceRef lifetimes of describe_field be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index ed95c0419e9..2f054b8dd52 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -303,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// End-user visible description of the `field`nth field of `base` - fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String { + fn describe_field(&self, place: PlaceRef<'tcx, 'tcx>, field: Field) -> String { // FIXME Place2 Make this work iteratively match place { PlaceRef { local, projection: [] } => { From 3b6a5fbeceff5a8910c07c6115396e0420e29bee Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 4 Mar 2020 17:45:51 +0100 Subject: [PATCH 0763/1250] Move formatting to different function This slims down the generator MIR considerably, which makes debugging easier --- src/test/ui/generator/issue-69039.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/test/ui/generator/issue-69039.rs b/src/test/ui/generator/issue-69039.rs index 60004f3b0ae..ccc141860aa 100644 --- a/src/test/ui/generator/issue-69039.rs +++ b/src/test/ui/generator/issue-69039.rs @@ -4,11 +4,15 @@ use std::ops::{Generator, GeneratorState}; +fn mkstr(my_name: String, my_mood: String) -> String { + format!("{} is {}", my_name.trim(), my_mood.trim()) +} + fn my_scenario() -> impl Generator { |_arg: String| { let my_name = yield "What is your name?"; let my_mood = yield "How are you feeling?"; - format!("{} is {}", my_name.trim(), my_mood.trim()) + mkstr(my_name, my_mood) } } From a30f55f4b2fc71acd04f5649678ca09c1523096d Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 17:47:00 -0300 Subject: [PATCH 0764/1250] Make PlaceRef lifetimes of borrowed_content_source be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +- src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 2f054b8dd52..e2d59ed3c6e 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -399,7 +399,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(super) fn borrowed_content_source( &self, - deref_base: PlaceRef<'cx, 'tcx>, + deref_base: PlaceRef<'tcx, 'tcx>, ) -> BorrowedContentSource<'tcx> { let tcx = self.infcx.tcx; diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index d91f6edc980..aa35c407b64 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -23,7 +23,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, access_place: &Place<'tcx>, span: Span, - the_place_err: PlaceRef<'cx, 'tcx>, + the_place_err: PlaceRef<'tcx, 'tcx>, error_access: AccessKind, location: Location, ) { From bd4dad4281220325dc5ae3ecca8c286ecba9b681 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:05:37 -0300 Subject: [PATCH 0765/1250] Make PlaceRef lifetimes of move_spans be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index e2d59ed3c6e..2565eeae06b 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( &self, - moved_place: PlaceRef<'cx, 'tcx>, // Could also be an upvar. + moved_place: PlaceRef<'tcx, 'tcx>, // Could also be an upvar. location: Location, ) -> UseSpans { use self::UseSpans::*; From 46d85e519bcd2b64ca0b069055e880b425fb3e74 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:07:33 -0300 Subject: [PATCH 0766/1250] Make PlaceRef lifetimes of closure_span be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 2565eeae06b..4b1c0b05817 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn closure_span( &self, def_id: DefId, - target_place: PlaceRef<'cx, 'tcx>, + target_place: PlaceRef<'tcx, 'tcx>, places: &Vec>, ) -> Option<(Span, Option, Span)> { debug!( From a32afa33c8a8ad58607bafbfb9399b2c51495e61 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:10:01 -0300 Subject: [PATCH 0767/1250] Make PlaceRef lifetimes of classify_drop_access_kind be both 'tcx --- src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 3a743536052..99cbc76efab 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.buffer(&mut self.errors_buffer); } - fn classify_drop_access_kind(&self, place: PlaceRef<'cx, 'tcx>) -> StorageDeadOrDrop<'tcx> { + fn classify_drop_access_kind(&self, place: PlaceRef<'tcx, 'tcx>) -> StorageDeadOrDrop<'tcx> { let tcx = self.infcx.tcx; match place.projection { [] => StorageDeadOrDrop::LocalStorageDead, From a5d1e189a12433d61ded6da47df76929cf8e94c1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:13:47 -0300 Subject: [PATCH 0768/1250] Make PlaceRef lifetimes of is_prefix_of be both 'tcx --- src/librustc_mir/borrow_check/prefixes.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index b66fd42d9c0..25356cd17ef 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -13,12 +13,12 @@ use rustc::mir::{Place, PlaceRef, ProjectionElem, ReadOnlyBodyAndCache}; use rustc::ty::{self, TyCtxt}; use rustc_hir as hir; -pub trait IsPrefixOf<'cx, 'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool; +pub trait IsPrefixOf<'tcx> { + fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool; } -impl<'cx, 'tcx> IsPrefixOf<'cx, 'tcx> for PlaceRef<'cx, 'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'cx, 'tcx>) -> bool { +impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx, 'tcx> { + fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool { self.local == other.local && self.projection.len() <= other.projection.len() && self.projection == &other.projection[..self.projection.len()] From 2cb2559c18c2d494710ab67324cdc73c4be7a46f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:18:15 -0300 Subject: [PATCH 0769/1250] Make PlaceRef lifetimes of in_projection be both 'tcx --- src/librustc_mir/dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/transform/check_consts/qualifs.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 57aa5de7f7a..fb7ae102a0f 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -483,7 +483,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.builder.data.loc_map[self.loc].push(move_out); } - fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) { + fn gather_init(&mut self, place: PlaceRef<'tcx, 'tcx>, kind: InitKind) { debug!("gather_init({:?}, {:?})", self.loc, place); let mut place = place; diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 215496e4d03..275b6e4d508 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -35,7 +35,7 @@ pub trait Qualif { fn in_projection_structurally( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'_, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, ) -> bool { if let [proj_base @ .., elem] = place.projection { let base_qualif = Self::in_place( @@ -67,7 +67,7 @@ pub trait Qualif { fn in_projection( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'_, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, ) -> bool { Self::in_projection_structurally(cx, per_local, place) } @@ -75,7 +75,7 @@ pub trait Qualif { fn in_place( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'_, 'tcx>, + place: PlaceRef<'tcx, 'tcx>, ) -> bool { match place { PlaceRef { local, projection: [] } => per_local(local), From b11cd0b587cc2a663ef358089a2d1cf709170371 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 4 Mar 2020 18:25:03 -0300 Subject: [PATCH 0770/1250] PlaceRef<'a, 'tcx> -> PlaceRef<'tcx> --- src/librustc/mir/mod.rs | 8 +++--- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- src/librustc_codegen_ssa/mir/operand.rs | 4 +-- src/librustc_codegen_ssa/mir/place.rs | 4 +-- .../diagnostics/conflict_errors.rs | 4 +-- .../borrow_check/diagnostics/mod.rs | 16 ++++++------ .../diagnostics/mutability_errors.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 26 ++++++++----------- .../borrow_check/places_conflict.rs | 4 +-- src/librustc_mir/borrow_check/prefixes.rs | 12 ++++----- .../dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/dataflow/move_paths/mod.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 2 +- .../transform/check_consts/qualifs.rs | 6 ++--- src/librustc_mir/transform/promote_consts.rs | 2 +- 15 files changed, 46 insertions(+), 50 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 0d429d8879b..ca97366f514 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1827,9 +1827,9 @@ rustc_index::newtype_index! { } #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct PlaceRef<'a, 'tcx> { +pub struct PlaceRef<'tcx> { pub local: Local, - pub projection: &'a [PlaceElem<'tcx>], + pub projection: &'tcx [PlaceElem<'tcx>], } impl<'tcx> Place<'tcx> { @@ -1864,7 +1864,7 @@ impl<'tcx> Place<'tcx> { self.as_ref().as_local() } - pub fn as_ref(&self) -> PlaceRef<'tcx, 'tcx> { + pub fn as_ref(&self) -> PlaceRef<'tcx> { PlaceRef { local: self.local, projection: &self.projection } } } @@ -1875,7 +1875,7 @@ impl From for Place<'_> { } } -impl<'a, 'tcx> PlaceRef<'a, 'tcx> { +impl<'tcx> PlaceRef<'tcx> { /// Finds the innermost `Local` from this `Place`, *if* it is either a local itself or /// a single deref of a local. // diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 6214aa84b81..2f7e70901f0 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -97,7 +97,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { fn process_place( &mut self, - place_ref: &mir::PlaceRef<'tcx, 'tcx>, + place_ref: &mir::PlaceRef<'tcx>, context: PlaceContext, location: Location, ) { diff --git a/src/librustc_codegen_ssa/mir/operand.rs b/src/librustc_codegen_ssa/mir/operand.rs index 96c1351de41..1e1fede2588 100644 --- a/src/librustc_codegen_ssa/mir/operand.rs +++ b/src/librustc_codegen_ssa/mir/operand.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn maybe_codegen_consume_direct( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'tcx, 'tcx>, + place_ref: mir::PlaceRef<'tcx>, ) -> Option> { debug!("maybe_codegen_consume_direct(place_ref={:?})", place_ref); @@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_consume( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'tcx, 'tcx>, + place_ref: mir::PlaceRef<'tcx>, ) -> OperandRef<'tcx, Bx::Value> { debug!("codegen_consume(place_ref={:?})", place_ref); diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index 3ff0c8dd2aa..2eba88c6b5f 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -408,7 +408,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { pub fn codegen_place( &mut self, bx: &mut Bx, - place_ref: mir::PlaceRef<'tcx, 'tcx>, + place_ref: mir::PlaceRef<'tcx>, ) -> PlaceRef<'tcx, Bx::Value> { debug!("codegen_place(place_ref={:?})", place_ref); let cx = self.cx; @@ -497,7 +497,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { result } - pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx, 'tcx>) -> Ty<'tcx> { + pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> { let tcx = self.cx.tcx(); let place_ty = mir::Place::ty_from(place_ref.local, place_ref.projection, *self.mir, tcx); self.monomorphize(&place_ty.ty) diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 99cbc76efab..6dc5d62babd 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - (moved_place, used_place, span): (PlaceRef<'tcx, 'tcx>, PlaceRef<'tcx, 'tcx>, Span), + (moved_place, used_place, span): (PlaceRef<'tcx>, PlaceRef<'tcx>, Span), mpi: MovePathIndex, ) { debug!( @@ -1521,7 +1521,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.buffer(&mut self.errors_buffer); } - fn classify_drop_access_kind(&self, place: PlaceRef<'tcx, 'tcx>) -> StorageDeadOrDrop<'tcx> { + fn classify_drop_access_kind(&self, place: PlaceRef<'tcx>) -> StorageDeadOrDrop<'tcx> { let tcx = self.infcx.tcx; match place.projection { [] => StorageDeadOrDrop::LocalStorageDead, diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index 4b1c0b05817..912b5f11f1a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -51,7 +51,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(super) fn add_moved_or_invoked_closure_note( &self, location: Location, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, diag: &mut DiagnosticBuilder<'_>, ) { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); @@ -139,7 +139,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// End-user visible description of `place` if one can be found. If the /// place is a temporary for instance, None will be returned. - pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option { + pub(super) fn describe_place(&self, place_ref: PlaceRef<'tcx>) -> Option { self.describe_place_with_options(place_ref, IncludingDowncast(false)) } @@ -149,7 +149,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// `Downcast` and `IncludingDowncast` is true pub(super) fn describe_place_with_options( &self, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, including_downcast: IncludingDowncast, ) -> Option { let mut buf = String::new(); @@ -162,7 +162,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Appends end-user visible description of `place` to `buf`. fn append_place_to_string( &self, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, buf: &mut String, mut autoderef: bool, including_downcast: &IncludingDowncast, @@ -303,7 +303,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// End-user visible description of the `field`nth field of `base` - fn describe_field(&self, place: PlaceRef<'tcx, 'tcx>, field: Field) -> String { + fn describe_field(&self, place: PlaceRef<'tcx>, field: Field) -> String { // FIXME Place2 Make this work iteratively match place { PlaceRef { local, projection: [] } => { @@ -399,7 +399,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub(super) fn borrowed_content_source( &self, - deref_base: PlaceRef<'tcx, 'tcx>, + deref_base: PlaceRef<'tcx>, ) -> BorrowedContentSource<'tcx> { let tcx = self.infcx.tcx; @@ -694,7 +694,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Finds the spans associated to a move or copy of move_place at location. pub(super) fn move_spans( &self, - moved_place: PlaceRef<'tcx, 'tcx>, // Could also be an upvar. + moved_place: PlaceRef<'tcx>, // Could also be an upvar. location: Location, ) -> UseSpans { use self::UseSpans::*; @@ -782,7 +782,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn closure_span( &self, def_id: DefId, - target_place: PlaceRef<'tcx, 'tcx>, + target_place: PlaceRef<'tcx>, places: &Vec>, ) -> Option<(Span, Option, Span)> { debug!( diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index aa35c407b64..1a13ef89585 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -23,7 +23,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { &mut self, access_place: &Place<'tcx>, span: Span, - the_place_err: PlaceRef<'tcx, 'tcx>, + the_place_err: PlaceRef<'tcx>, error_access: AccessKind, location: Location, ) { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 89a81945a27..4e84a416989 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -468,11 +468,10 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// `BTreeMap` is used to preserve the order of insertions when iterating. This is necessary /// when errors in the map are being re-added to the error buffer so that errors with the /// same primary span come out in a consistent order. - move_error_reported: - BTreeMap, (PlaceRef<'tcx, 'tcx>, DiagnosticBuilder<'cx>)>, + move_error_reported: BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'cx>)>, /// This field keeps track of errors reported in the checking of uninitialized variables, /// so that we don't report seemingly duplicate errors. - uninitialized_error_reported: FxHashSet>, + uninitialized_error_reported: FxHashSet>, /// Errors to be reported buffer errors_buffer: Vec, /// This field keeps track of all the local variables that are declared mut and are mutated. @@ -1528,7 +1527,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'tcx, 'tcx>, Span), + place_span: (PlaceRef<'tcx>, Span), flow_state: &Flows<'cx, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1594,7 +1593,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'tcx, 'tcx>, Span), + place_span: (PlaceRef<'tcx>, Span), maybe_uninits: &BitSet, from: u32, to: u32, @@ -1633,7 +1632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &mut self, location: Location, desired_action: InitializationRequiringAction, - place_span: (PlaceRef<'tcx, 'tcx>, Span), + place_span: (PlaceRef<'tcx>, Span), flow_state: &Flows<'cx, 'tcx>, ) { let maybe_uninits = &flow_state.uninits; @@ -1711,10 +1710,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// An Err result includes a tag indicated why the search failed. /// Currently this can only occur if the place is built off of a /// static variable, as we do not track those in the MoveData. - fn move_path_closest_to( - &mut self, - place: PlaceRef<'tcx, 'tcx>, - ) -> (PlaceRef<'tcx, 'tcx>, MovePathIndex) { + fn move_path_closest_to(&mut self, place: PlaceRef<'tcx>) -> (PlaceRef<'tcx>, MovePathIndex) { match self.move_data.rev_lookup.find(place) { LookupResult::Parent(Some(mpi)) | LookupResult::Exact(mpi) => { (self.move_data.move_paths[mpi].place.as_ref(), mpi) @@ -1723,7 +1719,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - fn move_path_for_place(&mut self, place: PlaceRef<'tcx, 'tcx>) -> Option { + fn move_path_for_place(&mut self, place: PlaceRef<'tcx>) -> Option { // If returns None, then there is no move path corresponding // to a direct owner of `place` (which means there is nothing // that borrowck tracks for its analysis). @@ -1818,7 +1814,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { fn check_parent_of_field<'cx, 'tcx>( this: &mut MirBorrowckCtxt<'cx, 'tcx>, location: Location, - base: PlaceRef<'tcx, 'tcx>, + base: PlaceRef<'tcx>, span: Span, flow_state: &Flows<'cx, 'tcx>, ) { @@ -2067,9 +2063,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Returns the root place if the place passed in is a projection. fn is_mutable( &self, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, is_local_mutation_allowed: LocalMutationIsAllowed, - ) -> Result, PlaceRef<'tcx, 'tcx>> { + ) -> Result, PlaceRef<'tcx>> { match place { PlaceRef { local, projection: [] } => { let local = &self.body.local_decls[local]; @@ -2220,7 +2216,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// then returns the index of the field being projected. Note that this closure will always /// be `self` in the current MIR, because that is the only time we directly access the fields /// of a closure type. - pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx, 'tcx>) -> Option { + pub fn is_upvar_field_projection(&self, place_ref: PlaceRef<'tcx>) -> Option { let mut place_projection = place_ref.projection; let mut by_ref = false; diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 1f90b94cfcd..767ffa50fed 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -48,7 +48,7 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( body: &Body<'tcx>, borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, - access_place: PlaceRef<'tcx, 'tcx>, + access_place: PlaceRef<'tcx>, access: AccessDepth, bias: PlaceConflictBias, ) -> bool { @@ -73,7 +73,7 @@ fn place_components_conflict<'tcx>( body: &Body<'tcx>, borrow_place: &Place<'tcx>, borrow_kind: BorrowKind, - access_place: PlaceRef<'tcx, 'tcx>, + access_place: PlaceRef<'tcx>, access: AccessDepth, bias: PlaceConflictBias, ) -> bool { diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 25356cd17ef..c64e8c363af 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -14,11 +14,11 @@ use rustc::ty::{self, TyCtxt}; use rustc_hir as hir; pub trait IsPrefixOf<'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool; + fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; } -impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx, 'tcx> { - fn is_prefix_of(&self, other: PlaceRef<'tcx, 'tcx>) -> bool { +impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> { + fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool { self.local == other.local && self.projection.len() <= other.projection.len() && self.projection == &other.projection[..self.projection.len()] @@ -29,7 +29,7 @@ pub(super) struct Prefixes<'cx, 'tcx> { body: ReadOnlyBodyAndCache<'cx, 'tcx>, tcx: TyCtxt<'tcx>, kind: PrefixSet, - next: Option>, + next: Option>, } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -50,7 +50,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// terminating the iteration early based on `kind`. pub(super) fn prefixes( &self, - place_ref: PlaceRef<'tcx, 'tcx>, + place_ref: PlaceRef<'tcx>, kind: PrefixSet, ) -> Prefixes<'cx, 'tcx> { Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx } @@ -58,7 +58,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { - type Item = PlaceRef<'tcx, 'tcx>; + type Item = PlaceRef<'tcx>; fn next(&mut self) -> Option { let mut cursor = self.next?; diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index fb7ae102a0f..0272e0c3a87 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -483,7 +483,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.builder.data.loc_map[self.loc].push(move_out); } - fn gather_init(&mut self, place: PlaceRef<'tcx, 'tcx>, kind: InitKind) { + fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) { debug!("gather_init({:?}, {:?})", self.loc, place); let mut place = place; diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 6f6ba7dc271..593952bfa7c 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -312,7 +312,7 @@ impl MovePathLookup { // alternative will *not* create a MovePath on the fly for an // unknown place, but will rather return the nearest available // parent. - pub fn find(&self, place: PlaceRef<'_, '_>) -> LookupResult { + pub fn find(&self, place: PlaceRef<'_>) -> LookupResult { let mut result = self.locals[place.local]; for elem in place.projection.iter() { diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index a5b467c1e10..a12d6e02a80 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -14,7 +14,7 @@ pub struct AddRetag; /// after the assignment, we can be sure to obtain the same place value. /// (Concurrent accesses by other threads are no problem as these are anyway non-atomic /// copies. Data races are UB.) -fn is_stable(place: PlaceRef<'_, '_>) -> bool { +fn is_stable(place: PlaceRef<'_>) -> bool { place.projection.iter().all(|elem| { match elem { // Which place this evaluates to can change with any memory write, diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index 275b6e4d508..baff8383c20 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -35,7 +35,7 @@ pub trait Qualif { fn in_projection_structurally( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, ) -> bool { if let [proj_base @ .., elem] = place.projection { let base_qualif = Self::in_place( @@ -67,7 +67,7 @@ pub trait Qualif { fn in_projection( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, ) -> bool { Self::in_projection_structurally(cx, per_local, place) } @@ -75,7 +75,7 @@ pub trait Qualif { fn in_place( cx: &ConstCx<'_, 'tcx>, per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx, 'tcx>, + place: PlaceRef<'tcx>, ) -> bool { match place { PlaceRef { local, projection: [] } => per_local(local), diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 286740f99dd..33f4e126f1e 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -474,7 +474,7 @@ impl<'tcx> Validator<'_, 'tcx> { } } - fn validate_place(&self, place: PlaceRef<'_, 'tcx>) -> Result<(), Unpromotable> { + fn validate_place(&self, place: PlaceRef<'tcx>) -> Result<(), Unpromotable> { match place { PlaceRef { local, projection: [] } => self.validate_local(local), PlaceRef { local: _, projection: [proj_base @ .., elem] } => { From f63b88c761f935d9b2c220a1b4e3abf0c0681c69 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 15 Feb 2020 19:04:20 -0500 Subject: [PATCH 0771/1250] Permit attributes on 'if' expressions Previously, attributes on 'if' expressions (e.g. #[attr] if true {}) were disallowed during parsing. This made it impossible for macros to perform any custom handling of such attributes (e.g. stripping them away), since a compilation error would be emitted before they ever had a chance to run. This PR permits attributes on 'if' expressions ('if-attrs' from here on). Both built-in attributes (e.g. `#[allow]`, `#[cfg]`) are supported. We still do *not* accept attributes on 'other parts' of an if-else chain. That is, the following code snippet still fails to parse: ```rust if true {} #[attr] else if false {} else #[attr] if false {} #[attr] else {} ``` --- src/librustc_parse/parser/expr.rs | 9 ------ src/test/pretty/if-attr.rs | 28 +++++++++++++++++ src/test/ui/parser/attr-stmt-expr-attr-bad.rs | 10 ++---- .../ui/parser/if-attrs/cfg-false-if-attr.rs | 31 +++++++++++++++++++ src/test/ui/parser/if-attrs/else-attrs.rs | 25 +++++++++++++++ src/test/ui/parser/if-attrs/else-attrs.stderr | 27 ++++++++++++++++ .../ui/parser/if-attrs/let-chains-attr.rs | 13 ++++++++ .../ui/parser/if-attrs/let-chains-attr.stderr | 8 +++++ src/test/ui/parser/recovery-attr-on-if.rs | 2 -- src/test/ui/parser/recovery-attr-on-if.stderr | 18 ++--------- 10 files changed, 137 insertions(+), 34 deletions(-) create mode 100644 src/test/pretty/if-attr.rs create mode 100644 src/test/ui/parser/if-attrs/cfg-false-if-attr.rs create mode 100644 src/test/ui/parser/if-attrs/else-attrs.rs create mode 100644 src/test/ui/parser/if-attrs/else-attrs.stderr create mode 100644 src/test/ui/parser/if-attrs/let-chains-attr.rs create mode 100644 src/test/ui/parser/if-attrs/let-chains-attr.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 18ddd23588e..f31686afd1a 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -665,20 +665,11 @@ impl<'a> Parser<'a> { expr.map(|mut expr| { attrs.extend::>(expr.attrs.into()); expr.attrs = attrs; - self.error_attr_on_if_expr(&expr); expr }) }) } - fn error_attr_on_if_expr(&self, expr: &Expr) { - if let (ExprKind::If(..), [a0, ..]) = (&expr.kind, &*expr.attrs) { - // Just point to the first attribute in there... - self.struct_span_err(a0.span, "attributes are not yet allowed on `if` expressions") - .emit(); - } - } - fn parse_dot_or_call_expr_with_(&mut self, mut e: P, lo: Span) -> PResult<'a, P> { loop { if self.eat(&token::Question) { diff --git a/src/test/pretty/if-attr.rs b/src/test/pretty/if-attr.rs new file mode 100644 index 00000000000..463476737a9 --- /dev/null +++ b/src/test/pretty/if-attr.rs @@ -0,0 +1,28 @@ +// pp-exact + +#[cfg(FALSE)] +fn simple_attr() { + + #[attr] + if true { } + + #[allow_warnings] + if true { } +} + +#[cfg(FALSE)] +fn if_else_chain() { + + #[first_attr] + if true { } else if false { } else { } +} + +#[cfg(FALSE)] +fn if_let() { + + #[attr] + if let Some(_) = Some(true) { } +} + + +fn main() { } diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs index 118bff8144c..f3980a59648 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.rs +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.rs @@ -38,8 +38,6 @@ fn main() {} //~^ ERROR an inner attribute is not permitted in this context #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; } -//~^ ERROR attributes are not yet allowed on `if` expressions #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } //~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } @@ -51,14 +49,11 @@ fn main() {} #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } -//~^ ERROR attributes are not yet allowed on `if` expressions -//~| ERROR expected `{`, found `#` +//~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } //~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context -#[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; } -//~^ ERROR attributes are not yet allowed on `if` expressions #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } //~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } @@ -70,8 +65,7 @@ fn main() {} #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } //~^ ERROR an inner attribute is not permitted in this context #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } -//~^ ERROR attributes are not yet allowed on `if` expressions -//~| ERROR expected `{`, found `#` +//~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } //~^ ERROR expected `{`, found `#` #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } diff --git a/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs b/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs new file mode 100644 index 00000000000..2932ec1a231 --- /dev/null +++ b/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs @@ -0,0 +1,31 @@ +// check-pass + +#[cfg(FALSE)] +fn simple_attr() { + #[attr] if true {} + #[allow_warnings] if true {} +} + +#[cfg(FALSE)] +fn if_else_chain() { + #[first_attr] if true { + } else if false { + } else { + } +} + +#[cfg(FALSE)] +fn if_let() { + #[attr] if let Some(_) = Some(true) {} +} + +macro_rules! custom_macro { + ($expr:expr) => {} +} + +custom_macro! { + #[attr] if true {} +} + + +fn main() {} diff --git a/src/test/ui/parser/if-attrs/else-attrs.rs b/src/test/ui/parser/if-attrs/else-attrs.rs new file mode 100644 index 00000000000..4394b2100c1 --- /dev/null +++ b/src/test/ui/parser/if-attrs/else-attrs.rs @@ -0,0 +1,25 @@ +#[cfg(FALSE)] +fn if_else_parse_error() { + if true { + } #[attr] else if false { //~ ERROR expected + } +} + +#[cfg(FALSE)] +fn else_attr_ifparse_error() { + if true { + } else #[attr] if false { //~ ERROR expected + } else { + } +} + +#[cfg(FALSE)] +fn else_parse_error() { + if true { + } else if false { + } #[attr] else { //~ ERROR expected + } +} + +fn main() { +} diff --git a/src/test/ui/parser/if-attrs/else-attrs.stderr b/src/test/ui/parser/if-attrs/else-attrs.stderr new file mode 100644 index 00000000000..af25b6abc0a --- /dev/null +++ b/src/test/ui/parser/if-attrs/else-attrs.stderr @@ -0,0 +1,27 @@ +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:4:15 + | +LL | } #[attr] else if false { + | ^^^^ expected expression + +error: expected `{`, found `#` + --> $DIR/else-attrs.rs:11:12 + | +LL | } else #[attr] if false { + | ^ expected `{` + | +help: try placing this code inside a block + | +LL | } else #[attr] { if false { +LL | } else { +LL | } } + | + +error: expected expression, found keyword `else` + --> $DIR/else-attrs.rs:20:15 + | +LL | } #[attr] else { + | ^^^^ expected expression + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.rs b/src/test/ui/parser/if-attrs/let-chains-attr.rs new file mode 100644 index 00000000000..5237a9ff396 --- /dev/null +++ b/src/test/ui/parser/if-attrs/let-chains-attr.rs @@ -0,0 +1,13 @@ +// check-pass + +#![feature(let_chains)] //~ WARN the feature `let_chains` is incomplete + +#[cfg(FALSE)] +fn foo() { + #[attr] + if let Some(_) = Some(true) && let Ok(_) = Ok(1) { + } else if let Some(false) = Some(true) { + } +} + +fn main() {} diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.stderr b/src/test/ui/parser/if-attrs/let-chains-attr.stderr new file mode 100644 index 00000000000..a6c91bb9203 --- /dev/null +++ b/src/test/ui/parser/if-attrs/let-chains-attr.stderr @@ -0,0 +1,8 @@ +warning: the feature `let_chains` is incomplete and may cause the compiler to crash + --> $DIR/let-chains-attr.rs:3:12 + | +LL | #![feature(let_chains)] + | ^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs index 0d1f5be7b49..b4fb25ec8d3 100644 --- a/src/test/ui/parser/recovery-attr-on-if.rs +++ b/src/test/ui/parser/recovery-attr-on-if.rs @@ -1,9 +1,7 @@ fn main() { #[attr] if true {}; //~^ ERROR cannot find attribute - //~| ERROR attributes are not yet allowed on `if` expressions #[attr] if true {}; //~^ ERROR cannot find attribute - //~| ERROR attributes are not yet allowed on `if` expressions let _recovery_witness: () = 0; //~ ERROR mismatched types } diff --git a/src/test/ui/parser/recovery-attr-on-if.stderr b/src/test/ui/parser/recovery-attr-on-if.stderr index a02846827c9..cbf2714a1a1 100644 --- a/src/test/ui/parser/recovery-attr-on-if.stderr +++ b/src/test/ui/parser/recovery-attr-on-if.stderr @@ -1,17 +1,5 @@ -error: attributes are not yet allowed on `if` expressions - --> $DIR/recovery-attr-on-if.rs:2:5 - | -LL | #[attr] if true {}; - | ^^^^^^^ - -error: attributes are not yet allowed on `if` expressions - --> $DIR/recovery-attr-on-if.rs:5:5 - | -LL | #[attr] if true {}; - | ^^^^^^^ - error: cannot find attribute `attr` in this scope - --> $DIR/recovery-attr-on-if.rs:5:7 + --> $DIR/recovery-attr-on-if.rs:4:7 | LL | #[attr] if true {}; | ^^^^ @@ -23,13 +11,13 @@ LL | #[attr] if true {}; | ^^^^ error[E0308]: mismatched types - --> $DIR/recovery-attr-on-if.rs:8:33 + --> $DIR/recovery-attr-on-if.rs:6:33 | LL | let _recovery_witness: () = 0; | -- ^ expected `()`, found integer | | | expected due to this -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. From e912d9d7ecd9d326affd18f7b133dafb72ee8896 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sat, 15 Feb 2020 19:13:36 -0500 Subject: [PATCH 0772/1250] Test #[allow(unused)] on `if` expression --- src/test/ui/parser/if-attrs/builtin-if-attr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/builtin-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/builtin-if-attr.rs b/src/test/ui/parser/if-attrs/builtin-if-attr.rs new file mode 100644 index 00000000000..7e290661501 --- /dev/null +++ b/src/test/ui/parser/if-attrs/builtin-if-attr.rs @@ -0,0 +1,12 @@ +// check-pass + +fn main() { + #[allow(unused_variables)] + if true { + let a = 1; + } else if false { + let b = 1; + } else { + let c = 1; + } +} From e9ec47bb70810f972e6565d496120b0b00f261f0 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:45:21 -0500 Subject: [PATCH 0773/1250] Test that stmt_expr_attrs properly gates if-attrs --- src/test/ui/parser/if-attrs/stmt-expr-gated.rs | 6 ++++++ src/test/ui/parser/if-attrs/stmt-expr-gated.stderr | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/stmt-expr-gated.rs create mode 100644 src/test/ui/parser/if-attrs/stmt-expr-gated.stderr diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.rs b/src/test/ui/parser/if-attrs/stmt-expr-gated.rs new file mode 100644 index 00000000000..38599c8e67c --- /dev/null +++ b/src/test/ui/parser/if-attrs/stmt-expr-gated.rs @@ -0,0 +1,6 @@ +fn main() { + let _ = #[deny(warnings)] if true { //~ ERROR attributes on expressions + } else if false { + } else { + }; +} diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr b/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr new file mode 100644 index 00000000000..47dac39a9ae --- /dev/null +++ b/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr @@ -0,0 +1,12 @@ +error[E0658]: attributes on expressions are experimental + --> $DIR/stmt-expr-gated.rs:2:13 + | +LL | let _ = #[deny(warnings)] if true { + | ^^^^^^^^^^^^^^^^^ + | + = note: see issue #15701 for more information + = help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From 9a299e4e210ff91ec59bf9f09bdb402196e02bd5 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:47:27 -0500 Subject: [PATCH 0774/1250] Test trying to cfg-remove an `if` expression --- src/test/ui/parser/if-attrs/bad-cfg.rs | 5 +++++ src/test/ui/parser/if-attrs/bad-cfg.stderr | 8 ++++++++ 2 files changed, 13 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/bad-cfg.rs create mode 100644 src/test/ui/parser/if-attrs/bad-cfg.stderr diff --git a/src/test/ui/parser/if-attrs/bad-cfg.rs b/src/test/ui/parser/if-attrs/bad-cfg.rs new file mode 100644 index 00000000000..3f84929a00e --- /dev/null +++ b/src/test/ui/parser/if-attrs/bad-cfg.rs @@ -0,0 +1,5 @@ +#![feature(stmt_expr_attributes)] + +fn main() { + let _ = #[cfg(FALSE)] if true {}; //~ ERROR removing an expression +} diff --git a/src/test/ui/parser/if-attrs/bad-cfg.stderr b/src/test/ui/parser/if-attrs/bad-cfg.stderr new file mode 100644 index 00000000000..8a2890886a1 --- /dev/null +++ b/src/test/ui/parser/if-attrs/bad-cfg.stderr @@ -0,0 +1,8 @@ +error: removing an expression is not supported in this position + --> $DIR/bad-cfg.rs:4:13 + | +LL | let _ = #[cfg(FALSE)] if true {}; + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + From b00f6745c4df0e979dd53dcbf43ededf5728e349 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:48:13 -0500 Subject: [PATCH 0775/1250] Remove recovery test --- src/test/ui/parser/recovery-attr-on-if.rs | 7 ------ src/test/ui/parser/recovery-attr-on-if.stderr | 23 ------------------- 2 files changed, 30 deletions(-) delete mode 100644 src/test/ui/parser/recovery-attr-on-if.rs delete mode 100644 src/test/ui/parser/recovery-attr-on-if.stderr diff --git a/src/test/ui/parser/recovery-attr-on-if.rs b/src/test/ui/parser/recovery-attr-on-if.rs deleted file mode 100644 index b4fb25ec8d3..00000000000 --- a/src/test/ui/parser/recovery-attr-on-if.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn main() { - #[attr] if true {}; - //~^ ERROR cannot find attribute - #[attr] if true {}; - //~^ ERROR cannot find attribute - let _recovery_witness: () = 0; //~ ERROR mismatched types -} diff --git a/src/test/ui/parser/recovery-attr-on-if.stderr b/src/test/ui/parser/recovery-attr-on-if.stderr deleted file mode 100644 index cbf2714a1a1..00000000000 --- a/src/test/ui/parser/recovery-attr-on-if.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error: cannot find attribute `attr` in this scope - --> $DIR/recovery-attr-on-if.rs:4:7 - | -LL | #[attr] if true {}; - | ^^^^ - -error: cannot find attribute `attr` in this scope - --> $DIR/recovery-attr-on-if.rs:2:7 - | -LL | #[attr] if true {}; - | ^^^^ - -error[E0308]: mismatched types - --> $DIR/recovery-attr-on-if.rs:6:33 - | -LL | let _recovery_witness: () = 0; - | -- ^ expected `()`, found integer - | | - | expected due to this - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0308`. From e11cdfdae48f8793c618834227114bcb5a6d57bd Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:49:34 -0500 Subject: [PATCH 0776/1250] Add run-pass test suggested by @joshtriplett --- src/test/ui/parser/if-attrs/gate-whole-expr.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/test/ui/parser/if-attrs/gate-whole-expr.rs diff --git a/src/test/ui/parser/if-attrs/gate-whole-expr.rs b/src/test/ui/parser/if-attrs/gate-whole-expr.rs new file mode 100644 index 00000000000..efce28e1d5b --- /dev/null +++ b/src/test/ui/parser/if-attrs/gate-whole-expr.rs @@ -0,0 +1,15 @@ +// run-pass + +fn main() { + let x = 1; + + #[cfg(FALSE)] + if false { + x = 2; + } else if true { + x = 3; + } else { + x = 4; + } + assert_eq!(x, 1); +} From 7f19358c9ef51a130e0177d327eaac5adc6d73ad Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 10:50:03 -0500 Subject: [PATCH 0777/1250] Move if-attr tests to their own directory --- src/test/ui/{parser => }/if-attrs/bad-cfg.rs | 0 src/test/ui/{parser => }/if-attrs/bad-cfg.stderr | 0 src/test/ui/{parser => }/if-attrs/builtin-if-attr.rs | 0 src/test/ui/{parser => }/if-attrs/cfg-false-if-attr.rs | 0 src/test/ui/{parser => }/if-attrs/else-attrs.rs | 0 src/test/ui/{parser => }/if-attrs/else-attrs.stderr | 0 src/test/ui/{parser => }/if-attrs/gate-whole-expr.rs | 0 src/test/ui/{parser => }/if-attrs/let-chains-attr.rs | 0 src/test/ui/{parser => }/if-attrs/let-chains-attr.stderr | 0 src/test/ui/{parser => }/if-attrs/stmt-expr-gated.rs | 0 src/test/ui/{parser => }/if-attrs/stmt-expr-gated.stderr | 0 11 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{parser => }/if-attrs/bad-cfg.rs (100%) rename src/test/ui/{parser => }/if-attrs/bad-cfg.stderr (100%) rename src/test/ui/{parser => }/if-attrs/builtin-if-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/cfg-false-if-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/else-attrs.rs (100%) rename src/test/ui/{parser => }/if-attrs/else-attrs.stderr (100%) rename src/test/ui/{parser => }/if-attrs/gate-whole-expr.rs (100%) rename src/test/ui/{parser => }/if-attrs/let-chains-attr.rs (100%) rename src/test/ui/{parser => }/if-attrs/let-chains-attr.stderr (100%) rename src/test/ui/{parser => }/if-attrs/stmt-expr-gated.rs (100%) rename src/test/ui/{parser => }/if-attrs/stmt-expr-gated.stderr (100%) diff --git a/src/test/ui/parser/if-attrs/bad-cfg.rs b/src/test/ui/if-attrs/bad-cfg.rs similarity index 100% rename from src/test/ui/parser/if-attrs/bad-cfg.rs rename to src/test/ui/if-attrs/bad-cfg.rs diff --git a/src/test/ui/parser/if-attrs/bad-cfg.stderr b/src/test/ui/if-attrs/bad-cfg.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/bad-cfg.stderr rename to src/test/ui/if-attrs/bad-cfg.stderr diff --git a/src/test/ui/parser/if-attrs/builtin-if-attr.rs b/src/test/ui/if-attrs/builtin-if-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/builtin-if-attr.rs rename to src/test/ui/if-attrs/builtin-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/cfg-false-if-attr.rs b/src/test/ui/if-attrs/cfg-false-if-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/cfg-false-if-attr.rs rename to src/test/ui/if-attrs/cfg-false-if-attr.rs diff --git a/src/test/ui/parser/if-attrs/else-attrs.rs b/src/test/ui/if-attrs/else-attrs.rs similarity index 100% rename from src/test/ui/parser/if-attrs/else-attrs.rs rename to src/test/ui/if-attrs/else-attrs.rs diff --git a/src/test/ui/parser/if-attrs/else-attrs.stderr b/src/test/ui/if-attrs/else-attrs.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/else-attrs.stderr rename to src/test/ui/if-attrs/else-attrs.stderr diff --git a/src/test/ui/parser/if-attrs/gate-whole-expr.rs b/src/test/ui/if-attrs/gate-whole-expr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/gate-whole-expr.rs rename to src/test/ui/if-attrs/gate-whole-expr.rs diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.rs b/src/test/ui/if-attrs/let-chains-attr.rs similarity index 100% rename from src/test/ui/parser/if-attrs/let-chains-attr.rs rename to src/test/ui/if-attrs/let-chains-attr.rs diff --git a/src/test/ui/parser/if-attrs/let-chains-attr.stderr b/src/test/ui/if-attrs/let-chains-attr.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/let-chains-attr.stderr rename to src/test/ui/if-attrs/let-chains-attr.stderr diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.rs b/src/test/ui/if-attrs/stmt-expr-gated.rs similarity index 100% rename from src/test/ui/parser/if-attrs/stmt-expr-gated.rs rename to src/test/ui/if-attrs/stmt-expr-gated.rs diff --git a/src/test/ui/parser/if-attrs/stmt-expr-gated.stderr b/src/test/ui/if-attrs/stmt-expr-gated.stderr similarity index 100% rename from src/test/ui/parser/if-attrs/stmt-expr-gated.stderr rename to src/test/ui/if-attrs/stmt-expr-gated.stderr From 1b681d6652bacce6b741ca66725f25b9afb16bc8 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:01:51 -0500 Subject: [PATCH 0778/1250] Test that cfg-gated if-exprs are not type-checked --- src/test/ui/if-attrs/cfg-false-if-attr.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/test/ui/if-attrs/cfg-false-if-attr.rs b/src/test/ui/if-attrs/cfg-false-if-attr.rs index 2932ec1a231..1f77a1bb342 100644 --- a/src/test/ui/if-attrs/cfg-false-if-attr.rs +++ b/src/test/ui/if-attrs/cfg-false-if-attr.rs @@ -19,6 +19,18 @@ fn if_let() { #[attr] if let Some(_) = Some(true) {} } +fn bar() { + #[cfg(FALSE)] + if true { + let x: () = true; // Should not error due to the #[cfg(FALSE)] + } + + #[cfg_attr(not(unset_attr), cfg(FALSE))] + if true { + let a: () = true; // Should not error due to the applied #[cfg(FALSE)] + } +} + macro_rules! custom_macro { ($expr:expr) => {} } From 37c2c38aeb0d50f7b956200c698bc59fce6e7181 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:05:31 -0500 Subject: [PATCH 0779/1250] Extent pretty-print test --- src/test/pretty/if-attr.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/pretty/if-attr.rs b/src/test/pretty/if-attr.rs index 463476737a9..652604fc7f3 100644 --- a/src/test/pretty/if-attr.rs +++ b/src/test/pretty/if-attr.rs @@ -24,5 +24,14 @@ fn if_let() { if let Some(_) = Some(true) { } } +#[cfg(FALSE)] +fn let_attr_if() { + let _ = #[attr] if let _ = 0 { }; + let _ = #[attr] if true { }; + + let _ = #[attr] if let _ = 0 { } else { }; + let _ = #[attr] if true { } else { }; +} + fn main() { } From 66b152cf9fd53b27027c66378a73404b92c6e35b Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 19 Feb 2020 11:36:04 -0500 Subject: [PATCH 0780/1250] Fix tabs --- src/test/ui/if-attrs/gate-whole-expr.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/test/ui/if-attrs/gate-whole-expr.rs b/src/test/ui/if-attrs/gate-whole-expr.rs index efce28e1d5b..63772d54b53 100644 --- a/src/test/ui/if-attrs/gate-whole-expr.rs +++ b/src/test/ui/if-attrs/gate-whole-expr.rs @@ -1,15 +1,15 @@ // run-pass fn main() { - let x = 1; + let x = 1; - #[cfg(FALSE)] - if false { - x = 2; - } else if true { - x = 3; - } else { - x = 4; - } - assert_eq!(x, 1); + #[cfg(FALSE)] + if false { + x = 2; + } else if true { + x = 3; + } else { + x = 4; + } + assert_eq!(x, 1); } From e50fd5a3dc587b5b970b6b969eff7e8547dede70 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Wed, 4 Mar 2020 16:54:16 -0500 Subject: [PATCH 0781/1250] Update stderr --- .../ui/parser/attr-stmt-expr-attr-bad.stderr | 94 +++++++------------ 1 file changed, 35 insertions(+), 59 deletions(-) diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index b03db85422d..3cc3a455c12 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -136,14 +136,8 @@ LL | #[cfg(FALSE)] fn e() { let _ = #[attr] &mut #![attr] 0; } | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. -error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:41:32 - | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if 0 {}; } - | ^^^^^^^ - error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:43:37 + --> $DIR/attr-stmt-expr-attr-bad.rs:41:37 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -152,7 +146,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:45:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:43:38 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } | ^^^^^^^^ @@ -160,13 +154,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:47:40 + --> $DIR/attr-stmt-expr-attr-bad.rs:45:40 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:49:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:47:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } | ^ --- help: try placing this code inside a block: `{ {}; }` @@ -174,21 +168,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } | expected `{` error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:51:46 + --> $DIR/attr-stmt-expr-attr-bad.rs:49:46 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. -error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:53:45 - | -LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } - | ^^^^^^^ - error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:53:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:51:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | ^ -------- help: try placing this code inside a block: `{ if 0 {}; }` @@ -196,7 +184,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } | expected `{` error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:56:50 + --> $DIR/attr-stmt-expr-attr-bad.rs:53:50 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -205,21 +193,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:58:51 + --> $DIR/attr-stmt-expr-attr-bad.rs:55:51 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. -error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:60:32 - | -LL | #[cfg(FALSE)] fn e() { let _ = #[attr] if let _ = 0 {}; } - | ^^^^^^^ - error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:62:45 + --> $DIR/attr-stmt-expr-attr-bad.rs:57:45 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -228,7 +210,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:64:46 + --> $DIR/attr-stmt-expr-attr-bad.rs:59:46 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } | ^^^^^^^^ @@ -236,13 +218,13 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {#![attr]}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: expected one of `.`, `;`, `?`, `else`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:66:48 + --> $DIR/attr-stmt-expr-attr-bad.rs:61:48 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} #[attr] else {}; } | ^ expected one of `.`, `;`, `?`, `else`, or an operator error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:68:53 + --> $DIR/attr-stmt-expr-attr-bad.rs:63:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } | ^ --- help: try placing this code inside a block: `{ {}; }` @@ -250,21 +232,15 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } | expected `{` error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:70:54 + --> $DIR/attr-stmt-expr-attr-bad.rs:65:54 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else {#![attr]}; } | ^^^^^^^^ | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. -error: attributes are not yet allowed on `if` expressions - --> $DIR/attr-stmt-expr-attr-bad.rs:72:53 - | -LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } - | ^^^^^^^ - error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:72:53 + --> $DIR/attr-stmt-expr-attr-bad.rs:67:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } | ^ ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }` @@ -272,7 +248,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {} | expected `{` error: expected `{`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:75:66 + --> $DIR/attr-stmt-expr-attr-bad.rs:69:66 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } | -- ^ --- help: try placing this code inside a block: `{ {}; }` @@ -281,7 +257,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {} | this `if` expression has a condition, but no block error: an inner attribute is not permitted in this context - --> $DIR/attr-stmt-expr-attr-bad.rs:77:67 + --> $DIR/attr-stmt-expr-attr-bad.rs:71:67 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]}; } | ^^^^^^^^ @@ -289,7 +265,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 {#![attr]} = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:74:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -299,7 +275,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:76:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -309,7 +285,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:84:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:78:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -319,7 +295,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:86:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -329,7 +305,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error: an inner attribute is not permitted following an outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:88:32 + --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } | ------- ^^^^^^^^ not permitted following an outer attibute @@ -339,7 +315,7 @@ LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. error[E0586]: inclusive range with no end - --> $DIR/attr-stmt-expr-attr-bad.rs:94:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:88:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | ^^^ help: use `..` instead @@ -347,13 +323,13 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:94:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:88:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } } | ^ expected one of `=>`, `if`, or `|` error[E0586]: inclusive range with no end - --> $DIR/attr-stmt-expr-attr-bad.rs:97:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:91:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | ^^^ help: use `..` instead @@ -361,19 +337,19 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:97:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:91:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:100:39 + --> $DIR/attr-stmt-expr-attr-bad.rs:94:39 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } } | ^ error[E0586]: inclusive range with no end - --> $DIR/attr-stmt-expr-attr-bad.rs:102:35 + --> $DIR/attr-stmt-expr-attr-bad.rs:96:35 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^^^ help: use `..` instead @@ -381,47 +357,47 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) error: expected one of `=>`, `if`, or `|`, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:102:38 + --> $DIR/attr-stmt-expr-attr-bad.rs:96:38 | LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } } | ^ expected one of `=>`, `if`, or `|` error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:106:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:100:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:106:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:100:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); } | ^ expected one of `.`, `;`, `?`, or an operator error: unexpected token: `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:109:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:103:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } | ^ error: expected one of `.`, `;`, `?`, or an operator, found `#` - --> $DIR/attr-stmt-expr-attr-bad.rs:109:34 + --> $DIR/attr-stmt-expr-attr-bad.rs:103:34 | LL | #[cfg(FALSE)] fn e() { let _ = x.#[attr]foo(); } | ^ expected one of `.`, `;`, `?`, or an operator error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:114:37 + --> $DIR/attr-stmt-expr-attr-bad.rs:108:37 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr]; } } } | ^^^^^^^ error: expected statement after outer attribute - --> $DIR/attr-stmt-expr-attr-bad.rs:116:37 + --> $DIR/attr-stmt-expr-attr-bad.rs:110:37 | LL | #[cfg(FALSE)] fn e() { { fn foo() { #[attr] } } } | ^^^^^^^ -error: aborting due to 57 previous errors +error: aborting due to 53 previous errors For more information about this error, try `rustc --explain E0586`. From 8a3272985b2c9bcd764d72ecf78e9c321b710e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Mar 2020 13:59:51 -0800 Subject: [PATCH 0782/1250] Correctly reject `TraitCandidate` in all cases Follow up to #69255, fix #69629. --- src/librustc_typeck/check/method/probe.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a52cabd8894..4f65b0e87a1 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1403,6 +1403,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let predicate = trait_ref.without_const().to_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; if self.probe(|_| { match self.select_trait_candidate(trait_ref) { Err(_) => return true, @@ -1413,7 +1414,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // Determine exactly which obligation wasn't met, so // that we can give more context in the error. if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; let o = self.resolve_vars_if_possible(obligation); let predicate = self.resolve_vars_if_possible(&predicate); @@ -1431,7 +1431,6 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { _ => { // Some nested subobligation of this predicate // failed. - result = ProbeResult::NoMatch; let predicate = self.resolve_vars_if_possible(&predicate); possibly_unsatisfied_predicates.push((predicate, None)); } From 9384cba72e09790eaf166510bed885ff1771dbfe Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Tue, 3 Mar 2020 09:41:44 +0100 Subject: [PATCH 0783/1250] Documentation and slight simplification of BTreeMap's internals --- src/liballoc/collections/btree/node.rs | 33 +++++++++++++++----------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index c1bd68a020a..c75c12df2d0 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -153,10 +153,15 @@ impl InternalNode { } } -/// An owned pointer to a node. This basically is either `Box>` or -/// `Box>`. However, it contains no information as to which of the two types -/// of nodes is actually behind the box, and, partially due to this lack of information, has no -/// destructor. +/// A managed, non-null pointer to a node. This is either an owned pointer to +/// `LeafNode`, an owned pointer to `InternalNode`, or a (not owned) +/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE). +/// All of these types have a `NodeHeader` prefix, meaning that they have at +/// least the same size as `NodeHeader` and store the same kinds of data at the same +/// offsets; and they have a pointer alignment at least as large as `NodeHeader`'s. +/// However, `BoxedNode` contains no information as to which of the three types +/// of nodes it actually contains, and, partially due to this lack of information, +/// has no destructor. struct BoxedNode { ptr: Unique>, } @@ -167,9 +172,7 @@ impl BoxedNode { } fn from_internal(node: Box>) -> Self { - unsafe { - BoxedNode { ptr: Unique::new_unchecked(Box::into_raw(node) as *mut LeafNode) } - } + BoxedNode { ptr: Box::into_unique(node).cast() } } unsafe fn from_ptr(ptr: NonNull>) -> Self { @@ -181,10 +184,11 @@ impl BoxedNode { } } -/// An owned tree. Note that despite being owned, this does not have a destructor, -/// and must be cleaned up manually. +/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor, +/// and must be cleaned up manually if it is an owned tree. pub struct Root { node: BoxedNode, + /// The number of levels below the root node. height: usize, } @@ -192,21 +196,21 @@ unsafe impl Sync for Root {} unsafe impl Send for Root {} impl Root { + /// Whether the instance of `Root` wraps a shared, empty root node. If not, + /// the entire tree is uniquely owned by the owner of the `Root` instance. pub fn is_shared_root(&self) -> bool { self.as_ref().is_shared_root() } + /// Returns a shared tree, wrapping a shared root node that is eternally empty. pub fn shared_empty_root() -> Self { Root { - node: unsafe { - BoxedNode::from_ptr(NonNull::new_unchecked( - &EMPTY_ROOT_NODE as *const _ as *const LeafNode as *mut _, - )) - }, + node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) }, height: 0, } } + /// Returns a new owned tree, with its own root node that is initially empty. pub fn new_leaf() -> Self { Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 } } @@ -310,6 +314,7 @@ impl Root { /// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior. /// Turning this into a `NodeHeader` reference is always safe. pub struct NodeRef { + /// The number of levels below the node. height: usize, node: NonNull>, // `root` is null unless the borrow type is `Mut` From 91525fd078bb6f3ec833aa42141ea027b37b26a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Mar 2020 16:15:23 -0800 Subject: [PATCH 0784/1250] Tweak output for invalid negative impl AST errors --- src/librustc_ast/ast.rs | 4 +-- src/librustc_ast_passes/ast_validation.rs | 28 ++++++++++++------- src/librustc_ast_passes/feature_gate.rs | 8 +++--- src/librustc_ast_pretty/pprust.rs | 2 +- src/librustc_hir/print.rs | 2 +- src/librustc_parse/parser/item.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/librustc_typeck/coherence/unsafety.rs | 4 +-- src/librustc_typeck/collect.rs | 2 +- .../coherence-negative-impls-safe.stderr | 4 +-- src/test/ui/error-codes/E0197.stderr | 2 +- src/test/ui/error-codes/E0198.stderr | 4 +-- .../feature-gate-optin-builtin-traits.stderr | 4 +-- .../inherent-impl.stderr | 8 +++--- .../defaultimpl/validation.stderr | 2 +- .../syntax-trait-polarity-feature-gate.stderr | 4 +-- src/test/ui/syntax-trait-polarity.stderr | 16 +++++------ .../traits/trait-safety-inherent-impl.stderr | 10 ++----- 18 files changed, 56 insertions(+), 52 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 88564647d61..e86ec2ebfa4 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -2117,14 +2117,14 @@ pub enum ImplPolarity { /// `impl Trait for Type` Positive, /// `impl !Trait for Type` - Negative, + Negative(Span), } impl fmt::Debug for ImplPolarity { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { ImplPolarity::Positive => "positive".fmt(f), - ImplPolarity::Negative => "negative".fmt(f), + ImplPolarity::Negative(_) => "negative".fmt(f), } } } diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 9f04c01bfa8..1070043458a 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -779,7 +779,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { defaultness: _, constness: _, generics: _, - of_trait: Some(_), + of_trait: Some(ref t), ref self_ty, items: _, } => { @@ -794,10 +794,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { .help("use `auto trait Trait {}` instead") .emit(); } - if let (Unsafe::Yes(span), ImplPolarity::Negative) = (unsafety, polarity) { + if let (Unsafe::Yes(span), ImplPolarity::Negative(sp)) = (unsafety, polarity) { struct_span_err!( this.session, - item.span, + sp.to(t.path.span), E0198, "negative impls cannot be unsafe" ) @@ -816,7 +816,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { constness, generics: _, of_trait: None, - self_ty: _, + ref self_ty, items: _, } => { self.invalid_visibility( @@ -826,28 +826,36 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if let Unsafe::Yes(span) = unsafety { struct_span_err!( self.session, - item.span, + vec![span, self_ty.span], E0197, "inherent impls cannot be unsafe" ) .span_label(span, "unsafe because of this") + .span_label(self_ty.span, "inherent impl for this type") .emit(); } - if polarity == ImplPolarity::Negative { - self.err_handler().span_err(item.span, "inherent impls cannot be negative"); + if let ImplPolarity::Negative(span) = polarity { + self.err_handler().span_err(span, "inherent impls cannot be negative"); } if let Defaultness::Default(def_span) = defaultness { - let span = self.session.source_map().def_span(item.span); self.err_handler() - .struct_span_err(span, "inherent impls cannot be `default`") + .struct_span_err( + vec![def_span, self_ty.span], + "inherent impls cannot be `default`", + ) .span_label(def_span, "`default` because of this") + .span_label(self_ty.span, "inherent impl for this type") .note("only trait implementations may be annotated with `default`") .emit(); } if let Const::Yes(span) = constness { self.err_handler() - .struct_span_err(item.span, "inherent impls cannot be `const`") + .struct_span_err( + vec![span, self_ty.span], + "inherent impls cannot be `const`", + ) .span_label(span, "`const` because of this") + .span_label(self_ty.span, "inherent impl for this type") .note("only trait implementations may be annotated with `const`") .emit(); } diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 05e69d0cfd7..3d9001d5d58 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -338,14 +338,14 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } } - ast::ItemKind::Impl { polarity, defaultness, .. } => { - if polarity == ast::ImplPolarity::Negative { + ast::ItemKind::Impl { polarity, defaultness, ref of_trait, .. } => { + if let ast::ImplPolarity::Negative(span) = polarity { gate_feature_post!( &self, optin_builtin_traits, - i.span, + span.to(of_trait.as_ref().map(|t| t.path.span).unwrap_or(span)), "negative trait bounds are not yet fully implemented; \ - use marker types for now" + use marker types for now" ); } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index f95c154bb3b..dbfe5d34bc0 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1175,7 +1175,7 @@ impl<'a> State<'a> { self.s.space(); } - if polarity == ast::ImplPolarity::Negative { + if let ast::ImplPolarity::Negative(_) = polarity { self.s.word("!"); } diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 8cbbef959ce..f03ab41f12d 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -652,7 +652,7 @@ impl<'a> State<'a> { self.word_nbsp("const"); } - if let hir::ImplPolarity::Negative = polarity { + if let hir::ImplPolarity::Negative(_) = polarity { self.s.word("!"); } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 9bca1d09901..09c512f3254 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -414,7 +414,7 @@ impl<'a> Parser<'a> { // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) { self.bump(); // `!` - ast::ImplPolarity::Negative + ast::ImplPolarity::Negative(self.prev_token.span) } else { ast::ImplPolarity::Positive }; diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index 32da62adc3c..4fa226712b7 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -519,7 +519,7 @@ impl Sig for ast::Item { text.push(' '); let trait_sig = if let Some(ref t) = *of_trait { - if polarity == ast::ImplPolarity::Negative { + if let ast::ImplPolarity::Negative(_) = polarity { text.push('!'); } let trait_sig = t.path.make(offset + text.len(), id, scx)?; diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs index a6044217403..3b25f67aacc 100644 --- a/src/librustc_typeck/coherence/unsafety.rs +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -69,11 +69,11 @@ impl UnsafetyChecker<'tcx> { .emit(); } - (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative) => { + (_, _, Unsafety::Unsafe, hir::ImplPolarity::Negative(_)) => { // Reported in AST validation self.tcx.sess.delay_span_bug(item.span, "unsafe negative impl"); } - (_, _, Unsafety::Normal, hir::ImplPolarity::Negative) + (_, _, Unsafety::Normal, hir::ImplPolarity::Negative(_)) | (Unsafety::Unsafe, _, Unsafety::Unsafe, hir::ImplPolarity::Positive) | (Unsafety::Normal, Some(_), Unsafety::Unsafe, hir::ImplPolarity::Positive) | (Unsafety::Normal, None, Unsafety::Normal, _) => { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2dad3d1d6d7..e6c3d5b8b9e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1548,7 +1548,7 @@ fn impl_polarity(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ImplPolarity { let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); let item = tcx.hir().expect_item(hir_id); match &item.kind { - hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative, .. } => { + hir::ItemKind::Impl { polarity: hir::ImplPolarity::Negative(_), .. } => { if is_rustc_reservation { tcx.sess.span_err(item.span, "reservation impls can't be negative"); } diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.stderr b/src/test/ui/coherence/coherence-negative-impls-safe.stderr index 4db66af6783..eebd1de277e 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe.stderr +++ b/src/test/ui/coherence/coherence-negative-impls-safe.stderr @@ -1,8 +1,8 @@ error[E0198]: negative impls cannot be unsafe - --> $DIR/coherence-negative-impls-safe.rs:7:1 + --> $DIR/coherence-negative-impls-safe.rs:7:13 | LL | unsafe impl !Send for TestType {} - | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------ ^^^^^ | | | unsafe because of this diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr index 51ed9c83bc9..bc3c2857958 100644 --- a/src/test/ui/error-codes/E0197.stderr +++ b/src/test/ui/error-codes/E0197.stderr @@ -2,7 +2,7 @@ error[E0197]: inherent impls cannot be unsafe --> $DIR/E0197.rs:3:1 | LL | unsafe impl Foo { } - | ------^^^^^^^^^^^^^ + | ^^^^^^ ^^^ inherent impl for this type | | | unsafe because of this diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr index 90e8b4abd12..43304768700 100644 --- a/src/test/ui/error-codes/E0198.stderr +++ b/src/test/ui/error-codes/E0198.stderr @@ -1,8 +1,8 @@ error[E0198]: negative impls cannot be unsafe - --> $DIR/E0198.rs:5:1 + --> $DIR/E0198.rs:5:13 | LL | unsafe impl !Send for Foo { } - | ------^^^^^^^^^^^^^^^^^^^^^^^ + | ------ ^^^^^ | | | unsafe because of this diff --git a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr index d29c373a33c..490d29ad8a3 100644 --- a/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr +++ b/src/test/ui/feature-gates/feature-gate-optin-builtin-traits.stderr @@ -8,10 +8,10 @@ LL | auto trait AutoDummyTrait {} = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now - --> $DIR/feature-gate-optin-builtin-traits.rs:9:1 + --> $DIR/feature-gate-optin-builtin-traits.rs:9:6 | LL | impl !AutoDummyTrait for DummyStruct {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | = note: see issue #13231 for more information = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr index 3ea58a3728a..0a76c70b97d 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -1,18 +1,18 @@ error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:9:1 + --> $DIR/inherent-impl.rs:9:6 | LL | impl const S {} - | ^^^^^-----^^^^^ + | ^^^^^ ^ inherent impl for this type | | | `const` because of this | = note: only trait implementations may be annotated with `const` error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:12:1 + --> $DIR/inherent-impl.rs:12:6 | LL | impl const T {} - | ^^^^^-----^^^^^ + | ^^^^^ ^ inherent impl for this type | | | `const` because of this | diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 03b1ef69ca0..2a96f41a249 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -2,7 +2,7 @@ error: inherent impls cannot be `default` --> $DIR/validation.rs:7:1 | LL | default impl S {} - | -------^^^^^^^ + | ^^^^^^^ ^ inherent impl for this type | | | `default` because of this | diff --git a/src/test/ui/syntax-trait-polarity-feature-gate.stderr b/src/test/ui/syntax-trait-polarity-feature-gate.stderr index ed76377278b..5d4c1b354f7 100644 --- a/src/test/ui/syntax-trait-polarity-feature-gate.stderr +++ b/src/test/ui/syntax-trait-polarity-feature-gate.stderr @@ -1,8 +1,8 @@ error[E0658]: negative trait bounds are not yet fully implemented; use marker types for now - --> $DIR/syntax-trait-polarity-feature-gate.rs:7:1 + --> $DIR/syntax-trait-polarity-feature-gate.rs:7:6 | LL | impl !Send for TestType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^ | = note: see issue #13231 for more information = help: add `#![feature(optin_builtin_traits)]` to the crate attributes to enable diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr index fef3a650888..b7d5b4570aa 100644 --- a/src/test/ui/syntax-trait-polarity.stderr +++ b/src/test/ui/syntax-trait-polarity.stderr @@ -1,28 +1,28 @@ error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:7:1 + --> $DIR/syntax-trait-polarity.rs:7:6 | LL | impl !TestType {} - | ^^^^^^^^^^^^^^^^^ + | ^ error[E0198]: negative impls cannot be unsafe - --> $DIR/syntax-trait-polarity.rs:12:1 + --> $DIR/syntax-trait-polarity.rs:12:13 | LL | unsafe impl !Send for TestType {} - | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------ ^^^^^ | | | unsafe because of this error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:19:1 + --> $DIR/syntax-trait-polarity.rs:19:9 | LL | impl !TestType2 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^ error[E0198]: negative impls cannot be unsafe - --> $DIR/syntax-trait-polarity.rs:22:1 + --> $DIR/syntax-trait-polarity.rs:22:16 | LL | unsafe impl !Send for TestType2 {} - | ------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------ ^^^^^ | | | unsafe because of this diff --git a/src/test/ui/traits/trait-safety-inherent-impl.stderr b/src/test/ui/traits/trait-safety-inherent-impl.stderr index c398785d394..09ad4585ab1 100644 --- a/src/test/ui/traits/trait-safety-inherent-impl.stderr +++ b/src/test/ui/traits/trait-safety-inherent-impl.stderr @@ -1,14 +1,10 @@ error[E0197]: inherent impls cannot be unsafe --> $DIR/trait-safety-inherent-impl.rs:5:1 | -LL | unsafe impl SomeStruct { - | ^----- - | | - | _unsafe because of this +LL | unsafe impl SomeStruct { + | ^^^^^^ ^^^^^^^^^^ inherent impl for this type | | -LL | | fn foo(self) { } -LL | | } - | |_^ + | unsafe because of this error: aborting due to previous error From 337af5ef7a31855fd7f6d6b77c9e52d6d747c350 Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Thu, 12 Dec 2019 17:23:14 +0100 Subject: [PATCH 0785/1250] Prepare const_limit feature gate and attribute --- .../src/language-features/const-limit.md | 7 +++++++ .../middle/{recursion_limit.rs => limits.rs} | 3 ++- src/librustc_feature/active.rs | 3 +++ src/librustc_feature/builtin_attrs.rs | 4 ++++ src/librustc_session/session.rs | 4 ++++ src/librustc_span/symbol.rs | 1 + .../consts/const_limit/feature-gate-const_limit.rs | 12 ++++++++++++ .../const_limit/feature-gate-const_limit.stderr | 12 ++++++++++++ 8 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/doc/unstable-book/src/language-features/const-limit.md rename src/librustc/middle/{recursion_limit.rs => limits.rs} (94%) create mode 100644 src/test/ui/consts/const_limit/feature-gate-const_limit.rs create mode 100644 src/test/ui/consts/const_limit/feature-gate-const_limit.stderr diff --git a/src/doc/unstable-book/src/language-features/const-limit.md b/src/doc/unstable-book/src/language-features/const-limit.md new file mode 100644 index 00000000000..2fc5963dc6e --- /dev/null +++ b/src/doc/unstable-book/src/language-features/const-limit.md @@ -0,0 +1,7 @@ +# `const_limit` + +The tracking issue for this feature is: [#67217] + +[#57563]: https://github.com/rust-lang/rust/issues/67217 + +The `const_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. \ No newline at end of file diff --git a/src/librustc/middle/recursion_limit.rs b/src/librustc/middle/limits.rs similarity index 94% rename from src/librustc/middle/recursion_limit.rs rename to src/librustc/middle/limits.rs index ae31a2cc63d..a831d99d4ed 100644 --- a/src/librustc/middle/recursion_limit.rs +++ b/src/librustc/middle/limits.rs @@ -1,4 +1,4 @@ -// Recursion limit. +// Registering limits, recursion_limit, type_length_limit and const_limit // // There are various parts of the compiler that must impose arbitrary limits // on how deeply they recurse to prevent stack overflow. Users can override @@ -16,6 +16,7 @@ use rustc_data_structures::sync::Once; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); + update_limit(sess, krate, &sess.const_limit, sym::const_limit, 128); } fn update_limit( diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 0082f4f1a6e..2f9394cd566 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -532,6 +532,9 @@ declare_features! ( /// Allows using `&mut` in constant functions. (active, const_mut_refs, "1.41.0", Some(57349), None), + // Allows limiting the evaluation steps of const expressions + (active, const_limit, "1.41.0", Some(67217), None), + /// Allows the use of `loop` and `while` in constants. (active, const_loop, "1.41.0", Some(52000), None), diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e2e061c185c..2b79f6bd942 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -239,6 +239,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), + gated!( + const_limit, CrateLevel, template!(NameValueStr: "N"), const_limit, + experimental!(const_limit) + ), // Entry point: ungated!(main, Normal, template!(Word)), diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 2fb7977dce9..a8879f00c80 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -88,6 +88,9 @@ pub struct Session { /// The maximum length of types during monomorphization. pub type_length_limit: Once, + /// The maximum blocks a const expression can evaluate. + pub const_limit: Once, + /// Map from imported macro spans (which consist of /// the localized span for the macro body) to the /// macro name and definition span in the source crate. @@ -1053,6 +1056,7 @@ fn build_session_( features: Once::new(), recursion_limit: Once::new(), type_length_limit: Once::new(), + const_limit: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index d6232f32f4c..e92e2fc1d43 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -208,6 +208,7 @@ symbols! { console, const_compare_raw_pointers, const_constructor, + const_limit, const_extern_fn, const_fn, const_fn_union, diff --git a/src/test/ui/consts/const_limit/feature-gate-const_limit.rs b/src/test/ui/consts/const_limit/feature-gate-const_limit.rs new file mode 100644 index 00000000000..11d2b6af25d --- /dev/null +++ b/src/test/ui/consts/const_limit/feature-gate-const_limit.rs @@ -0,0 +1,12 @@ +#![const_limit="1"] +//~^ ERROR the `#[const_limit]` attribute is an experimental feature [E0658] + +const CONSTANT: usize = limit(); + +fn main() {} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/src/test/ui/consts/const_limit/feature-gate-const_limit.stderr b/src/test/ui/consts/const_limit/feature-gate-const_limit.stderr new file mode 100644 index 00000000000..db248994b47 --- /dev/null +++ b/src/test/ui/consts/const_limit/feature-gate-const_limit.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[const_limit]` attribute is an experimental feature + --> $DIR/feature-gate-const_limit.rs:1:1 + | +LL | #![const_limit="1"] + | ^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67217 + = help: add `#![feature(const_limit)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. From ff38babc31a364e77d1d4d3702c91884b073af17 Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Fri, 13 Dec 2019 09:38:07 +0100 Subject: [PATCH 0786/1250] Disable CTFE if const_limit was set to 0, otherwise use the value set, which defaults to 1_000_000 --- src/librustc/middle/limits.rs | 14 +++++++------- .../consts/const_limit/const_limit_not_reached.rs | 15 +++++++++++++++ .../ui/consts/const_limit/const_limit_overflow.rs | 15 +++++++++++++++ .../const_limit/feature-gate-const_limit.rs | 4 +++- 4 files changed, 40 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/consts/const_limit/const_limit_not_reached.rs create mode 100644 src/test/ui/consts/const_limit/const_limit_overflow.rs diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index a831d99d4ed..6ed0a498c7d 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -1,9 +1,9 @@ -// Registering limits, recursion_limit, type_length_limit and const_limit -// -// There are various parts of the compiler that must impose arbitrary limits -// on how deeply they recurse to prevent stack overflow. Users can override -// this via an attribute on the crate like `#![recursion_limit="22"]`. This pass -// just peeks and looks for that attribute. +//! Registering limits, recursion_limit, type_length_limit and const_limit +//! +//! There are various parts of the compiler that must impose arbitrary limits +//! on how deeply they recurse to prevent stack overflow. Users can override +//! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass +//! just peeks and looks for that attribute. use crate::session::Session; use core::num::IntErrorKind; @@ -16,7 +16,7 @@ use rustc_data_structures::sync::Once; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); - update_limit(sess, krate, &sess.const_limit, sym::const_limit, 128); + update_limit(sess, krate, &sess.const_limit, sym::const_limit, 1_000_000); } fn update_limit( diff --git a/src/test/ui/consts/const_limit/const_limit_not_reached.rs b/src/test/ui/consts/const_limit/const_limit_not_reached.rs new file mode 100644 index 00000000000..24c0f92af34 --- /dev/null +++ b/src/test/ui/consts/const_limit/const_limit_not_reached.rs @@ -0,0 +1,15 @@ +// run-pass +#![feature(const_limit)] +#![const_limit="1000"] + +const CONSTANT: usize = limit(); + +fn main() { + assert_eq!(CONSTANT, 1764); +} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/src/test/ui/consts/const_limit/const_limit_overflow.rs b/src/test/ui/consts/const_limit/const_limit_overflow.rs new file mode 100644 index 00000000000..bea40e60261 --- /dev/null +++ b/src/test/ui/consts/const_limit/const_limit_overflow.rs @@ -0,0 +1,15 @@ +// run-pass +#![feature(const_limit)] +#![const_limit="18_446_744_073_709_551_615"] + +const CONSTANT: usize = limit(); + +fn main() { + assert_eq!(CONSTANT, 1764); +} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/src/test/ui/consts/const_limit/feature-gate-const_limit.rs b/src/test/ui/consts/const_limit/feature-gate-const_limit.rs index 11d2b6af25d..761e80050a6 100644 --- a/src/test/ui/consts/const_limit/feature-gate-const_limit.rs +++ b/src/test/ui/consts/const_limit/feature-gate-const_limit.rs @@ -3,7 +3,9 @@ const CONSTANT: usize = limit(); -fn main() {} +fn main() { + assert_eq!(CONSTANT, 1764); +} const fn limit() -> usize { let x = 42; From 288e142737af75007ef973c037cd4ded87d7e510 Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Sat, 14 Dec 2019 18:51:56 +0100 Subject: [PATCH 0787/1250] Add a new test to reach const_limit setting, although with wrong WARNINGs yet rename feature to const_eval_limit --- .../src/language-features/const-eval-limit.md | 7 +++++++ .../src/language-features/const-limit.md | 7 ------- src/librustc/middle/limits.rs | 4 ++-- src/librustc/middle/mod.rs | 2 +- src/librustc_feature/active.rs | 2 +- src/librustc_feature/builtin_attrs.rs | 4 ++-- src/librustc_interface/passes.rs | 2 +- src/librustc_session/session.rs | 4 ++-- src/librustc_span/symbol.rs | 2 +- ...overflow.rs => const_eval_limit_not_reached.rs} | 6 +++--- ...const_limit.rs => const_eval_limit_overflow.rs} | 5 +++-- ..._not_reached.rs => const_eval_limit_reached.rs} | 6 +++--- .../const_limit/feature-gate-const_eval_limit.rs | 14 ++++++++++++++ .../feature-gate-const_eval_limit.stderr | 12 ++++++++++++ .../const_limit/feature-gate-const_limit.stderr | 12 ------------ 15 files changed, 52 insertions(+), 37 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/const-eval-limit.md delete mode 100644 src/doc/unstable-book/src/language-features/const-limit.md rename src/test/ui/consts/const_limit/{const_limit_overflow.rs => const_eval_limit_not_reached.rs} (63%) rename src/test/ui/consts/const_limit/{feature-gate-const_limit.rs => const_eval_limit_overflow.rs} (59%) rename src/test/ui/consts/const_limit/{const_limit_not_reached.rs => const_eval_limit_reached.rs} (66%) create mode 100644 src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs create mode 100644 src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr delete mode 100644 src/test/ui/consts/const_limit/feature-gate-const_limit.stderr diff --git a/src/doc/unstable-book/src/language-features/const-eval-limit.md b/src/doc/unstable-book/src/language-features/const-eval-limit.md new file mode 100644 index 00000000000..d1442d866dc --- /dev/null +++ b/src/doc/unstable-book/src/language-features/const-eval-limit.md @@ -0,0 +1,7 @@ +# `const_eval_limit` + +The tracking issue for this feature is: [#67217] + +[#57563]: https://github.com/rust-lang/rust/issues/67217 + +The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. \ No newline at end of file diff --git a/src/doc/unstable-book/src/language-features/const-limit.md b/src/doc/unstable-book/src/language-features/const-limit.md deleted file mode 100644 index 2fc5963dc6e..00000000000 --- a/src/doc/unstable-book/src/language-features/const-limit.md +++ /dev/null @@ -1,7 +0,0 @@ -# `const_limit` - -The tracking issue for this feature is: [#67217] - -[#57563]: https://github.com/rust-lang/rust/issues/67217 - -The `const_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. \ No newline at end of file diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index 6ed0a498c7d..19eb8a3fab8 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -1,4 +1,4 @@ -//! Registering limits, recursion_limit, type_length_limit and const_limit +//! Registering limits, recursion_limit, type_length_limit and const_eval_limit //! //! There are various parts of the compiler that must impose arbitrary limits //! on how deeply they recurse to prevent stack overflow. Users can override @@ -16,7 +16,7 @@ use rustc_data_structures::sync::Once; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576); - update_limit(sess, krate, &sess.const_limit, sym::const_limit, 1_000_000); + update_limit(sess, krate, &sess.const_eval_limit, sym::const_eval_limit, 1_000_000); } fn update_limit( diff --git a/src/librustc/middle/mod.rs b/src/librustc/middle/mod.rs index b20f2cf3a85..464488964af 100644 --- a/src/librustc/middle/mod.rs +++ b/src/librustc/middle/mod.rs @@ -28,8 +28,8 @@ pub mod lib_features { } } } +pub mod limits; pub mod privacy; -pub mod recursion_limit; pub mod region; pub mod resolve_lifetime; pub mod stability; diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 2f9394cd566..9bfb1a3a664 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -533,7 +533,7 @@ declare_features! ( (active, const_mut_refs, "1.41.0", Some(57349), None), // Allows limiting the evaluation steps of const expressions - (active, const_limit, "1.41.0", Some(67217), None), + (active, const_eval_limit, "1.41.0", Some(67217), None), /// Allows the use of `loop` and `while` in constants. (active, const_loop, "1.41.0", Some(52000), None), diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index 2b79f6bd942..c140adf64d5 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -240,8 +240,8 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N")), ungated!(type_length_limit, CrateLevel, template!(NameValueStr: "N")), gated!( - const_limit, CrateLevel, template!(NameValueStr: "N"), const_limit, - experimental!(const_limit) + const_eval_limit, CrateLevel, template!(NameValueStr: "N"), const_eval_limit, + experimental!(const_eval_limit) ), // Entry point: diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 1e9b76c3e14..29e9ea1833f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -189,7 +189,7 @@ pub fn register_plugins<'a>( } sess.time("recursion_limit", || { - middle::recursion_limit::update_limits(sess, &krate); + middle::limits::update_limits(sess, &krate); }); let mut lint_store = rustc_lint::new_lint_store( diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index a8879f00c80..173b120e1f6 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -89,7 +89,7 @@ pub struct Session { pub type_length_limit: Once, /// The maximum blocks a const expression can evaluate. - pub const_limit: Once, + pub const_eval_limit: Once, /// Map from imported macro spans (which consist of /// the localized span for the macro body) to the @@ -1056,7 +1056,7 @@ fn build_session_( features: Once::new(), recursion_limit: Once::new(), type_length_limit: Once::new(), - const_limit: Once::new(), + const_eval_limit: Once::new(), imported_macro_spans: OneThread::new(RefCell::new(FxHashMap::default())), incr_comp_session: OneThread::new(RefCell::new(IncrCompSession::NotInitialized)), cgu_reuse_tracker, diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index e92e2fc1d43..c39f9f360c0 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -208,7 +208,7 @@ symbols! { console, const_compare_raw_pointers, const_constructor, - const_limit, + const_eval_limit, const_extern_fn, const_fn, const_fn_union, diff --git a/src/test/ui/consts/const_limit/const_limit_overflow.rs b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs similarity index 63% rename from src/test/ui/consts/const_limit/const_limit_overflow.rs rename to src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs index bea40e60261..4ed908312fb 100644 --- a/src/test/ui/consts/const_limit/const_limit_overflow.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_not_reached.rs @@ -1,6 +1,6 @@ -// run-pass -#![feature(const_limit)] -#![const_limit="18_446_744_073_709_551_615"] +// check-pass +#![feature(const_eval_limit)] +#![const_eval_limit="1000"] const CONSTANT: usize = limit(); diff --git a/src/test/ui/consts/const_limit/feature-gate-const_limit.rs b/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs similarity index 59% rename from src/test/ui/consts/const_limit/feature-gate-const_limit.rs rename to src/test/ui/consts/const_limit/const_eval_limit_overflow.rs index 761e80050a6..38e70f997f0 100644 --- a/src/test/ui/consts/const_limit/feature-gate-const_limit.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs @@ -1,5 +1,6 @@ -#![const_limit="1"] -//~^ ERROR the `#[const_limit]` attribute is an experimental feature [E0658] +// check-pass +#![feature(const_eval_limit)] +#![const_eval_limit="18_446_744_073_709_551_615"] const CONSTANT: usize = limit(); diff --git a/src/test/ui/consts/const_limit/const_limit_not_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs similarity index 66% rename from src/test/ui/consts/const_limit/const_limit_not_reached.rs rename to src/test/ui/consts/const_limit/const_eval_limit_reached.rs index 24c0f92af34..86570c240e5 100644 --- a/src/test/ui/consts/const_limit/const_limit_not_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs @@ -1,6 +1,6 @@ -// run-pass -#![feature(const_limit)] -#![const_limit="1000"] +// check-pass +#![feature(const_eval_limit)] +#![const_eval_limit="2"] const CONSTANT: usize = limit(); diff --git a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs new file mode 100644 index 00000000000..61119d7511d --- /dev/null +++ b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.rs @@ -0,0 +1,14 @@ +#![const_eval_limit="42"] +//~^ ERROR the `#[const_eval_limit]` attribute is an experimental feature [E0658] + +const CONSTANT: usize = limit(); + +fn main() { + assert_eq!(CONSTANT, 1764); +} + +const fn limit() -> usize { + let x = 42; + + x * 42 +} diff --git a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr new file mode 100644 index 00000000000..790ba2483a1 --- /dev/null +++ b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr @@ -0,0 +1,12 @@ +error[E0658]: the `#[const_eval_limit]` attribute is an experimental feature + --> $DIR/feature-gate-const_eval_limit.rs:1:1 + | +LL | #![const_eval_limit="42"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: for more information, see https://github.com/rust-lang/rust/issues/67217 + = help: add `#![feature(const_eval_limit)]` 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/consts/const_limit/feature-gate-const_limit.stderr b/src/test/ui/consts/const_limit/feature-gate-const_limit.stderr deleted file mode 100644 index db248994b47..00000000000 --- a/src/test/ui/consts/const_limit/feature-gate-const_limit.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: the `#[const_limit]` attribute is an experimental feature - --> $DIR/feature-gate-const_limit.rs:1:1 - | -LL | #![const_limit="1"] - | ^^^^^^^^^^^^^^^^^^^ - | - = note: for more information, see https://github.com/rust-lang/rust/issues/67217 - = help: add `#![feature(const_limit)]` to the crate attributes to enable - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0658`. From c94c74e2d936213cabcbb9675f81007ac7c3b78a Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Tue, 21 Jan 2020 16:46:07 +0100 Subject: [PATCH 0788/1250] Opt out of CTFE if the 'const_eval_limit' is set to 0 --- .../src/language-features/const-eval-limit.md | 4 ++-- src/librustc_mir/const_eval/eval_queries.rs | 4 ++-- src/librustc_mir/const_eval/machine.rs | 18 +++++++++++++----- .../const_limit/const_eval_limit_reached.rs | 2 ++ .../const_eval_limit_reached.stderr | 6 ++++++ .../feature-gate-const_eval_limit.stderr | 2 +- 6 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/consts/const_limit/const_eval_limit_reached.stderr diff --git a/src/doc/unstable-book/src/language-features/const-eval-limit.md b/src/doc/unstable-book/src/language-features/const-eval-limit.md index d1442d866dc..df68e83bcac 100644 --- a/src/doc/unstable-book/src/language-features/const-eval-limit.md +++ b/src/doc/unstable-book/src/language-features/const-eval-limit.md @@ -2,6 +2,6 @@ The tracking issue for this feature is: [#67217] -[#57563]: https://github.com/rust-lang/rust/issues/67217 +[#67217]: https://github.com/rust-lang/rust/issues/67217 -The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. \ No newline at end of file +The `const_eval_limit` allows someone to limit the evaluation steps the CTFE undertakes to evaluate a `const fn`. diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 4d5464f774f..1bf748e66e2 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -89,7 +89,7 @@ pub(super) fn mk_eval_cx<'mir, 'tcx>( InterpCx::new( tcx.at(span), param_env, - CompileTimeInterpreter::new(), + CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()), MemoryExtra { can_access_statics }, ) } @@ -297,7 +297,7 @@ pub fn const_eval_raw_provider<'tcx>( let mut ecx = InterpCx::new( tcx.at(span), key.param_env, - CompileTimeInterpreter::new(), + CompileTimeInterpreter::new(*tcx.sess.const_eval_limit.get()), MemoryExtra { can_access_statics: is_static }, ); diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index 25727b75faf..ed802983468 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -3,6 +3,7 @@ use rustc::ty::layout::HasTyCtxt; use rustc::ty::{self, Ty}; use std::borrow::{Borrow, Cow}; use std::collections::hash_map::Entry; +use std::convert::TryFrom; use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; @@ -85,9 +86,6 @@ impl<'mir, 'tcx> InterpCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>> { } } -/// Number of steps until the detector even starts doing anything. -/// Also, a warning is shown to the user when this number is reached. -const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000; /// The number of steps between loop detector snapshots. /// Should be a power of two for performance reasons. const DETECTOR_SNAPSHOT_PERIOD: isize = 256; @@ -100,6 +98,8 @@ pub struct CompileTimeInterpreter<'mir, 'tcx> { /// detector period. pub(super) steps_since_detector_enabled: isize, + pub(super) is_detector_enabled: bool, + /// Extra state to detect loops. pub(super) loop_detector: snapshot::InfiniteLoopDetector<'mir, 'tcx>, } @@ -111,10 +111,14 @@ pub struct MemoryExtra { } impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> { - pub(super) fn new() -> Self { + pub(super) fn new(const_eval_limit: usize) -> Self { + let steps_until_detector_enabled = + isize::try_from(const_eval_limit).unwrap_or(std::isize::MAX); + CompileTimeInterpreter { loop_detector: Default::default(), - steps_since_detector_enabled: -STEPS_UNTIL_DETECTOR_ENABLED, + steps_since_detector_enabled: -steps_until_detector_enabled, + is_detector_enabled: const_eval_limit != 0, } } } @@ -343,6 +347,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + if !ecx.machine.is_detector_enabled { + return Ok(()); + } + { let steps = &mut ecx.machine.steps_since_detector_enabled; diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs index 86570c240e5..1e146d447fa 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs @@ -1,8 +1,10 @@ +// only-x86_64 // check-pass #![feature(const_eval_limit)] #![const_eval_limit="2"] const CONSTANT: usize = limit(); +//~^ WARNING Constant evaluating a complex constant, this might take some time fn main() { assert_eq!(CONSTANT, 1764); diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr new file mode 100644 index 00000000000..8301dff6005 --- /dev/null +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -0,0 +1,6 @@ +warning: Constant evaluating a complex constant, this might take some time + --> $DIR/const_eval_limit_reached.rs:6:1 + | +LL | const CONSTANT: usize = limit(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + diff --git a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr index 790ba2483a1..5bd29c7dfd2 100644 --- a/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr +++ b/src/test/ui/consts/const_limit/feature-gate-const_eval_limit.stderr @@ -4,7 +4,7 @@ error[E0658]: the `#[const_eval_limit]` attribute is an experimental feature LL | #![const_eval_limit="42"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: for more information, see https://github.com/rust-lang/rust/issues/67217 + = note: see issue #67217 for more information = help: add `#![feature(const_eval_limit)]` to the crate attributes to enable error: aborting due to previous error From 527456e219d1d898eee53b2d0e29cdb296c7bab8 Mon Sep 17 00:00:00 2001 From: Christoph Schmidler Date: Wed, 19 Feb 2020 10:24:16 +0100 Subject: [PATCH 0789/1250] Bumped version number for const_eval_limit in active.rs and renamed 'recursion_limit' in limits.rs to simple 'limit' because it does handle other limits too. --- src/librustc/middle/limits.rs | 14 ++++++-------- src/librustc_feature/active.rs | 6 +++--- .../const_limit/const_eval_limit_overflow.rs | 2 +- .../const_limit/const_eval_limit_overflow.stderr | 10 ++++++++++ .../consts/const_limit/const_eval_limit_reached.rs | 6 +++++- .../const_limit/const_eval_limit_reached.stderr | 12 +++++++++++- src/test/ui/recursion_limit/empty.rs | 4 ++-- src/test/ui/recursion_limit/empty.stderr | 4 ++-- src/test/ui/recursion_limit/invalid_digit.rs | 2 +- src/test/ui/recursion_limit/invalid_digit.stderr | 2 +- src/test/ui/recursion_limit/overflow.rs | 4 ++-- src/test/ui/recursion_limit/overflow.stderr | 4 ++-- src/test/ui/recursion_limit/zero.rs | 2 +- 13 files changed, 47 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index 19eb8a3fab8..22e4f5ea222 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -38,10 +38,8 @@ fn update_limit( return; } Err(e) => { - let mut err = sess.struct_span_err( - attr.span, - "`recursion_limit` must be a non-negative integer", - ); + let mut err = + sess.struct_span_err(attr.span, "`limit` must be a non-negative integer"); let value_span = attr .meta() @@ -50,11 +48,11 @@ fn update_limit( .unwrap_or(attr.span); let error_str = match e.kind() { - IntErrorKind::Overflow => "`recursion_limit` is too large", - IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer", + IntErrorKind::Overflow => "`limit` is too large", + IntErrorKind::Empty => "`limit` must be a non-negative integer", IntErrorKind::InvalidDigit => "not a valid integer", - IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"), - IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"), + IntErrorKind::Underflow => bug!("`limit` should never underflow"), + IntErrorKind::Zero => bug!("zero is a valid `limit`"), kind => bug!("unimplemented IntErrorKind variant: {:?}", kind), }; diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 9bfb1a3a664..6517a22701b 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -532,9 +532,6 @@ declare_features! ( /// Allows using `&mut` in constant functions. (active, const_mut_refs, "1.41.0", Some(57349), None), - // Allows limiting the evaluation steps of const expressions - (active, const_eval_limit, "1.41.0", Some(67217), None), - /// Allows the use of `loop` and `while` in constants. (active, const_loop, "1.41.0", Some(52000), None), @@ -555,6 +552,9 @@ declare_features! ( /// Allows the use of `no_sanitize` attribute. (active, no_sanitize, "1.42.0", Some(39699), None), + // Allows limiting the evaluation steps of const expressions + (active, const_eval_limit, "1.43.0", Some(67217), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs b/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs index 38e70f997f0..1c49593cd53 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_overflow.rs @@ -1,6 +1,6 @@ -// check-pass #![feature(const_eval_limit)] #![const_eval_limit="18_446_744_073_709_551_615"] +//~^ ERROR `limit` must be a non-negative integer const CONSTANT: usize = limit(); diff --git a/src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr b/src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr new file mode 100644 index 00000000000..7f5d5e6cd4c --- /dev/null +++ b/src/test/ui/consts/const_limit/const_eval_limit_overflow.stderr @@ -0,0 +1,10 @@ +error: `limit` must be a non-negative integer + --> $DIR/const_eval_limit_overflow.rs:2:1 + | +LL | #![const_eval_limit="18_446_744_073_709_551_615"] + | ^^^^^^^^^^^^^^^^^^^^----------------------------^ + | | + | not a valid integer + +error: aborting due to previous error + diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs index 1e146d447fa..d962398d413 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.rs +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.rs @@ -1,5 +1,9 @@ +// ignore-tidy-linelength // only-x86_64 // check-pass +// NOTE: We always compile this test with -Copt-level=0 because higher opt-levels +// optimize away the const function +// compile-flags:-Copt-level=0 #![feature(const_eval_limit)] #![const_eval_limit="2"] @@ -10,7 +14,7 @@ fn main() { assert_eq!(CONSTANT, 1764); } -const fn limit() -> usize { +const fn limit() -> usize { //~ WARNING Constant evaluating a complex constant, this might take some time let x = 42; x * 42 diff --git a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr index 8301dff6005..e0871ff7185 100644 --- a/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr +++ b/src/test/ui/consts/const_limit/const_eval_limit_reached.stderr @@ -1,5 +1,15 @@ warning: Constant evaluating a complex constant, this might take some time - --> $DIR/const_eval_limit_reached.rs:6:1 + --> $DIR/const_eval_limit_reached.rs:17:1 + | +LL | / const fn limit() -> usize { +LL | | let x = 42; +LL | | +LL | | x * 42 +LL | | } + | |_^ + +warning: Constant evaluating a complex constant, this might take some time + --> $DIR/const_eval_limit_reached.rs:10:1 | LL | const CONSTANT: usize = limit(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/recursion_limit/empty.rs b/src/test/ui/recursion_limit/empty.rs index 2a064f3e115..31ff9c1e3a7 100644 --- a/src/test/ui/recursion_limit/empty.rs +++ b/src/test/ui/recursion_limit/empty.rs @@ -1,6 +1,6 @@ // Test the parse error for an empty recursion_limit -#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer - //~| `recursion_limit` must be a non-negative integer +#![recursion_limit = ""] //~ ERROR `limit` must be a non-negative integer + //~| `limit` must be a non-negative integer fn main() {} diff --git a/src/test/ui/recursion_limit/empty.stderr b/src/test/ui/recursion_limit/empty.stderr index 690c33a7463..bcd1d27e59b 100644 --- a/src/test/ui/recursion_limit/empty.stderr +++ b/src/test/ui/recursion_limit/empty.stderr @@ -1,10 +1,10 @@ -error: `recursion_limit` must be a non-negative integer +error: `limit` must be a non-negative integer --> $DIR/empty.rs:3:1 | LL | #![recursion_limit = ""] | ^^^^^^^^^^^^^^^^^^^^^--^ | | - | `recursion_limit` must be a non-negative integer + | `limit` must be a non-negative integer error: aborting due to previous error diff --git a/src/test/ui/recursion_limit/invalid_digit.rs b/src/test/ui/recursion_limit/invalid_digit.rs index 903d8040476..759d69d0af2 100644 --- a/src/test/ui/recursion_limit/invalid_digit.rs +++ b/src/test/ui/recursion_limit/invalid_digit.rs @@ -1,6 +1,6 @@ // Test the parse error for an invalid digit in recursion_limit -#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer +#![recursion_limit = "-100"] //~ ERROR `limit` must be a non-negative integer //~| not a valid integer fn main() {} diff --git a/src/test/ui/recursion_limit/invalid_digit.stderr b/src/test/ui/recursion_limit/invalid_digit.stderr index 1dcfea547c0..e6fd6b72a09 100644 --- a/src/test/ui/recursion_limit/invalid_digit.stderr +++ b/src/test/ui/recursion_limit/invalid_digit.stderr @@ -1,4 +1,4 @@ -error: `recursion_limit` must be a non-negative integer +error: `limit` must be a non-negative integer --> $DIR/invalid_digit.rs:3:1 | LL | #![recursion_limit = "-100"] diff --git a/src/test/ui/recursion_limit/overflow.rs b/src/test/ui/recursion_limit/overflow.rs index 6487b1350aa..8eee2792b23 100644 --- a/src/test/ui/recursion_limit/overflow.rs +++ b/src/test/ui/recursion_limit/overflow.rs @@ -1,7 +1,7 @@ // Test the parse error for an overflowing recursion_limit #![recursion_limit = "999999999999999999999999"] -//~^ ERROR `recursion_limit` must be a non-negative integer -//~| `recursion_limit` is too large +//~^ ERROR `limit` must be a non-negative integer +//~| `limit` is too large fn main() {} diff --git a/src/test/ui/recursion_limit/overflow.stderr b/src/test/ui/recursion_limit/overflow.stderr index c3fc11989dc..f6ed76c1ebc 100644 --- a/src/test/ui/recursion_limit/overflow.stderr +++ b/src/test/ui/recursion_limit/overflow.stderr @@ -1,10 +1,10 @@ -error: `recursion_limit` must be a non-negative integer +error: `limit` must be a non-negative integer --> $DIR/overflow.rs:3:1 | LL | #![recursion_limit = "999999999999999999999999"] | ^^^^^^^^^^^^^^^^^^^^^--------------------------^ | | - | `recursion_limit` is too large + | `limit` is too large error: aborting due to previous error diff --git a/src/test/ui/recursion_limit/zero.rs b/src/test/ui/recursion_limit/zero.rs index f7199944e00..eb95d7babc6 100644 --- a/src/test/ui/recursion_limit/zero.rs +++ b/src/test/ui/recursion_limit/zero.rs @@ -1,4 +1,4 @@ -// Test that a `recursion_limit` of 0 is valid +// Test that a `limit` of 0 is valid #![recursion_limit = "0"] From 6ed4829c17bb3bf627fa09b5c15be7e47610acf8 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Thu, 5 Mar 2020 08:52:46 +0100 Subject: [PATCH 0790/1250] Make link to `std::str` active --- src/libcore/str/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 9c0db5d9872..6ad0e68a88f 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -2,7 +2,9 @@ //! String manipulation. //! -//! For more details, see the `std::str` module. +//! For more details, see the [`std::str`] module. +//! +//! [`std::str`]: ../../std/str/index.html #![stable(feature = "rust1", since = "1.0.0")] From 6b28a8c46f0578d5edef19d4ba7500bae63c7962 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 5 Mar 2020 13:05:08 +0100 Subject: [PATCH 0791/1250] Clean E0382 and E0384 explanations --- src/librustc_error_codes/error_codes/E0382.md | 3 +-- src/librustc_error_codes/error_codes/E0384.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0382.md b/src/librustc_error_codes/error_codes/E0382.md index 1592eac2ec5..9ea9b9ed113 100644 --- a/src/librustc_error_codes/error_codes/E0382.md +++ b/src/librustc_error_codes/error_codes/E0382.md @@ -1,5 +1,4 @@ -This error occurs when an attempt is made to use a variable after its contents -have been moved elsewhere. +A variable was used after its contents have been moved elsewhere. Erroneous code example: diff --git a/src/librustc_error_codes/error_codes/E0384.md b/src/librustc_error_codes/error_codes/E0384.md index 7c7ee744a8c..e21fac0797c 100644 --- a/src/librustc_error_codes/error_codes/E0384.md +++ b/src/librustc_error_codes/error_codes/E0384.md @@ -1,4 +1,4 @@ -This error occurs when an attempt is made to reassign an immutable variable. +An immutable variable was reassigned. Erroneous code example: From d6a17b598f0e82535fc38c8455aed9571f44aaa2 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 4 Mar 2020 14:21:38 +0900 Subject: [PATCH 0792/1250] Move tidy check to mingw-check --- src/ci/docker/mingw-check/Dockerfile | 1 + src/ci/docker/x86_64-gnu-llvm-7/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/mingw-check/Dockerfile b/src/ci/docker/mingw-check/Dockerfile index b2d96aed2a9..e973ba2e33c 100644 --- a/src/ci/docker/mingw-check/Dockerfile +++ b/src/ci/docker/mingw-check/Dockerfile @@ -25,4 +25,5 @@ ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1 ENV SCRIPT python2.7 ../x.py check --target=i686-pc-windows-gnu --host=i686-pc-windows-gnu && \ python2.7 ../x.py build --stage 0 src/tools/build-manifest && \ python2.7 ../x.py test --stage 0 src/tools/compiletest && \ + python2.7 ../x.py test src/tools/tidy && \ /scripts/validate-toolstate.sh diff --git a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile index dc90c286f5c..284c1e763e5 100644 --- a/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile +++ b/src/ci/docker/x86_64-gnu-llvm-7/Dockerfile @@ -28,7 +28,7 @@ ENV RUST_CONFIGURE_ARGS \ --enable-llvm-link-shared \ --set rust.thin-lto-import-instr-limit=10 -ENV SCRIPT python2.7 ../x.py test src/tools/tidy && python2.7 ../x.py test +ENV SCRIPT python2.7 ../x.py test --exclude src/tools/tidy && python2.7 ../x.py test src/tools/tidy # The purpose of this container isn't to test with debug assertions and # this is run on all PRs, so let's get speedier builds by disabling these extra From e54a16cffce0ecea2954b5af51247f7b4179900b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 5 Mar 2020 00:00:00 +0000 Subject: [PATCH 0793/1250] Change DIBuilderCreateEnumerator signature to match LLVM 9 No functional changes intended. --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 16 ++++++++++------ src/librustc_codegen_llvm/llvm/ffi.rs | 4 +++- src/rustllvm/RustWrapper.cpp | 8 ++++---- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3916653eb1d..7beaf134e6b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1779,13 +1779,15 @@ fn prepare_enum_metadata( .discriminants(cx.tcx) .zip(&def.variants) .map(|((_, discr), v)| { - let name = SmallCStr::new(&v.ident.as_str()); + let name = v.ident.as_str(); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), - name.as_ptr(), + name.as_ptr().cast(), + name.len(), // FIXME: what if enumeration has i128 discriminant? - discr.val as u64, + discr.val as i64, + false, // FIXME: IsUnsigned. )) } }) @@ -1794,13 +1796,15 @@ fn prepare_enum_metadata( .as_generator() .variant_range(enum_def_id, cx.tcx) .map(|variant_index| { - let name = SmallCStr::new(&substs.as_generator().variant_name(variant_index)); + let name = substs.as_generator().variant_name(variant_index); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), - name.as_ptr(), + name.as_ptr().cast(), + name.len(), // FIXME: what if enumeration has i128 discriminant? - variant_index.as_usize() as u64, + variant_index.as_usize() as i64, + false, // FIXME: IsUnsigned. )) } }) diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index f56647044e0..8b796e0423b 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1776,7 +1776,9 @@ extern "C" { pub fn LLVMRustDIBuilderCreateEnumerator( Builder: &DIBuilder<'a>, Name: *const c_char, - Val: u64, + NameLen: size_t, + Value: i64, + IsUnsigned: bool, ) -> &'a DIEnumerator; pub fn LLVMRustDIBuilderCreateEnumerationType( diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 49b6e1bfec3..0e430d3881e 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -891,10 +891,10 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( unwrap(InsertAtEnd))); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateEnumerator(LLVMRustDIBuilderRef Builder, - const char *Name, uint64_t Val) { - return wrap(Builder->createEnumerator(Name, Val)); +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( + LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, + int64_t Value, bool IsUnsigned) { + return wrap(Builder->createEnumerator({Name, NameLen}, Value, IsUnsigned)); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( From 726d5185e00d37ad7bd24aac4f05bf9fd34765be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 5 Mar 2020 00:00:00 +0000 Subject: [PATCH 0794/1250] bootstrap: Use hash to determine if sanitizers needs to be rebuilt * Rebuild sanitizers runtimes when LLVM submodule commit changes. * When rebuilding LLVM / sanitizers, remove the stamp file before starting the build process to invalidate previous build output. --- src/bootstrap/native.rs | 98 ++++++++++++++++++++++++++++------------- 1 file changed, 67 insertions(+), 31 deletions(-) diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index c22c2a336f1..d4d66abd520 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -11,6 +11,7 @@ use std::env; use std::ffi::OsString; use std::fs::{self, File}; +use std::io; use std::path::{Path, PathBuf}; use std::process::Command; @@ -54,7 +55,6 @@ impl Step for Llvm { } } - let llvm_info = &builder.in_tree_llvm_info; let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build); @@ -65,40 +65,35 @@ impl Step for Llvm { let build_llvm_config = llvm_config_ret_dir.join(exe("llvm-config", &*builder.config.build)); - let done_stamp = out_dir.join("llvm-finished-building"); - if done_stamp.exists() { - if builder.config.llvm_skip_rebuild { - builder.info( - "Warning: \ - Using a potentially stale build of LLVM; \ - This may not behave well.", - ); - return build_llvm_config; - } + let stamp = out_dir.join("llvm-finished-building"); + let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); - if let Some(llvm_commit) = llvm_info.sha() { - let done_contents = t!(fs::read(&done_stamp)); + if builder.config.llvm_skip_rebuild && stamp.path.exists() { + builder.info( + "Warning: \ + Using a potentially stale build of LLVM; \ + This may not behave well.", + ); + return build_llvm_config; + } - // If LLVM was already built previously and the submodule's commit didn't change - // from the previous build, then no action is required. - if done_contents == llvm_commit.as_bytes() { - return build_llvm_config; - } - } else { + if stamp.is_done() { + if stamp.hash.is_none() { builder.info( "Could not determine the LLVM submodule commit hash. \ Assuming that an LLVM rebuild is not necessary.", ); builder.info(&format!( "To force LLVM to rebuild, remove the file `{}`", - done_stamp.display() + stamp.path.display() )); - return build_llvm_config; } + return build_llvm_config; } builder.info(&format!("Building LLVM for {}", target)); + t!(stamp.remove()); let _time = util::timeit(&builder); t!(fs::create_dir_all(&out_dir)); @@ -271,7 +266,7 @@ impl Step for Llvm { cfg.build(); - t!(fs::write(&done_stamp, llvm_info.sha().unwrap_or(""))); + t!(stamp.write()); build_llvm_config } @@ -584,17 +579,21 @@ impl Step for Sanitizers { return runtimes; } - let done_stamp = out_dir.join("sanitizers-finished-building"); - if done_stamp.exists() { - builder.info(&format!( - "Assuming that sanitizers rebuild is not necessary. \ - To force a rebuild, remove the file `{}`", - done_stamp.display() - )); + let stamp = out_dir.join("sanitizers-finished-building"); + let stamp = HashStamp::new(stamp, builder.in_tree_llvm_info.sha()); + + if stamp.is_done() { + if stamp.hash.is_none() { + builder.info(&format!( + "Rebuild sanitizers by removing the file `{}`", + stamp.path.display() + )); + } return runtimes; } builder.info(&format!("Building sanitizers for {}", self.target)); + t!(stamp.remove()); let _time = util::timeit(&builder); let mut cfg = cmake::Config::new(&compiler_rt_dir); @@ -623,8 +622,7 @@ impl Step for Sanitizers { cfg.build_target(&runtime.cmake_target); cfg.build(); } - - t!(fs::write(&done_stamp, b"")); + t!(stamp.write()); runtimes } @@ -689,3 +687,41 @@ fn supported_sanitizers( } result } + +struct HashStamp { + path: PathBuf, + hash: Option>, +} + +impl HashStamp { + fn new(path: PathBuf, hash: Option<&str>) -> Self { + HashStamp { path, hash: hash.map(|s| s.as_bytes().to_owned()) } + } + + fn is_done(&self) -> bool { + match fs::read(&self.path) { + Ok(h) => self.hash.as_deref().unwrap_or(b"") == h.as_slice(), + Err(e) if e.kind() == io::ErrorKind::NotFound => false, + Err(e) => { + panic!("failed to read stamp file `{}`: {}", self.path.display(), e); + } + } + } + + fn remove(&self) -> io::Result<()> { + match fs::remove_file(&self.path) { + Ok(()) => Ok(()), + Err(e) => { + if e.kind() == io::ErrorKind::NotFound { + Ok(()) + } else { + Err(e) + } + } + } + } + + fn write(&self) -> io::Result<()> { + fs::write(&self.path, self.hash.as_deref().unwrap_or(b"")) + } +} From edd3e175d6206946b862f1222c5cc3386b0be873 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 11:26:51 +0100 Subject: [PATCH 0795/1250] Remove redundant patterns when matching ( x @ _ to x) (clippy::redundant_pattern) --- src/librustc_resolve/imports.rs | 2 +- src/librustdoc/html/item_type.rs | 2 +- src/librustdoc/html/render.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 73bc038ea15..3b018005a88 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1432,7 +1432,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } msg } - ref s @ _ => bug!("unexpected import subclass {:?}", s), + ref s => bug!("unexpected import subclass {:?}", s), }; let mut err = this.session.struct_span_err(binding.span, &msg); diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index 4a0f4e5a4c9..b4486fdb7a7 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -62,7 +62,7 @@ impl<'a> From<&'a clean::Item> for ItemType { fn from(item: &'a clean::Item) -> ItemType { let inner = match item.inner { clean::StrippedItem(box ref item) => item, - ref inner @ _ => inner, + ref inner => inner, }; match *inner { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4dd2a6562a4..f357c962991 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2727,7 +2727,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>) -> String { let name = it.name.as_ref().unwrap(); let ty = match it.type_() { Typedef | AssocType => AssocType, - s @ _ => s, + s => s, }; let anchor = format!("#{}.{}", ty, name); From c2bbe3349f3c93d63d6408d4df1d190c7890f512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 11:33:05 +0100 Subject: [PATCH 0796/1250] Const items have by default a static lifetime, there's no need to annotate it. (clippy::redundant_static_lifetimes) --- src/librustc/mir/mod.rs | 2 +- src/librustc_mir/dataflow/generic/graphviz.rs | 4 ++-- src/librustc_parse/parser/diagnostics.rs | 2 +- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/html/item_type.rs | 8 ++++---- src/librustdoc/html/render.rs | 4 ++-- src/libstd/sys/unix/process/process_common.rs | 4 ++-- src/libtest/lib.rs | 2 +- 8 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 36818020569..51718592fd9 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1198,7 +1198,7 @@ impl<'tcx> TerminatorKind<'tcx> { t: BasicBlock, f: BasicBlock, ) -> TerminatorKind<'tcx> { - static BOOL_SWITCH_FALSE: &'static [u128] = &[0]; + static BOOL_SWITCH_FALSE: &[u128] = &[0]; TerminatorKind::SwitchInt { discr: cond, switch_ty: tcx.types.bool, diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index 157526d3c51..f8e1d3e9fe8 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -604,8 +604,8 @@ fn write_diff>( Ok(()) } -const BR_LEFT: &'static str = r#"
"#; -const BR_LEFT_SPACE: &'static str = r#"
"#; +const BR_LEFT: &str = r#"
"#; +const BR_LEFT_SPACE: &str = r#"
"#; /// Line break policy that breaks at 40 characters and starts the next line with a single space. const LIMIT_30_ALIGN_1: Option = Some(LineBreak { sequence: BR_LEFT_SPACE, limit: 30 }); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 0759c43d452..8b43b424f55 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -19,7 +19,7 @@ use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use log::{debug, trace}; use std::mem; -const TURBOFISH: &'static str = "use `::<...>` instead of `<...>` to specify type arguments"; +const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; /// Creates a placeholder argument. pub(super) fn dummy_arg(ident: Ident) -> Param { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7c845a9b66b..4c7765b2965 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -50,7 +50,7 @@ pub use self::types::Type::*; pub use self::types::Visibility::{Inherited, Public}; pub use self::types::*; -const FN_OUTPUT_NAME: &'static str = "Output"; +const FN_OUTPUT_NAME: &str = "Output"; pub trait Clean { fn clean(&self, cx: &DocContext<'_>) -> T; diff --git a/src/librustdoc/html/item_type.rs b/src/librustdoc/html/item_type.rs index b4486fdb7a7..0b2b0cdc18b 100644 --- a/src/librustdoc/html/item_type.rs +++ b/src/librustdoc/html/item_type.rs @@ -194,7 +194,7 @@ impl fmt::Display for ItemType { } } -pub const NAMESPACE_TYPE: &'static str = "t"; -pub const NAMESPACE_VALUE: &'static str = "v"; -pub const NAMESPACE_MACRO: &'static str = "m"; -pub const NAMESPACE_KEYWORD: &'static str = "k"; +pub const NAMESPACE_TYPE: &str = "t"; +pub const NAMESPACE_VALUE: &str = "v"; +pub const NAMESPACE_MACRO: &str = "m"; +pub const NAMESPACE_KEYWORD: &str = "k"; diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index f357c962991..07fe439ace2 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3150,7 +3150,7 @@ fn render_attribute(attr: &ast::MetaItem) -> Option { } } -const ATTRIBUTE_WHITELIST: &'static [Symbol] = &[ +const ATTRIBUTE_WHITELIST: &[Symbol] = &[ sym::export_name, sym::lang, sym::link_section, @@ -4610,7 +4610,7 @@ fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) { document(w, cx, it) } -crate const BASIC_KEYWORDS: &'static str = "rust, rustlang, rust-lang"; +crate const BASIC_KEYWORDS: &str = "rust, rustlang, rust-lang"; fn make_item_keywords(it: &clean::Item) -> String { format!("{}, {}", BASIC_KEYWORDS, it.name.as_ref().unwrap()) diff --git a/src/libstd/sys/unix/process/process_common.rs b/src/libstd/sys/unix/process/process_common.rs index 83f052c898b..859da691ad2 100644 --- a/src/libstd/sys/unix/process/process_common.rs +++ b/src/libstd/sys/unix/process/process_common.rs @@ -19,9 +19,9 @@ cfg_if::cfg_if! { if #[cfg(target_os = "fuchsia")] { // fuchsia doesn't have /dev/null } else if #[cfg(target_os = "redox")] { - const DEV_NULL: &'static str = "null:\0"; + const DEV_NULL: &str = "null:\0"; } else { - const DEV_NULL: &'static str = "/dev/null\0"; + const DEV_NULL: &str = "/dev/null\0"; } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index b42e41cbfe6..6bd3399cd17 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -96,7 +96,7 @@ use time::TestExecTime; // Process exit code to be used to indicate test failures. const ERROR_EXIT_CODE: i32 = 101; -const SECONDARY_TEST_INVOKER_VAR: &'static str = "__RUST_TEST_INVOKE"; +const SECONDARY_TEST_INVOKER_VAR: &str = "__RUST_TEST_INVOKE"; // The default console test runner. It accepts the command line // arguments and a vector of test_descs. From 3e70c8ec2ffb17ad55d57032a9d47fe7463f2d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 13:20:04 +0100 Subject: [PATCH 0797/1250] Use simple 'for i in x' loops instead of 'while let Some(x) = x.next()' loops on iterators. (clippy::while_let_on_iterator) --- src/librustc_mir/interpret/terminator.rs | 5 ++--- src/librustdoc/html/markdown.rs | 8 ++------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 08d4ae34afb..ea8378574a3 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -311,9 +311,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // taking into account the `spread_arg`. If we could write // this is a single iterator (that handles `spread_arg`), then // `pass_argument` would be the loop body. It takes care to - // not advance `caller_iter` for ZSTs. - let mut locals_iter = body.args_iter(); - while let Some(local) = locals_iter.next() { + // not advance `caller_iter` for ZSTs + for local in body.args_iter() { let dest = self.eval_place(&mir::Place::from(local))?; if Some(local) == body.spread_arg { // Must be a tuple diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ed007fe383c..805cd9d3e35 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -869,12 +869,8 @@ pub fn plain_summary_line(md: &str) -> String { } } let mut s = String::with_capacity(md.len() * 3 / 2); - let mut p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true }; - while let Some(t) = p.next() { - if !t.is_empty() { - s.push_str(&t); - } - } + let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true }; + p.into_iter().filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); s } From 3fc5c118dd328e786c1f389feac259f65409589c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 13:56:01 +0100 Subject: [PATCH 0798/1250] Use righthand '&' instead of lefthand "ref". (clippy::toplevel_ref_arg) --- src/librustc_builtin_macros/format.rs | 8 ++++---- src/librustc_builtin_macros/global_allocator.rs | 4 ++-- src/librustc_builtin_macros/test.rs | 4 ++-- src/librustc_builtin_macros/test_harness.rs | 2 +- src/librustc_infer/traits/select.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 4 ++-- src/librustc_mir_build/hair/pattern/_match.rs | 2 +- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 3724a83a949..81c97bcea05 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -476,7 +476,7 @@ impl<'a, 'b> Context<'a, 'b> { match ty { Placeholder(_) => { // record every (position, type) combination only once - let ref mut seen_ty = self.arg_unique_types[arg]; + let seen_ty = &mut self.arg_unique_types[arg]; let i = seen_ty.iter().position(|x| *x == ty).unwrap_or_else(|| { let i = seen_ty.len(); seen_ty.push(ty); @@ -526,7 +526,7 @@ impl<'a, 'b> Context<'a, 'b> { // Map the arguments for i in 0..args_len { - let ref arg_types = self.arg_types[i]; + let arg_types = &self.arg_types[i]; let arg_offsets = arg_types.iter().map(|offset| sofar + *offset).collect::>(); self.arg_index_map.push(arg_offsets); sofar += self.arg_unique_types[i].len(); @@ -597,7 +597,7 @@ impl<'a, 'b> Context<'a, 'b> { let arg_idx = match arg_index_consumed.get_mut(i) { None => 0, // error already emitted elsewhere Some(offset) => { - let ref idx_map = self.arg_index_map[i]; + let idx_map = &self.arg_index_map[i]; // unwrap_or branch: error already emitted elsewhere let arg_idx = *idx_map.get(*offset).unwrap_or(&0); *offset += 1; @@ -721,7 +721,7 @@ impl<'a, 'b> Context<'a, 'b> { let name = names_pos[i]; let span = self.ecx.with_def_site_ctxt(e.span); pats.push(self.ecx.pat_ident(span, name)); - for ref arg_ty in self.arg_unique_types[i].iter() { + for arg_ty in self.arg_unique_types[i].iter() { locals.push(Context::format_arg(self.ecx, self.macsp, e.span, arg_ty, name)); } heads.push(self.ecx.expr_addr_of(e.span, e)); diff --git a/src/librustc_builtin_macros/global_allocator.rs b/src/librustc_builtin_macros/global_allocator.rs index 8de7455a09a..5d16be3206a 100644 --- a/src/librustc_builtin_macros/global_allocator.rs +++ b/src/librustc_builtin_macros/global_allocator.rs @@ -57,12 +57,12 @@ impl AllocFnFactory<'_, '_> { fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt { let mut abi_args = Vec::new(); let mut i = 0; - let ref mut mk = || { + let mut mk = || { let name = self.cx.ident_of(&format!("arg{}", i), self.span); i += 1; name }; - let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, mk)).collect(); + let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, &mut mk)).collect(); let result = self.call_allocator(method.name, args); let (output_ty, output_expr) = self.ret_ty(&method.output, result); let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty)); diff --git a/src/librustc_builtin_macros/test.rs b/src/librustc_builtin_macros/test.rs index 7fe65f28532..bc194a3eec4 100644 --- a/src/librustc_builtin_macros/test.rs +++ b/src/librustc_builtin_macros/test.rs @@ -313,7 +313,7 @@ fn should_fail(i: &ast::Item) -> bool { fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic { match attr::find_by_name(&i.attrs, sym::should_panic) { Some(attr) => { - let ref sd = cx.parse_sess.span_diagnostic; + let sd = &cx.parse_sess.span_diagnostic; match attr.meta_item_list() { // Handle #[should_panic(expected = "foo")] @@ -378,7 +378,7 @@ fn test_type(cx: &ExtCtxt<'_>) -> TestType { fn has_test_signature(cx: &ExtCtxt<'_>, i: &ast::Item) -> bool { let has_should_panic_attr = attr::contains_name(&i.attrs, sym::should_panic); - let ref sd = cx.parse_sess.span_diagnostic; + let sd = &cx.parse_sess.span_diagnostic; if let ast::ItemKind::Fn(_, ref sig, ref generics, _) = i.kind { if let ast::Unsafe::Yes(span) = sig.header.unsafety { sd.struct_span_err(i.span, "unsafe functions cannot be used for tests") diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 51a21702805..e7e1ad8eda7 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -326,7 +326,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P { /// &[&test1, &test2] fn mk_tests_slice(cx: &TestCtxt<'_>, sp: Span) -> P { debug!("building test vector from {} tests", cx.test_cases.len()); - let ref ecx = cx.ext_cx; + let ecx = &cx.ext_cx; ecx.expr_vec_slice( sp, diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index 4c312c9fce2..fd94e3b6994 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -1341,7 +1341,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { stack: &TraitObligationStack<'o, 'tcx>, ) -> Result, SelectionError<'tcx>> { let TraitObligationStack { obligation, .. } = *stack; - let ref obligation = Obligation { + let obligation = &Obligation { param_env: obligation.param_env, cause: obligation.cause.clone(), recursion_depth: obligation.recursion_depth, diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 286740f99dd..9fe21964b98 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -920,7 +920,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut(); match candidate { Candidate::Ref(loc) => { - let ref mut statement = blocks[loc.block].statements[loc.statement_index]; + let statement = &mut blocks[loc.block].statements[loc.statement_index]; match statement.kind { StatementKind::Assign(box ( _, @@ -971,7 +971,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { } } Candidate::Repeat(loc) => { - let ref mut statement = blocks[loc.block].statements[loc.statement_index]; + let statement = &mut blocks[loc.block].statements[loc.statement_index]; match statement.kind { StatementKind::Assign(box (_, Rvalue::Repeat(ref mut operand, _))) => { let ty = operand.ty(local_decls, self.tcx); diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 4c7e6e1754a..5b054c04522 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -2331,7 +2331,7 @@ fn specialize_one_pattern<'p, 'tcx>( PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.iter().collect()), PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => { - let ref variant = adt_def.variants[variant_index]; + let variant = &adt_def.variants[variant_index]; let is_non_exhaustive = cx.is_foreign_non_exhaustive_variant(pat.ty, variant); Some(Variant(variant.def_id)) .filter(|variant_constructor| variant_constructor == constructor) From a1c3eb60433163e341feddb7c1a1cc7f65421764 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 14:08:27 +0100 Subject: [PATCH 0799/1250] Don't always eval arguments inside .expect(), use unwrap_or_else and closure. (clippy::expect_fun_call) --- src/librustdoc/docfs.rs | 12 ++++++------ src/libtest/lib.rs | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs index ecc394a2bc9..9c9a00295c3 100644 --- a/src/librustdoc/docfs.rs +++ b/src/librustdoc/docfs.rs @@ -90,14 +90,14 @@ impl DocFS { let sender = self.errors.sender.clone().unwrap(); rayon::spawn(move || match fs::write(&path, &contents) { Ok(_) => { - sender - .send(None) - .expect(&format!("failed to send error on \"{}\"", path.display())); + sender.send(None).unwrap_or_else(|_| { + panic!("failed to send error on \"{}\"", path.display()) + }); } Err(e) => { - sender - .send(Some(format!("\"{}\": {}", path.display(), e))) - .expect(&format!("failed to send non-error on \"{}\"", path.display())); + sender.send(Some(format!("\"{}\": {}", path.display(), e))).unwrap_or_else( + |_| panic!("failed to send non-error on \"{}\"", path.display()), + ); } }); Ok(()) diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 6bd3399cd17..55f9df9caaf 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -158,7 +158,7 @@ pub fn test_main_static_abort(tests: &[&TestDescAndFn]) { .filter(|test| test.desc.name.as_slice() == name) .map(make_owned_test) .next() - .expect(&format!("couldn't find a test with the provided name '{}'", name)); + .unwrap_or_else(|| panic!("couldn't find a test with the provided name '{}'", name)); let TestDescAndFn { desc, testfn } = test; let testfn = match testfn { StaticTestFn(f) => f, From 8ba92d9ce4ec834e925a514d280c2d822334ca00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 14:29:58 +0100 Subject: [PATCH 0800/1250] Use more efficient &&str to String conversion (clippy::inefficient_to_string) --- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_codegen_llvm/asm.rs | 2 +- src/librustc_incremental/persist/dirty_clean.rs | 3 ++- src/librustc_lint/context.rs | 4 ++-- src/librustc_typeck/collect.rs | 4 ++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 81c97bcea05..d6b8b8cafb7 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -284,7 +284,7 @@ impl<'a, 'b> Context<'a, 'b> { err.tool_only_span_suggestion( sp, &format!("use the `{}` trait", name), - fmt.to_string(), + (*fmt).to_string(), Applicability::MaybeIncorrect, ); } diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index 8066136c2fe..c8f0fe8c723 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -60,7 +60,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { .chain(ia.inputs.iter().map(|s| s.to_string())) .chain(ext_constraints) .chain(clobbers) - .chain(arch_clobbers.iter().map(|s| s.to_string())) + .chain(arch_clobbers.iter().map(|s| (*s).to_string())) .collect::>() .join(","); diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index f304292d922..e212dc81070 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -343,7 +343,8 @@ impl DirtyCleanVisitor<'tcx> { &format!("clean/dirty auto-assertions not yet defined for {:?}", node), ), }; - let labels = Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| l.to_string()))); + let labels = + Labels::from_iter(labels.iter().flat_map(|s| s.iter().map(|l| (*l).to_string()))); (name, labels) } diff --git a/src/librustc_lint/context.rs b/src/librustc_lint/context.rs index 29a6b8c693f..75d493e0f5e 100644 --- a/src/librustc_lint/context.rs +++ b/src/librustc_lint/context.rs @@ -369,7 +369,7 @@ impl LintStore { return if *silent { CheckLintNameResult::Ok(&lint_ids) } else { - CheckLintNameResult::Tool(Err((Some(&lint_ids), name.to_string()))) + CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string()))) }; } CheckLintNameResult::Ok(&lint_ids) @@ -404,7 +404,7 @@ impl LintStore { return if *silent { CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name))) } else { - CheckLintNameResult::Tool(Err((Some(&lint_ids), name.to_string()))) + CheckLintNameResult::Tool(Err((Some(&lint_ids), (*name).to_string()))) }; } CheckLintNameResult::Tool(Err((Some(&lint_ids), complete_name))) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2dad3d1d6d7..26462e61e5d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -151,7 +151,7 @@ crate fn placeholder_type_error( .unwrap_or(&"ParamName"); let mut sugg: Vec<_> = - placeholder_types.iter().map(|sp| (*sp, type_name.to_string())).collect(); + placeholder_types.iter().map(|sp| (*sp, (*type_name).to_string())).collect(); if generics.is_empty() { sugg.push((span, format!("<{}>", type_name))); } else if let Some(arg) = generics.iter().find(|arg| match arg.name { @@ -160,7 +160,7 @@ crate fn placeholder_type_error( }) { // Account for `_` already present in cases like `struct S<_>(_);` and suggest // `struct S(T);` instead of `struct S<_, T>(T);`. - sugg.push((arg.span, type_name.to_string())); + sugg.push((arg.span, (*type_name).to_string())); } else { sugg.push(( generics.iter().last().unwrap().span.shrink_to_hi(), From 84577c86bf5e1908acfc2cd097684f11e828518c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 14:54:19 +0100 Subject: [PATCH 0801/1250] Don't pass &mut where immutable reference (&) is sufficient (clippy::unnecessary_mut_passed) --- src/librustc_infer/traits/auto_trait.rs | 2 +- src/librustc_mir/dataflow/generic/visitor.rs | 8 ++++---- src/librustc_typeck/check/mod.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs index 1a4f899ac85..3166fe06576 100644 --- a/src/librustc_infer/traits/auto_trait.rs +++ b/src/librustc_infer/traits/auto_trait.rs @@ -150,7 +150,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { // SelectionContext to return it back to us. let (new_env, user_env) = match self.evaluate_predicates( - &mut infcx, + &infcx, trait_did, ty, orig_env, diff --git a/src/librustc_mir/dataflow/generic/visitor.rs b/src/librustc_mir/dataflow/generic/visitor.rs index 5bad8c61a0c..6e1513bcd1d 100644 --- a/src/librustc_mir/dataflow/generic/visitor.rs +++ b/src/librustc_mir/dataflow/generic/visitor.rs @@ -22,20 +22,20 @@ pub fn visit_results( let loc = Location { block, statement_index }; results.reconstruct_before_statement_effect(&mut state, stmt, loc); - vis.visit_statement(&mut state, stmt, loc); + vis.visit_statement(&state, stmt, loc); results.reconstruct_statement_effect(&mut state, stmt, loc); - vis.visit_statement_exit(&mut state, stmt, loc); + vis.visit_statement_exit(&state, stmt, loc); } let loc = body.terminator_loc(block); let term = block_data.terminator(); results.reconstruct_before_terminator_effect(&mut state, term, loc); - vis.visit_terminator(&mut state, term, loc); + vis.visit_terminator(&state, term, loc); results.reconstruct_terminator_effect(&mut state, term, loc); - vis.visit_terminator_exit(&mut state, term, loc); + vis.visit_terminator_exit(&state, term, loc); } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index b7353c6af26..d8b23998e72 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -737,8 +737,8 @@ impl ItemLikeVisitor<'tcx> for CheckItemTypesVisitor<'tcx> { } pub fn check_wf_new(tcx: TyCtxt<'_>) { - let mut visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); - tcx.hir().krate().par_visit_all_item_likes(&mut visit); + let visit = wfcheck::CheckTypeWellFormedVisitor::new(tcx); + tcx.hir().krate().par_visit_all_item_likes(&visit); } fn check_mod_item_types(tcx: TyCtxt<'_>, module_def_id: DefId) { From f4f91f0b2f98ddf9ea36c4bc200ebda2cd898230 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 27 Jan 2020 06:10:10 +0000 Subject: [PATCH 0802/1250] Remove eh_unwind_resume lang item --- Cargo.lock | 1 - .../src/language-features/lang-items.md | 22 ++------- src/libpanic_abort/Cargo.toml | 1 - src/libpanic_abort/lib.rs | 2 +- src/libpanic_unwind/gcc.rs | 10 +--- src/librustc/middle/lang_items.rs | 3 +- src/librustc_codegen_llvm/context.rs | 47 +------------------ src/librustc_codegen_ssa/mir/block.rs | 13 ++--- src/librustc_codegen_ssa/traits/misc.rs | 1 - src/librustc_hir/lang_items.rs | 1 - src/librustc_hir/weak_lang_items.rs | 1 - src/librustc_passes/weak_lang_items.rs | 3 -- src/librustc_span/symbol.rs | 2 - src/librustc_target/spec/mod.rs | 8 ---- src/librustc_target/spec/windows_uwp_base.rs | 1 - .../auxiliary/panic-runtime-lang-items.rs | 2 - .../const-eval/const_panic_libcore_main.rs | 2 - .../macros/macro-comma-behavior.core.stderr | 14 +++--- src/test/ui/macros/macro-comma-behavior.rs | 1 - .../ui/macros/macro-comma-behavior.std.stderr | 20 ++++---- src/test/ui/no_owned_box_lang_item.rs | 1 - .../auxiliary/panic-runtime-lang-items.rs | 2 - src/test/ui/range/issue-54505-no-std.rs | 4 -- src/test/ui/range/issue-54505-no-std.stderr | 12 ++--- 24 files changed, 34 insertions(+), 140 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 08c0462a1dc..f639095fae7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2308,7 +2308,6 @@ dependencies = [ name = "panic_abort" version = "0.0.0" dependencies = [ - "cfg-if", "compiler_builtins", "core", "libc", diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index b6e61e7050c..25082432192 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -52,7 +52,6 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize { #[lang = "eh_personality"] extern fn rust_eh_personality() {} #[lang = "panic_impl"] extern fn rust_begin_panic(info: &PanicInfo) -> ! { unsafe { intrinsics::abort() } } -#[lang = "eh_unwind_resume"] extern fn rust_eh_unwind_resume() {} #[no_mangle] pub extern fn rust_eh_register_frames () {} #[no_mangle] pub extern fn rust_eh_unregister_frames () {} ``` @@ -67,7 +66,7 @@ Other features provided by lang items include: marked with lang items; those specific four are `eq`, `ord`, `deref`, and `add` respectively. - stack unwinding and general failure; the `eh_personality`, - `eh_unwind_resume`, `fail` and `fail_bounds_checks` lang items. + `panic` and `panic_bounds_checks` lang items. - the traits in `std::marker` used to indicate types of various kinds; lang items `send`, `sync` and `copy`. - the marker types and variance indicators found in @@ -130,12 +129,6 @@ fn start(_argc: isize, _argv: *const *const u8) -> isize { pub extern fn rust_eh_personality() { } -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - #[lang = "panic_impl"] #[no_mangle] pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { @@ -173,12 +166,6 @@ pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 { pub extern fn rust_eh_personality() { } -// This function may be needed based on the compilation target. -#[lang = "eh_unwind_resume"] -#[no_mangle] -pub extern fn rust_eh_unwind_resume() { -} - #[lang = "panic_impl"] #[no_mangle] pub extern fn rust_begin_panic(info: &PanicInfo) -> ! { @@ -211,10 +198,8 @@ compiler. When a panic happens, this controls the message that's displayed on the screen. While the language item's name is `panic_impl`, the symbol name is `rust_begin_panic`. -A third function, `rust_eh_unwind_resume`, is also needed if the `custom_unwind_resume` -flag is set in the options of the compilation target. It allows customizing the -process of resuming unwind at the end of the landing pads. The language item's name -is `eh_unwind_resume`. +Finally, a `eh_catch_typeinfo` static is needed for certain targets which +implement Rust panics on top of C++ exceptions. ## List of all language items @@ -247,7 +232,6 @@ the source code. - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC) - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU) - `eh_personality`: `libpanic_unwind/seh.rs` (SEH) - - `eh_unwind_resume`: `libpanic_unwind/gcc.rs` (GCC) - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC) - `panic`: `libcore/panicking.rs` - `panic_bounds_check`: `libcore/panicking.rs` diff --git a/src/libpanic_abort/Cargo.toml b/src/libpanic_abort/Cargo.toml index 8ebd95047ac..2bee0b716c7 100644 --- a/src/libpanic_abort/Cargo.toml +++ b/src/libpanic_abort/Cargo.toml @@ -14,4 +14,3 @@ doc = false core = { path = "../libcore" } libc = { version = "0.2", default-features = false } compiler_builtins = "0.1.0" -cfg-if = "0.1.8" diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 6ea818ecef8..d894b50e077 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -115,7 +115,7 @@ pub mod personalities { // Note that we don't execute landing pads, so this is never called, so it's // body is empty. #[no_mangle] - #[cfg(all(target_os = "windows", target_env = "gnu"))] + #[cfg(all(bootstrap, target_os = "windows", target_env = "gnu"))] pub extern "C" fn rust_eh_unwind_resume() {} // These two are called by our startup objects on i686-pc-windows-gnu, but diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 20ae5edaa2a..4fcf048a2cd 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -35,14 +35,6 @@ //! //! Once stack has been unwound down to the handler frame level, unwinding stops //! and the last personality routine transfers control to the catch block. -//! -//! ## `eh_personality` and `eh_unwind_resume` -//! -//! These language items are used by the compiler when generating unwind info. -//! The first one is the personality routine described above. The second one -//! allows compilation target to customize the process of resuming unwind at the -//! end of the landing pads. `eh_unwind_resume` is used only if -//! `custom_unwind_resume` flag in the target options is set. #![allow(private_no_mangle_fns)] @@ -324,8 +316,8 @@ unsafe fn find_eh_action( eh::find_eh_action(lsda, &eh_context, foreign_exception) } -// See docs in the `unwind` module. #[cfg(all( + bootstrap, target_os = "windows", any(target_arch = "x86", target_arch = "x86_64"), target_env = "gnu" diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index c8e284be6fc..36560371587 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -57,8 +57,7 @@ pub fn whitelisted(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { // symbols. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. if tcx.sess.panic_strategy() != PanicStrategy::Unwind { - return lang_item == LangItem::EhPersonalityLangItem - || lang_item == LangItem::EhUnwindResumeLangItem; + return lang_item == LangItem::EhPersonalityLangItem; } false diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 46f461b98c8..04e161d6e08 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,4 +1,3 @@ -use crate::abi::FnAbi; use crate::attributes; use crate::debuginfo; use crate::llvm; @@ -15,7 +14,7 @@ use rustc::mir::mono::CodegenUnit; use rustc::session::config::{self, CFGuard, DebugInfo}; use rustc::session::Session; use rustc::ty::layout::{ - FnAbiExt, HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, + HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, }; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_codegen_ssa::base::wants_msvc_seh; @@ -23,15 +22,12 @@ use rustc_data_structures::base_n; use rustc_data_structures::const_cstr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_hir::Unsafety; use rustc_target::spec::{HasTargetSpec, Target}; -use crate::abi::Abi; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::Symbol; use std::cell::{Cell, RefCell}; use std::ffi::CStr; -use std::iter; use std::str; use std::sync::Arc; @@ -87,7 +83,6 @@ pub struct CodegenCx<'ll, 'tcx> { pub dbg_cx: Option>, eh_personality: Cell>, - eh_unwind_resume: Cell>, pub rust_try_fn: Cell>, intrinsics: RefCell>, @@ -328,7 +323,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { isize_ty, dbg_cx, eh_personality: Cell::new(None), - eh_unwind_resume: Cell::new(None), rust_try_fn: Cell::new(None), intrinsics: Default::default(), local_gen_sym_counter: Cell::new(0), @@ -406,45 +400,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { llfn } - // Returns a Value of the "eh_unwind_resume" lang item if one is defined, - // otherwise declares it as an external function. - fn eh_unwind_resume(&self) -> &'ll Value { - let unwresume = &self.eh_unwind_resume; - if let Some(llfn) = unwresume.get() { - return llfn; - } - - let tcx = self.tcx; - assert!(self.sess().target.target.options.custom_unwind_resume); - if let Some(def_id) = tcx.lang_items().eh_unwind_resume() { - let llfn = self.get_fn_addr( - ty::Instance::resolve( - tcx, - ty::ParamEnv::reveal_all(), - def_id, - tcx.intern_substs(&[]), - ) - .unwrap(), - ); - unwresume.set(Some(llfn)); - return llfn; - } - - let sig = ty::Binder::bind(tcx.mk_fn_sig( - iter::once(tcx.mk_mut_ptr(tcx.types.u8)), - tcx.types.never, - false, - Unsafety::Unsafe, - Abi::C, - )); - - let fn_abi = FnAbi::of_fn_ptr(self, sig, &[]); - let llfn = self.declare_fn("rust_eh_unwind_resume", &fn_abi); - attributes::apply_target_cpu_attr(self, llfn); - unwresume.set(Some(llfn)); - llfn - } - fn sess(&self) -> &Session { &self.tcx.sess } diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index a1b54607b80..2cf0cceb910 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -178,15 +178,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let lp1 = bx.load_operand(lp1).immediate(); slot.storage_dead(&mut bx); - if !bx.sess().target.target.options.custom_unwind_resume { - let mut lp = bx.const_undef(self.landing_pad_type()); - lp = bx.insert_value(lp, lp0, 0); - lp = bx.insert_value(lp, lp1, 1); - bx.resume(lp); - } else { - bx.call(bx.eh_unwind_resume(), &[lp0], helper.funclet(self)); - bx.unreachable(); - } + let mut lp = bx.const_undef(self.landing_pad_type()); + lp = bx.insert_value(lp, lp0, 0); + lp = bx.insert_value(lp, lp1, 1); + bx.resume(lp); } } diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index 691b94c2f9d..d7587163ba0 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -14,7 +14,6 @@ pub trait MiscMethods<'tcx>: BackendTypes { fn get_fn(&self, instance: Instance<'tcx>) -> Self::Function; fn get_fn_addr(&self, instance: Instance<'tcx>) -> Self::Value; fn eh_personality(&self) -> Self::Value; - fn eh_unwind_resume(&self) -> Self::Value; fn sess(&self) -> &Session; fn codegen_unit(&self) -> &Arc>; fn used_statics(&self) -> &RefCell>; diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index fc91b68e3ea..89457009a8b 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -240,7 +240,6 @@ language_item_table! { StartFnLangItem, "start", start_fn, Target::Fn; EhPersonalityLangItem, "eh_personality", eh_personality, Target::Fn; - EhUnwindResumeLangItem, "eh_unwind_resume", eh_unwind_resume, Target::Fn; EhCatchTypeinfoLangItem, "eh_catch_typeinfo", eh_catch_typeinfo, Target::Static; OwnedBoxLangItem, "owned_box", owned_box, Target::Struct; diff --git a/src/librustc_hir/weak_lang_items.rs b/src/librustc_hir/weak_lang_items.rs index 405a31d5a69..c0560eb8d45 100644 --- a/src/librustc_hir/weak_lang_items.rs +++ b/src/librustc_hir/weak_lang_items.rs @@ -43,6 +43,5 @@ impl LanguageItems { weak_lang_items! { panic_impl, PanicImplLangItem, rust_begin_unwind; eh_personality, EhPersonalityLangItem, rust_eh_personality; - eh_unwind_resume, EhUnwindResumeLangItem, rust_eh_unwind_resume; oom, OomLangItem, rust_oom; } diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 1511742446b..7bf49d56531 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -28,9 +28,6 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>, items: &mut lang_items::LanguageItem if items.eh_personality().is_none() { items.missing.push(lang_items::EhPersonalityLangItem); } - if tcx.sess.target.target.options.custom_unwind_resume & items.eh_unwind_resume().is_none() { - items.missing.push(lang_items::EhUnwindResumeLangItem); - } { let mut cx = Context { tcx, items }; diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index d6232f32f4c..6231489dfb2 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -287,7 +287,6 @@ symbols! { dylib, dyn_trait, eh_personality, - eh_unwind_resume, enable, Encodable, env, @@ -663,7 +662,6 @@ symbols! { rustc_variance, rustfmt, rust_eh_personality, - rust_eh_unwind_resume, rust_oom, rvalue_static_promotion, sanitize, diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 67f45d3d230..542bcd27507 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -692,11 +692,6 @@ pub struct TargetOptions { pub archive_format: String, /// Is asm!() allowed? Defaults to true. pub allow_asm: bool, - /// Whether the target uses a custom unwind resumption routine. - /// By default LLVM lowers `resume` instructions into calls to `_Unwind_Resume` - /// defined in libgcc. If this option is enabled, the target must provide - /// `eh_unwind_resume` lang item. - pub custom_unwind_resume: bool, /// Whether the runtime startup code requires the `main` function be passed /// `argc` and `argv` values. pub main_needs_argc_argv: bool, @@ -866,7 +861,6 @@ impl Default for TargetOptions { link_env: Vec::new(), link_env_remove: Vec::new(), archive_format: "gnu".to_string(), - custom_unwind_resume: false, main_needs_argc_argv: true, allow_asm: true, has_elf_tls: false, @@ -1182,7 +1176,6 @@ impl Target { key!(relro_level, RelroLevel)?; key!(archive_format); key!(allow_asm, bool); - key!(custom_unwind_resume, bool); key!(main_needs_argc_argv, bool); key!(has_elf_tls, bool); key!(obj_is_bitcode, bool); @@ -1410,7 +1403,6 @@ impl ToJson for Target { target_option_val!(relro_level); target_option_val!(archive_format); target_option_val!(allow_asm); - target_option_val!(custom_unwind_resume); target_option_val!(main_needs_argc_argv); target_option_val!(has_elf_tls); target_option_val!(obj_is_bitcode); diff --git a/src/librustc_target/spec/windows_uwp_base.rs b/src/librustc_target/spec/windows_uwp_base.rs index b19c4dd7eb1..3f7eb442bbc 100644 --- a/src/librustc_target/spec/windows_uwp_base.rs +++ b/src/librustc_target/spec/windows_uwp_base.rs @@ -54,7 +54,6 @@ pub fn opts() -> TargetOptions { pre_link_objects_dll: vec!["rsbegin.o".to_string()], late_link_args, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs index abe34a39caf..3e5cdad7ab9 100644 --- a/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/compile-fail/auxiliary/panic-runtime-lang-items.rs @@ -11,5 +11,3 @@ use core::panic::PanicInfo; fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} diff --git a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs index 9afcdf77610..6b86feb5921 100644 --- a/src/test/ui/consts/const-eval/const_panic_libcore_main.rs +++ b/src/test/ui/consts/const-eval/const_panic_libcore_main.rs @@ -17,8 +17,6 @@ const X: () = unimplemented!(); #[lang = "eh_personality"] fn eh() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} #[panic_handler] fn panic(_info: &PanicInfo) -> ! { diff --git a/src/test/ui/macros/macro-comma-behavior.core.stderr b/src/test/ui/macros/macro-comma-behavior.core.stderr index dd0cac659fd..83a88ab3bd9 100644 --- a/src/test/ui/macros/macro-comma-behavior.core.stderr +++ b/src/test/ui/macros/macro-comma-behavior.core.stderr @@ -1,41 +1,41 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:53:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:71:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:80:24 | LL | write!(f, "{}",)?; | ^^ diff --git a/src/test/ui/macros/macro-comma-behavior.rs b/src/test/ui/macros/macro-comma-behavior.rs index 006319aa9f5..04714c65b5c 100644 --- a/src/test/ui/macros/macro-comma-behavior.rs +++ b/src/test/ui/macros/macro-comma-behavior.rs @@ -9,7 +9,6 @@ #[cfg(std)] use std::fmt; #[cfg(core)] use core::fmt; #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {} -#[cfg(core)] #[lang = "eh_unwind_resume"] fn eh_unwind_resume() {} #[cfg(core)] #[lang = "panic_impl"] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} } // (see documentation of the similarly-named test in run-pass) diff --git a/src/test/ui/macros/macro-comma-behavior.std.stderr b/src/test/ui/macros/macro-comma-behavior.std.stderr index 4372d89fbf5..26445f2c5c5 100644 --- a/src/test/ui/macros/macro-comma-behavior.std.stderr +++ b/src/test/ui/macros/macro-comma-behavior.std.stderr @@ -1,59 +1,59 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:38:18 + --> $DIR/macro-comma-behavior.rs:37:18 | LL | eprint!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:50:18 + --> $DIR/macro-comma-behavior.rs:49:18 | LL | format!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:54:19 + --> $DIR/macro-comma-behavior.rs:53:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:61:17 + --> $DIR/macro-comma-behavior.rs:60:17 | LL | print!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:72:21 + --> $DIR/macro-comma-behavior.rs:71:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:24 + --> $DIR/macro-comma-behavior.rs:80:24 | LL | write!(f, "{}",)?; | ^^ diff --git a/src/test/ui/no_owned_box_lang_item.rs b/src/test/ui/no_owned_box_lang_item.rs index b76699c19ac..58e45ff73a5 100644 --- a/src/test/ui/no_owned_box_lang_item.rs +++ b/src/test/ui/no_owned_box_lang_item.rs @@ -12,5 +12,4 @@ fn main() { } #[lang = "eh_personality"] extern fn eh_personality() {} -#[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {} #[lang = "panic_impl"] fn panic_impl(panic: &PanicInfo) -> ! { loop {} } diff --git a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs index abe34a39caf..3e5cdad7ab9 100644 --- a/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs +++ b/src/test/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -11,5 +11,3 @@ use core::panic::PanicInfo; fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_unwind_resume"] -fn eh_unwind_resume() {} diff --git a/src/test/ui/range/issue-54505-no-std.rs b/src/test/ui/range/issue-54505-no-std.rs index 22cf15fb2e4..c6a3cc346fc 100644 --- a/src/test/ui/range/issue-54505-no-std.rs +++ b/src/test/ui/range/issue-54505-no-std.rs @@ -15,10 +15,6 @@ use core::ops::RangeBounds; #[lang = "eh_personality"] extern fn eh_personality() {} -#[cfg(target_os = "windows")] -#[lang = "eh_unwind_resume"] -extern fn eh_unwind_resume() {} - // take a reference to any built-in range fn take_range(_r: &impl RangeBounds) {} diff --git a/src/test/ui/range/issue-54505-no-std.stderr b/src/test/ui/range/issue-54505-no-std.stderr index aead80fa500..90934061132 100644 --- a/src/test/ui/range/issue-54505-no-std.stderr +++ b/src/test/ui/range/issue-54505-no-std.stderr @@ -1,7 +1,7 @@ error: `#[panic_handler]` function required, but not found error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:28:16 + --> $DIR/issue-54505-no-std.rs:24:16 | LL | take_range(0..1); | ^^^^ @@ -13,7 +13,7 @@ LL | take_range(0..1); found struct `core::ops::Range<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:33:16 + --> $DIR/issue-54505-no-std.rs:29:16 | LL | take_range(1..); | ^^^ @@ -25,7 +25,7 @@ LL | take_range(1..); found struct `core::ops::RangeFrom<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:38:16 + --> $DIR/issue-54505-no-std.rs:34:16 | LL | take_range(..); | ^^ @@ -37,7 +37,7 @@ LL | take_range(..); found struct `core::ops::RangeFull` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:43:16 + --> $DIR/issue-54505-no-std.rs:39:16 | LL | take_range(0..=1); | ^^^^^ @@ -49,7 +49,7 @@ LL | take_range(0..=1); found struct `core::ops::RangeInclusive<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:48:16 + --> $DIR/issue-54505-no-std.rs:44:16 | LL | take_range(..5); | ^^^ @@ -61,7 +61,7 @@ LL | take_range(..5); found struct `core::ops::RangeTo<{integer}>` error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:53:16 + --> $DIR/issue-54505-no-std.rs:49:16 | LL | take_range(..=42); | ^^^^^ From 5953c100d1e9eea5ca70f185e905ea0773a34eb5 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 2 Mar 2020 11:57:30 +0000 Subject: [PATCH 0803/1250] Use #[rustc_std_internal_symbol] instead of #[no_mangle] --- src/libpanic_abort/lib.rs | 10 +++++----- src/libpanic_unwind/emcc.rs | 1 - src/libpanic_unwind/gcc.rs | 7 ++----- src/libpanic_unwind/lib.rs | 4 ++-- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index d894b50e077..1af93ff4ada 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -89,7 +89,7 @@ pub unsafe extern "C" fn __rust_start_panic(_payload: usize) -> u32 { // binaries, but it should never be called as we don't link in an unwinding // runtime at all. pub mod personalities { - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(not(any( all(target_arch = "wasm32", not(target_os = "emscripten"),), all(target_os = "windows", target_env = "gnu", target_arch = "x86_64",), @@ -98,7 +98,7 @@ pub mod personalities { // On x86_64-pc-windows-gnu we use our own personality function that needs // to return `ExceptionContinueSearch` as we're passing on all our frames. - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86_64"))] pub extern "C" fn rust_eh_personality( _record: usize, @@ -114,16 +114,16 @@ pub mod personalities { // // Note that we don't execute landing pads, so this is never called, so it's // body is empty. - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(bootstrap, target_os = "windows", target_env = "gnu"))] pub extern "C" fn rust_eh_unwind_resume() {} // These two are called by our startup objects on i686-pc-windows-gnu, but // they don't need to do anything so the bodies are nops. - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] pub extern "C" fn rust_eh_register_frames() {} - #[no_mangle] + #[rustc_std_internal_symbol] #[cfg(all(target_os = "windows", target_env = "gnu", target_arch = "x86"))] pub extern "C" fn rust_eh_unregister_frames() {} } diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index e541ec30025..117246aa6c9 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -94,7 +94,6 @@ extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> DestructorRet { } #[lang = "eh_personality"] -#[no_mangle] unsafe extern "C" fn rust_eh_personality( version: c_int, actions: uw::_Unwind_Action, diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 4fcf048a2cd..9c032b30341 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -130,7 +130,6 @@ cfg_if::cfg_if! { // // iOS uses the default routine instead since it uses SjLj unwinding. #[lang = "eh_personality"] - #[no_mangle] unsafe extern "C" fn rust_eh_personality(state: uw::_Unwind_State, exception_object: *mut uw::_Unwind_Exception, context: *mut uw::_Unwind_Context) @@ -264,7 +263,6 @@ cfg_if::cfg_if! { // On x86_64 MinGW targets, the unwinding mechanism is SEH however the unwind // handler data (aka LSDA) uses GCC-compatible encoding. #[lang = "eh_personality"] - #[no_mangle] #[allow(nonstandard_style)] unsafe extern "C" fn rust_eh_personality(exceptionRecord: *mut uw::EXCEPTION_RECORD, establisherFrame: uw::LPVOID, @@ -280,7 +278,6 @@ cfg_if::cfg_if! { } else { // The personality routine for most of our targets. #[lang = "eh_personality"] - #[no_mangle] unsafe extern "C" fn rust_eh_personality(version: c_int, actions: uw::_Unwind_Action, exception_class: uw::_Unwind_Exception_Class, @@ -351,12 +348,12 @@ pub mod eh_frame_registry { fn __deregister_frame_info(eh_frame_begin: *const u8, object: *mut u8); } - #[no_mangle] + #[rustc_std_internal_symbol] pub unsafe extern "C" fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8) { __register_frame_info(eh_frame_begin, object); } - #[no_mangle] + #[rustc_std_internal_symbol] pub unsafe extern "C" fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8) { __deregister_frame_info(eh_frame_begin, object); } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 87d24841d04..20331e8808c 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -72,7 +72,7 @@ extern "C" { mod dwarf; -#[no_mangle] +#[rustc_std_internal_symbol] pub unsafe extern "C" fn __rust_panic_cleanup( payload: TryPayload, ) -> *mut (dyn Any + Send + 'static) { @@ -81,7 +81,7 @@ pub unsafe extern "C" fn __rust_panic_cleanup( // Entry point for raising an exception, just delegates to the platform-specific // implementation. -#[no_mangle] +#[rustc_std_internal_symbol] #[unwind(allowed)] pub unsafe extern "C" fn __rust_start_panic(payload: usize) -> u32 { let payload = payload as *mut &mut dyn BoxMeUp; From 1c950e5c6f85422283bb23bb4bad07ae6c3d2fe1 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 2 Mar 2020 13:59:20 +0000 Subject: [PATCH 0804/1250] Simplify the try intrinsic by using a callback in the catch block --- src/libcore/intrinsics.rs | 14 ++-- src/libpanic_abort/lib.rs | 5 +- src/libpanic_unwind/emcc.rs | 2 +- src/libpanic_unwind/lib.rs | 8 +- src/libpanic_unwind/payload.rs | 21 ------ src/libpanic_unwind/seh.rs | 41 +++++----- src/librustc_codegen_llvm/intrinsic.rs | 100 ++++++++++++------------- src/librustc_typeck/check/intrinsic.rs | 15 +++- src/libstd/panicking.rs | 65 ++++++++++++---- src/test/codegen/try-panic-abort.rs | 5 +- 10 files changed, 150 insertions(+), 126 deletions(-) delete mode 100644 src/libpanic_unwind/payload.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index fca2c3d31d9..20fb4149b93 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1390,14 +1390,16 @@ extern "rust-intrinsic" { /// cast to a `u64`; if `T` has no discriminant, returns 0. pub fn discriminant_value(v: &T) -> u64; - /// Rust's "try catch" construct which invokes the function pointer `f` with - /// the data pointer `data`. + /// Rust's "try catch" construct which invokes the function pointer `try_fn` + /// with the data pointer `data`. /// - /// The third pointer is a target-specific data pointer which is filled in - /// with the specifics of the exception that occurred. For examples on Unix - /// platforms this is a `*mut *mut T` which is filled in by the compiler and - /// on MSVC it's `*mut [usize; 2]`. For more information see the compiler's + /// The third argument is a function called if a panic occurs. This function + /// takes the data pointer and a pointer to the target-specific exception + /// object that was caught. For more information see the compiler's /// source as well as std's catch implementation. + #[cfg(not(bootstrap))] + pub fn r#try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32; + #[cfg(bootstrap)] pub fn r#try(f: fn(*mut u8), data: *mut u8, local_ptr: *mut u8) -> i32; /// Emits a `!nontemporal` store according to LLVM (see their docs). diff --git a/src/libpanic_abort/lib.rs b/src/libpanic_abort/lib.rs index 1af93ff4ada..f44a875c9d0 100644 --- a/src/libpanic_abort/lib.rs +++ b/src/libpanic_abort/lib.rs @@ -20,11 +20,8 @@ use core::any::Any; -// We need the definition of TryPayload for __rust_panic_cleanup. -include!("../libpanic_unwind/payload.rs"); - #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_panic_cleanup(_: TryPayload) -> *mut (dyn Any + Send + 'static) { +pub unsafe extern "C" fn __rust_panic_cleanup(_: *mut u8) -> *mut (dyn Any + Send + 'static) { unreachable!() } diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index 117246aa6c9..c7144fe16cd 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -52,7 +52,7 @@ struct Exception { // This needs to be an Option because the object's lifetime follows C++ // semantics: when catch_unwind moves the Box out of the exception it must // still leave the exception object in a valid state because its destructor - // is still going to be called by __cxa_end_catch.. + // is still going to be called by __cxa_end_catch. data: Option>, } diff --git a/src/libpanic_unwind/lib.rs b/src/libpanic_unwind/lib.rs index 20331e8808c..d6c33666938 100644 --- a/src/libpanic_unwind/lib.rs +++ b/src/libpanic_unwind/lib.rs @@ -35,8 +35,6 @@ use alloc::boxed::Box; use core::any::Any; use core::panic::BoxMeUp; -// If adding to this list, you should also look at the list of TryPayload types -// defined in payload.rs and likely add to there as well. cfg_if::cfg_if! { if #[cfg(target_os = "emscripten")] { #[path = "emcc.rs"] @@ -62,8 +60,6 @@ cfg_if::cfg_if! { } } -include!("payload.rs"); - extern "C" { /// Handler in libstd called when a panic object is dropped outside of /// `catch_unwind`. @@ -73,9 +69,7 @@ extern "C" { mod dwarf; #[rustc_std_internal_symbol] -pub unsafe extern "C" fn __rust_panic_cleanup( - payload: TryPayload, -) -> *mut (dyn Any + Send + 'static) { +pub unsafe extern "C" fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static) { Box::into_raw(imp::cleanup(payload)) } diff --git a/src/libpanic_unwind/payload.rs b/src/libpanic_unwind/payload.rs deleted file mode 100644 index 1234db7da0f..00000000000 --- a/src/libpanic_unwind/payload.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Type definition for the payload argument of the try intrinsic. -// -// This must be kept in sync with the implementations of the try intrinsic. -// -// This file is included by both panic runtimes and libstd. It is part of the -// panic runtime ABI. -cfg_if::cfg_if! { - if #[cfg(target_os = "emscripten")] { - type TryPayload = *mut u8; - } else if #[cfg(target_arch = "wasm32")] { - type TryPayload = *mut u8; - } else if #[cfg(target_os = "hermit")] { - type TryPayload = *mut u8; - } else if #[cfg(all(target_env = "msvc", target_arch = "aarch64"))] { - type TryPayload = *mut u8; - } else if #[cfg(target_env = "msvc")] { - type TryPayload = [u64; 2]; - } else { - type TryPayload = *mut u8; - } -} diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index f599f9815a6..c1656023b60 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -49,10 +49,17 @@ use alloc::boxed::Box; use core::any::Any; -use core::mem; -use core::raw; +use core::mem::{self, ManuallyDrop}; use libc::{c_int, c_uint, c_void}; +struct Exception { + // This needs to be an Option because we catch the exception by reference + // and its destructor is executed by the C++ runtime. When we take the Box + // out of the exception, we need to leave the exception in a valid state + // for its destructor to run without double-dropping the Box. + data: Option>, +} + // First up, a whole bunch of type definitions. There's a few platform-specific // oddities here, and a lot that's just blatantly copied from LLVM. The purpose // of all this is to implement the `panic` function below through a call to @@ -186,7 +193,7 @@ static mut CATCHABLE_TYPE: _CatchableType = _CatchableType { properties: 0, pType: ptr!(0), thisDisplacement: _PMD { mdisp: 0, pdisp: -1, vdisp: 0 }, - sizeOrOffset: mem::size_of::<[u64; 2]>() as c_int, + sizeOrOffset: mem::size_of::() as c_int, copyFunction: ptr!(0), }; @@ -229,16 +236,16 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { // because Box isn't clonable. macro_rules! define_cleanup { ($abi:tt) => { - unsafe extern $abi fn exception_cleanup(e: *mut [u64; 2]) { - if (*e)[0] != 0 { - cleanup(*e); + unsafe extern $abi fn exception_cleanup(e: *mut Exception) { + if let Some(b) = e.read().data { + drop(b); super::__rust_drop_panic(); } } #[unwind(allowed)] - unsafe extern $abi fn exception_copy(_dest: *mut [u64; 2], - _src: *mut [u64; 2]) - -> *mut [u64; 2] { + unsafe extern $abi fn exception_copy(_dest: *mut Exception, + _src: *mut Exception) + -> *mut Exception { panic!("Rust panics cannot be copied"); } } @@ -258,12 +265,11 @@ pub unsafe fn panic(data: Box) -> u32 { // need to otherwise transfer `data` to the heap. We just pass a stack // pointer to this function. // - // The first argument is the payload being thrown (our two pointers), and - // the second argument is the type information object describing the - // exception (constructed above). - let ptrs = mem::transmute::<_, raw::TraitObject>(data); - let mut ptrs = [ptrs.data as u64, ptrs.vtable as u64]; - let throw_ptr = ptrs.as_mut_ptr() as *mut _; + // The ManuallyDrop is needed here since we don't want Exception to be + // dropped when unwinding. Instead it will be dropped by exception_cleanup + // which is invoked by the C++ runtime. + let mut exception = ManuallyDrop::new(Exception { data: Some(data) }); + let throw_ptr = &mut exception as *mut _ as *mut _; // This... may seems surprising, and justifiably so. On 32-bit MSVC the // pointers between these structure are just that, pointers. On 64-bit MSVC, @@ -311,8 +317,9 @@ pub unsafe fn panic(data: Box) -> u32 { _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _); } -pub unsafe fn cleanup(payload: [u64; 2]) -> Box { - mem::transmute(raw::TraitObject { data: payload[0] as *mut _, vtable: payload[1] as *mut _ }) +pub unsafe fn cleanup(payload: *mut u8) -> Box { + let exception = &mut *(payload as *mut Exception); + exception.data.take().unwrap() } // This is required by the compiler to exist (e.g., it's a lang item), but diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index baaa2a5cf45..d34540638f1 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -851,21 +851,21 @@ fn memset_intrinsic( fn try_intrinsic( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { if bx.sess().no_landing_pads() { - bx.call(func, &[data], None); + bx.call(try_func, &[data], None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. let ret_align = bx.tcx().data_layout.i32_align.abi; bx.store(bx.const_i32(0), dest, ret_align); } else if wants_msvc_seh(bx.sess()) { - codegen_msvc_try(bx, func, data, local_ptr, dest); + codegen_msvc_try(bx, try_func, data, catch_func, dest); } else { - codegen_gnu_try(bx, func, data, local_ptr, dest); + codegen_gnu_try(bx, try_func, data, catch_func, dest); } } @@ -878,9 +878,9 @@ fn try_intrinsic( // as the old ones are still more optimized. fn codegen_msvc_try( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { @@ -892,15 +892,15 @@ fn codegen_msvc_try( let mut catchpad = bx.build_sibling_block("catchpad"); let mut caught = bx.build_sibling_block("caught"); - let func = llvm::get_param(bx.llfn(), 0); + let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); - let local_ptr = llvm::get_param(bx.llfn(), 2); + let catch_func = llvm::get_param(bx.llfn(), 2); // We're generating an IR snippet that looks like: // - // declare i32 @rust_try(%func, %data, %ptr) { - // %slot = alloca [2 x i64] - // invoke %func(%data) to label %normal unwind label %catchswitch + // declare i32 @rust_try(%try_func, %data, %catch_func) { + // %slot = alloca u8* + // invoke %try_func(%data) to label %normal unwind label %catchswitch // // normal: // ret i32 0 @@ -910,8 +910,8 @@ fn codegen_msvc_try( // // catchpad: // %tok = catchpad within %cs [%type_descriptor, 0, %slot] - // %ptr[0] = %slot[0] - // %ptr[1] = %slot[1] + // %ptr = load %slot + // call %catch_func(%data, %ptr) // catchret from %tok to label %caught // // caught: @@ -928,26 +928,26 @@ fn codegen_msvc_try( // ~rust_panic(); // // uint64_t x[2]; - // } + // }; // - // int bar(void (*foo)(void), uint64_t *ret) { + // int __rust_try( + // void (*try_func)(void*), + // void *data, + // void (*catch_func)(void*, void*) noexcept + // ) { // try { - // foo(); + // try_func(data); // return 0; // } catch(rust_panic& a) { - // ret[0] = a.x[0]; - // ret[1] = a.x[1]; - // a.x[0] = 0; + // catch_func(data, &a); // return 1; // } // } // // More information can be found in libstd's seh.rs implementation. - let i64_2 = bx.type_array(bx.type_i64(), 2); - let i64_2_ptr = bx.type_ptr_to(i64_2); let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let slot = bx.alloca(i64_2_ptr, ptr_align); - bx.invoke(func, &[data], normal.llbb(), catchswitch.llbb(), None); + let slot = bx.alloca(bx.type_i8p(), ptr_align); + bx.invoke(try_func, &[data], normal.llbb(), catchswitch.llbb(), None); normal.ret(bx.const_i32(0)); @@ -987,17 +987,8 @@ fn codegen_msvc_try( // Source: MicrosoftCXXABI::getAddrOfCXXCatchHandlerType in clang let flags = bx.const_i32(8); let funclet = catchpad.catch_pad(cs, &[tydesc, flags, slot]); - let i64_align = bx.tcx().data_layout.i64_align.abi; - let payload_ptr = catchpad.load(slot, ptr_align); - let payload = catchpad.load(payload_ptr, i64_align); - let local_ptr = catchpad.bitcast(local_ptr, bx.type_ptr_to(i64_2)); - catchpad.store(payload, local_ptr, i64_align); - - // Clear the first word of the exception so avoid double-dropping it. - // This will be read by the destructor which is implicitly called at the - // end of the catch block by the runtime. - let payload_0_ptr = catchpad.inbounds_gep(payload_ptr, &[bx.const_i32(0), bx.const_i32(0)]); - catchpad.store(bx.const_u64(0), payload_0_ptr, i64_align); + let ptr = catchpad.load(slot, ptr_align); + catchpad.call(catch_func, &[data, ptr], Some(&funclet)); catchpad.catch_ret(&funclet, caught.llbb()); @@ -1006,7 +997,7 @@ fn codegen_msvc_try( // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llfn, &[func, data, local_ptr], None); + let ret = bx.call(llfn, &[try_func, data, catch_func], None); let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -1024,38 +1015,34 @@ fn codegen_msvc_try( // the right personality function. fn codegen_gnu_try( bx: &mut Builder<'a, 'll, 'tcx>, - func: &'ll Value, + try_func: &'ll Value, data: &'ll Value, - local_ptr: &'ll Value, + catch_func: &'ll Value, dest: &'ll Value, ) { let llfn = get_rust_try_fn(bx, &mut |mut bx| { // Codegens the shims described above: // // bx: - // invoke %func(%args...) normal %normal unwind %catch + // invoke %func(%data) normal %normal unwind %catch // // normal: // ret 0 // // catch: - // (ptr, _) = landingpad - // store ptr, %local_ptr + // (%ptr, _) = landingpad + // call %catch_func(%data, %ptr) // ret 1 - // - // Note that the `local_ptr` data passed into the `try` intrinsic is - // expected to be `*mut *mut u8` for this to actually work, but that's - // managed by the standard library. bx.sideeffect(); let mut then = bx.build_sibling_block("then"); let mut catch = bx.build_sibling_block("catch"); - let func = llvm::get_param(bx.llfn(), 0); + let try_func = llvm::get_param(bx.llfn(), 0); let data = llvm::get_param(bx.llfn(), 1); - let local_ptr = llvm::get_param(bx.llfn(), 2); - bx.invoke(func, &[data], then.llbb(), catch.llbb(), None); + let catch_func = llvm::get_param(bx.llfn(), 2); + bx.invoke(try_func, &[data], then.llbb(), catch.llbb(), None); then.ret(bx.const_i32(0)); // Type indicator for the exception being thrown. @@ -1075,15 +1062,13 @@ fn codegen_gnu_try( }; catch.add_clause(vals, tydesc); let ptr = catch.extract_value(vals, 0); - let ptr_align = bx.tcx().data_layout.pointer_align.abi; - let bitcast = catch.bitcast(local_ptr, bx.type_ptr_to(bx.type_i8p())); - catch.store(ptr, bitcast, ptr_align); + catch.call(catch_func, &[data, ptr], None); catch.ret(bx.const_i32(1)); }); // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llfn, &[func, data, local_ptr], None); + let ret = bx.call(llfn, &[try_func, data, catch_func], None); let i32_align = bx.tcx().data_layout.i32_align.abi; bx.store(ret, dest, i32_align); } @@ -1130,15 +1115,22 @@ fn get_rust_try_fn<'ll, 'tcx>( // Define the type up front for the signature of the rust_try function. let tcx = cx.tcx; let i8p = tcx.mk_mut_ptr(tcx.types.i8); - let fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( + let try_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( iter::once(i8p), tcx.mk_unit(), false, hir::Unsafety::Unsafe, Abi::Rust, ))); + let catch_fn_ty = tcx.mk_fn_ptr(ty::Binder::bind(tcx.mk_fn_sig( + [i8p, i8p].iter().cloned(), + tcx.mk_unit(), + false, + hir::Unsafety::Unsafe, + Abi::Rust, + ))); let output = tcx.types.i32; - let rust_try = gen_fn(cx, "__rust_try", vec![fn_ty, i8p, i8p], output, codegen); + let rust_try = gen_fn(cx, "__rust_try", vec![try_fn_ty, i8p, catch_fn_ty], output, codegen); cx.rust_try_fn.set(Some(rust_try)); rust_try } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 3572eda5c13..fc2d315b609 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -297,14 +297,25 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { "try" => { let mut_u8 = tcx.mk_mut_ptr(tcx.types.u8); - let fn_ty = ty::Binder::bind(tcx.mk_fn_sig( + let try_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( iter::once(mut_u8), tcx.mk_unit(), false, hir::Unsafety::Normal, Abi::Rust, )); - (0, vec![tcx.mk_fn_ptr(fn_ty), mut_u8, mut_u8], tcx.types.i32) + let catch_fn_ty = ty::Binder::bind(tcx.mk_fn_sig( + [mut_u8, mut_u8].iter().cloned(), + tcx.mk_unit(), + false, + hir::Unsafety::Normal, + Abi::Rust, + )); + ( + 0, + vec![tcx.mk_fn_ptr(try_fn_ty), mut_u8, tcx.mk_fn_ptr(catch_fn_ty)], + tcx.types.i32, + ) } "va_start" | "va_end" => match mk_va_list_ty(hir::Mutability::Mut) { diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 38cb4418dd0..0be71b52d9e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -12,7 +12,7 @@ use core::panic::{BoxMeUp, Location, PanicInfo}; use crate::any::Any; use crate::fmt; use crate::intrinsics; -use crate::mem::{self, ManuallyDrop, MaybeUninit}; +use crate::mem::{self, ManuallyDrop}; use crate::process; use crate::sync::atomic::{AtomicBool, Ordering}; use crate::sys::stdio::panic_output; @@ -28,9 +28,6 @@ use crate::io::set_panic; #[cfg(test)] use realstd::io::set_panic; -// Include the definition of UnwindPayload from libpanic_unwind. -include!("../libpanic_unwind/payload.rs"); - // Binary interface to the panic runtime that the standard library depends on. // // The standard library is tagged with `#![needs_panic_runtime]` (introduced in @@ -43,9 +40,7 @@ include!("../libpanic_unwind/payload.rs"); // hook up these functions, but it is not this day! #[allow(improper_ctypes)] extern "C" { - /// The payload ptr here is actually the same as the payload ptr for the try - /// intrinsic (i.e., is really `*mut [u64; 2]` or `*mut *mut u8`). - fn __rust_panic_cleanup(payload: TryPayload) -> *mut (dyn Any + Send + 'static); + fn __rust_panic_cleanup(payload: *mut u8) -> *mut (dyn Any + Send + 'static); /// `payload` is actually a `*mut &mut dyn BoxMeUp` but that would cause FFI warnings. /// It cannot be `Box` because the other end of this call does not depend @@ -246,6 +241,7 @@ pub unsafe fn r#try R>(f: F) -> Result> union Data { f: ManuallyDrop, r: ManuallyDrop, + p: ManuallyDrop>, } // We do some sketchy operations with ownership here for the sake of @@ -275,27 +271,57 @@ pub unsafe fn r#try R>(f: F) -> Result> // method of calling a catch panic whilst juggling ownership. let mut data = Data { f: ManuallyDrop::new(f) }; - let mut payload: MaybeUninit = MaybeUninit::uninit(); - let data_ptr = &mut data as *mut _ as *mut u8; - let payload_ptr = payload.as_mut_ptr() as *mut _; - return if intrinsics::r#try(do_call::, data_ptr, payload_ptr) == 0 { + return if do_try(do_call::, data_ptr, do_catch::) == 0 { Ok(ManuallyDrop::into_inner(data.r)) } else { - Err(cleanup(payload.assume_init())) + Err(ManuallyDrop::into_inner(data.p)) }; + // Compatibility wrapper around the try intrinsic for bootstrap + #[inline] + unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 { + #[cfg(not(bootstrap))] + { + intrinsics::r#try(try_fn, data, catch_fn) + } + #[cfg(bootstrap)] + { + use crate::mem::MaybeUninit; + #[cfg(target_env = "msvc")] + type TryPayload = [u64; 2]; + #[cfg(not(target_env = "msvc"))] + type TryPayload = *mut u8; + + let mut payload: MaybeUninit = MaybeUninit::uninit(); + let payload_ptr = payload.as_mut_ptr() as *mut u8; + let r = intrinsics::r#try(try_fn, data, payload_ptr); + if r != 0 { + #[cfg(target_env = "msvc")] + { + catch_fn(data, payload_ptr) + } + #[cfg(not(target_env = "msvc"))] + { + catch_fn(data, payload.assume_init()) + } + } + r + } + } + // We consider unwinding to be rare, so mark this function as cold. However, // do not mark it no-inline -- that decision is best to leave to the // optimizer (in most cases this function is not inlined even as a normal, // non-cold function, though, as of the writing of this comment). #[cold] - unsafe fn cleanup(payload: TryPayload) -> Box { + unsafe fn cleanup(payload: *mut u8) -> Box { let obj = Box::from_raw(__rust_panic_cleanup(payload)); update_panic_count(-1); obj } + #[inline] fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; @@ -304,6 +330,19 @@ pub unsafe fn r#try R>(f: F) -> Result> data.r = ManuallyDrop::new(f()); } } + + // We *do* want this part of the catch to be inlined: this allows the + // compiler to properly track accesses to the Data union and optimize it + // away most of the time. + #[inline] + fn do_catch R, R>(data: *mut u8, payload: *mut u8) { + unsafe { + let data = data as *mut Data; + let data = &mut (*data); + let obj = cleanup(payload); + data.p = ManuallyDrop::new(obj); + } + } } /// Determines whether the current thread is unwinding because of panic. diff --git a/src/test/codegen/try-panic-abort.rs b/src/test/codegen/try-panic-abort.rs index 9bc89a32157..166d2bb9942 100644 --- a/src/test/codegen/try-panic-abort.rs +++ b/src/test/codegen/try-panic-abort.rs @@ -7,11 +7,14 @@ extern "C" { #[unwind(allow)] fn bar(data: *mut u8); } +extern "Rust" { + fn catch(data: *mut u8, exception: *mut u8); +} // CHECK-LABEL: @foo #[no_mangle] pub unsafe fn foo() -> i32 { // CHECK: call void @bar // CHECK: ret i32 0 - std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, 0 as *mut u8) + std::intrinsics::r#try(|x| bar(x), 0 as *mut u8, |x, y| catch(x, y)) } From 8e3467c2150eddc636e88346255bec20feb38b3a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 3 Mar 2020 20:41:37 +0000 Subject: [PATCH 0805/1250] Link to libgcc dynamically on windows-gnu when using dylib crates --- src/librustc_codegen_ssa/back/link.rs | 14 +++++++++++ src/librustc_target/spec/mod.rs | 12 +++++++++ src/librustc_target/spec/windows_base.rs | 31 ++++++++++++++++++++++-- src/libunwind/build.rs | 9 +++++-- 4 files changed, 62 insertions(+), 4 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 90601521b19..fb0205dffe7 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -490,6 +490,11 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( info!("preparing {:?} to {:?}", crate_type, out_filename); let (linker, flavor) = linker_and_flavor(sess); + let any_dynamic_crate = crate_type == config::CrateType::Dylib + || codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| { + *ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic) + }); + // The invocations of cc share some flags across platforms let (pname, mut cmd) = get_linker(sess, &linker, flavor); @@ -555,6 +560,15 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>( if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) { cmd.args(args); } + if any_dynamic_crate { + if let Some(args) = sess.target.target.options.late_link_args_dynamic.get(&flavor) { + cmd.args(args); + } + } else { + if let Some(args) = sess.target.target.options.late_link_args_static.get(&flavor) { + cmd.args(args); + } + } for obj in &sess.target.target.options.post_link_objects { cmd.arg(get_file_path(sess, obj)); } diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 542bcd27507..9c3d760451c 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -579,6 +579,12 @@ pub struct TargetOptions { /// user-defined but before post_link_objects. Standard platform /// libraries that should be always be linked to, usually go here. pub late_link_args: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if at least one + /// Rust dependency is dynamically linked. + pub late_link_args_dynamic: LinkArgs, + /// Linker arguments used in addition to `late_link_args` if aall Rust + /// dependencies are statically linked. + pub late_link_args_static: LinkArgs, /// Objects to link after all others, always found within the /// sysroot folder. pub post_link_objects: Vec, // ... unconditionally @@ -858,6 +864,8 @@ impl Default for TargetOptions { post_link_objects: Vec::new(), post_link_objects_crt: Vec::new(), late_link_args: LinkArgs::new(), + late_link_args_dynamic: LinkArgs::new(), + late_link_args_static: LinkArgs::new(), link_env: Vec::new(), link_env_remove: Vec::new(), archive_format: "gnu".to_string(), @@ -1136,6 +1144,8 @@ impl Target { key!(pre_link_objects_exe_crt, list); key!(pre_link_objects_dll, list); key!(late_link_args, link_args); + key!(late_link_args_dynamic, link_args); + key!(late_link_args_static, link_args); key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); @@ -1363,6 +1373,8 @@ impl ToJson for Target { target_option_val!(pre_link_objects_exe_crt); target_option_val!(pre_link_objects_dll); target_option_val!(link_args - late_link_args); + target_option_val!(link_args - late_link_args_dynamic); + target_option_val!(link_args - late_link_args_static); target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); diff --git a/src/librustc_target/spec/windows_base.rs b/src/librustc_target/spec/windows_base.rs index 693a343d5a5..188548b41fe 100644 --- a/src/librustc_target/spec/windows_base.rs +++ b/src/librustc_target/spec/windows_base.rs @@ -17,12 +17,13 @@ pub fn opts() -> TargetOptions { ); let mut late_link_args = LinkArgs::new(); + let mut late_link_args_dynamic = LinkArgs::new(); + let mut late_link_args_static = LinkArgs::new(); late_link_args.insert( LinkerFlavor::Gcc, vec![ "-lmingwex".to_string(), "-lmingw32".to_string(), - "-lgcc".to_string(), // alas, mingw* libraries above depend on libgcc "-lmsvcrt".to_string(), // mingw's msvcrt is a weird hybrid import library and static library. // And it seems that the linker fails to use import symbols from msvcrt @@ -37,6 +38,31 @@ pub fn opts() -> TargetOptions { "-lkernel32".to_string(), ], ); + late_link_args_dynamic.insert( + LinkerFlavor::Gcc, + vec![ + // If any of our crates are dynamically linked then we need to use + // the shared libgcc_s-dw2-1.dll. This is required to support + // unwinding across DLL boundaries. + "-lgcc_s".to_string(), + "-lgcc".to_string(), + "-lkernel32".to_string(), + ], + ); + late_link_args_static.insert( + LinkerFlavor::Gcc, + vec![ + // If all of our crates are statically linked then we can get away + // with statically linking the libgcc unwinding code. This allows + // binaries to be redistributed without the libgcc_s-dw2-1.dll + // dependency, but unfortunately break unwinding across DLL + // boundaries when unwinding across FFI boundaries. + "-lgcc".to_string(), + "-lgcc_eh".to_string(), + "-lpthread".to_string(), + "-lkernel32".to_string(), + ], + ); TargetOptions { // FIXME(#13846) this should be enabled for windows @@ -63,8 +89,9 @@ pub fn opts() -> TargetOptions { "rsbegin.o".to_string(), ], late_link_args, + late_link_args_dynamic, + late_link_args_static, post_link_objects: vec!["rsend.o".to_string()], - custom_unwind_resume: true, abi_return_struct_as_int: true, emit_debug_gdb_scripts: false, requires_uwtable: true, diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index a24808b3250..0628e5d2fc0 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -33,8 +33,13 @@ fn main() { } else if target.contains("dragonfly") { println!("cargo:rustc-link-lib=gcc_pic"); } else if target.contains("pc-windows-gnu") { - println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); - println!("cargo:rustc-link-lib=static-nobundle=pthread"); + // This is handled in the target spec with late_link_args_[static|dynamic] + + // cfg!(bootstrap) doesn't work in build scripts + if env::var("RUSTC_STAGE").ok() == Some("0".to_string()) { + println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); + println!("cargo:rustc-link-lib=static-nobundle=pthread"); + } } else if target.contains("uwp-windows-gnu") { println!("cargo:rustc-link-lib=unwind"); } else if target.contains("fuchsia") { From 04f24b7c69a576533a3dba889c1a78f21e0d38a9 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 5 Mar 2020 14:34:25 +0000 Subject: [PATCH 0806/1250] Fix MinGW termination callbacks not being invoked --- src/rtstartup/rsbegin.rs | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/src/rtstartup/rsbegin.rs b/src/rtstartup/rsbegin.rs index f92ff9f071a..bd1946133e8 100644 --- a/src/rtstartup/rsbegin.rs +++ b/src/rtstartup/rsbegin.rs @@ -60,37 +60,36 @@ pub mod eh_frames { } // Unwind info registration/deregistration routines. - // See the docs of `unwind` module in libstd. + // See the docs of libpanic_unwind. extern "C" { fn rust_eh_register_frames(eh_frame_begin: *const u8, object: *mut u8); fn rust_eh_unregister_frames(eh_frame_begin: *const u8, object: *mut u8); } - unsafe fn init() { + unsafe extern "C" fn init() { // register unwind info on module startup rust_eh_register_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); } - unsafe fn uninit() { + unsafe extern "C" fn uninit() { // unregister on shutdown rust_eh_unregister_frames(&__EH_FRAME_BEGIN__ as *const u8, &mut OBJ as *mut _ as *mut u8); } - // MSVC-specific init/uninit routine registration - pub mod ms_init { - // .CRT$X?? sections are roughly analogous to ELF's .init_array and .fini_array, - // except that they exploit the fact that linker will sort them alphabitically, - // so e.g., sections with names between .CRT$XIA and .CRT$XIZ are guaranteed to be - // placed between those two, without requiring any ordering of objects on the linker - // command line. - // Note that ordering of same-named sections from different objects is not guaranteed. - // Since .CRT$XIA contains init array's header symbol, which must always come first, - // we place our initialization callback into .CRT$XIB. + // MinGW-specific init/uninit routine registration + pub mod mingw_init { + // MinGW's startup objects (crt0.o / dllcrt0.o) will invoke global constructors in the + // .ctors and .dtors sections on startup and exit. In the case of DLLs, this is done when + // the DLL is loaded and unloaded. + // + // The linker will sort the sections, which ensures that our callbacks are located at the + // end of the list. Since constructors are run in reverse order, this ensures that our + // callbacks are the first and last ones executed. - #[link_section = ".CRT$XIB"] // .CRT$XI? : C initialization callbacks - pub static P_INIT: unsafe fn() = super::init; + #[link_section = ".ctors.65535"] // .ctors.* : C initialization callbacks + pub static P_INIT: unsafe extern "C" fn() = super::init; - #[link_section = ".CRT$XTY"] // .CRT$XT? : C termination callbacks - pub static P_UNINIT: unsafe fn() = super::uninit; + #[link_section = ".dtors.65535"] // .dtors.* : C termination callbacks + pub static P_UNINIT: unsafe extern "C" fn() = super::uninit; } } From c1df945a610bb6eddfe0dc5ff033722fa611ef09 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 01:06:07 +0300 Subject: [PATCH 0807/1250] rustc_metadata: Give decoder access to whole crate store --- src/librustc_metadata/creader.rs | 24 ++++++++++-- src/librustc_metadata/rmeta/decoder.rs | 39 +++++++++++-------- .../rmeta/decoder/cstore_impl.rs | 2 +- 3 files changed, 43 insertions(+), 22 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 5254471051f..18b4c9ad504 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -76,6 +76,21 @@ impl<'a> LoadError<'a> { } } +/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary. +#[derive(Clone, Copy)] +crate struct CrateMetadataRef<'a> { + pub cdata: &'a CrateMetadata, + pub cstore: &'a CStore, +} + +impl std::ops::Deref for CrateMetadataRef<'_> { + type Target = CrateMetadata; + + fn deref(&self) -> &Self::Target { + self.cdata + } +} + fn dump_crates(cstore: &CStore) { info!("resolved crates:"); cstore.iter_crate_data(|cnum, data| { @@ -100,10 +115,11 @@ impl CStore { CrateNum::new(self.metas.len() - 1) } - crate fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata { - self.metas[cnum] + crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> { + let cdata = self.metas[cnum] .as_ref() - .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)) + .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)); + CrateMetadataRef { cdata, cstore: self } } fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { @@ -217,7 +233,7 @@ impl<'a> CrateLoader<'a> { // We're also sure to compare *paths*, not actual byte slices. The // `source` stores paths which are normalized which may be different // from the strings on the command line. - let source = self.cstore.get_crate_data(cnum).source(); + let source = self.cstore.get_crate_data(cnum).cdata.source(); if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) { // Only use `--extern crate_name=path` here, not `--extern crate_name`. if let Some(mut files) = entry.files() { diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a72ee0cbe47..5dec7bfe60c 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1,5 +1,6 @@ // Decoding metadata from a single crate's metadata +use crate::creader::CrateMetadataRef; use crate::rmeta::table::{FixedSizeEncoding, Table}; use crate::rmeta::*; @@ -125,7 +126,7 @@ struct ImportedSourceFile { pub(super) struct DecodeContext<'a, 'tcx> { opaque: opaque::Decoder<'a>, - cdata: Option<&'a CrateMetadata>, + cdata: Option>, sess: Option<&'tcx Session>, tcx: Option>, @@ -141,7 +142,7 @@ pub(super) struct DecodeContext<'a, 'tcx> { /// Abstract over the various ways one can create metadata decoders. pub(super) trait Metadata<'a, 'tcx>: Copy { fn raw_bytes(self) -> &'a [u8]; - fn cdata(self) -> Option<&'a CrateMetadata> { + fn cdata(self) -> Option> { None } fn sess(self) -> Option<&'tcx Session> { @@ -162,7 +163,7 @@ pub(super) trait Metadata<'a, 'tcx>: Copy { lazy_state: LazyState::NoNode, alloc_decoding_session: self .cdata() - .map(|cdata| cdata.alloc_decoding_state.new_decoding_session()), + .map(|cdata| cdata.cdata.alloc_decoding_state.new_decoding_session()), } } } @@ -185,33 +186,33 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a MetadataBlob, &'tcx Session) { } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata { +impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadataRef<'a> { fn raw_bytes(self) -> &'a [u8] { self.blob.raw_bytes() } - fn cdata(self) -> Option<&'a CrateMetadata> { - Some(self) + fn cdata(self) -> Option> { + Some(*self) } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, &'tcx Session) { +impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, &'tcx Session) { fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() } - fn cdata(self) -> Option<&'a CrateMetadata> { - Some(self.0) + fn cdata(self) -> Option> { + Some(*self.0) } fn sess(self) -> Option<&'tcx Session> { Some(&self.1) } } -impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) { +impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) { fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() } - fn cdata(self) -> Option<&'a CrateMetadata> { - Some(self.0) + fn cdata(self) -> Option> { + Some(*self.0) } fn tcx(self) -> Option> { Some(self.1) @@ -242,7 +243,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.tcx.expect("missing TyCtxt in DecodeContext") } - fn cdata(&self) -> &'a CrateMetadata { + fn cdata(&self) -> CrateMetadataRef<'a> { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -558,7 +559,7 @@ impl CrateRoot<'_> { } } -impl<'a, 'tcx> CrateMetadata { +impl CrateMetadata { crate fn new( sess: &Session, blob: MetadataBlob, @@ -601,7 +602,9 @@ impl<'a, 'tcx> CrateMetadata { extern_crate: Lock::new(None), } } +} +impl<'a, 'tcx> CrateMetadataRef<'a> { fn is_proc_macro(&self, id: DefIndex) -> bool { self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some() } @@ -1440,10 +1443,10 @@ impl<'a, 'tcx> CrateMetadata { /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. fn imported_source_files( - &'a self, + &self, local_source_map: &source_map::SourceMap, - ) -> &[ImportedSourceFile] { - self.source_map_import_info.init_locking(|| { + ) -> &'a [ImportedSourceFile] { + self.cdata.source_map_import_info.init_locking(|| { let external_source_map = self.root.source_map.decode(self); external_source_map @@ -1540,7 +1543,9 @@ impl<'a, 'tcx> CrateMetadata { dep_node_index } +} +impl CrateMetadata { crate fn dependencies(&self) -> LockGuard<'_, Vec> { self.dependencies.borrow() } diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index be229350f3b..c890640d432 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -517,7 +517,7 @@ impl CrateStore for CStore { } fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable { - &self.get_crate_data(cnum).def_path_table + &self.get_crate_data(cnum).cdata.def_path_table } fn crates_untracked(&self) -> Vec { From 41374d748b3c8bc39a78adf703d7d5560a4a8ab7 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 22:56:27 +0300 Subject: [PATCH 0808/1250] rustc_metadata: Move some code from `impl CrateMetadataRef` to `impl CrateMetadata` --- src/librustc_metadata/rmeta/decoder.rs | 176 ++++++++++++------------- 1 file changed, 87 insertions(+), 89 deletions(-) diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 5dec7bfe60c..e60ae5b6c25 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -559,51 +559,6 @@ impl CrateRoot<'_> { } } -impl CrateMetadata { - crate fn new( - sess: &Session, - blob: MetadataBlob, - root: CrateRoot<'static>, - raw_proc_macros: Option<&'static [ProcMacro]>, - cnum: CrateNum, - cnum_map: CrateNumMap, - dep_kind: DepKind, - source: CrateSource, - private_dep: bool, - host_hash: Option, - ) -> CrateMetadata { - let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || { - root.def_path_table.decode((&blob, sess)) - }); - let trait_impls = root - .impls - .decode((&blob, sess)) - .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) - .collect(); - let alloc_decoding_state = - AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); - let dependencies = Lock::new(cnum_map.iter().cloned().collect()); - CrateMetadata { - blob, - root, - def_path_table, - trait_impls, - raw_proc_macros, - source_map_import_info: Once::new(), - alloc_decoding_state, - dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), - cnum, - cnum_map, - dependencies, - dep_kind: Lock::new(dep_kind), - source, - private_dep, - host_hash, - extern_crate: Lock::new(None), - } - } -} - impl<'a, 'tcx> CrateMetadataRef<'a> { fn is_proc_macro(&self, id: DefIndex) -> bool { self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some() @@ -625,10 +580,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { }) } - fn local_def_id(&self, index: DefIndex) -> DefId { - DefId { krate: self.cnum, index } - } - 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'. @@ -1194,18 +1145,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .collect() } - // Translate a DefId from the current compilation environment to a DefId - // for an external crate. - fn reverse_translate_def_id(&self, did: DefId) -> Option { - for (local, &global) in self.cnum_map.iter_enumerated() { - if global == did.krate { - return Some(DefId { krate: local, index: did.index }); - } - } - - None - } - fn get_inherent_implementations_for_type( &self, tcx: TyCtxt<'tcx>, @@ -1412,11 +1351,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } - #[inline] - fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - self.def_path_table.def_path_hash(index) - } - /// Imports the source_map from an external crate into the source_map of the crate /// currently being compiled (the "local crate"). /// @@ -1519,33 +1453,52 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .collect() }) } +} - /// Get the `DepNodeIndex` corresponding this crate. The result of this - /// method is cached in the `dep_node_index` field. - fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { - let mut dep_node_index = self.dep_node_index.load(); - - if unlikely!(dep_node_index == DepNodeIndex::INVALID) { - // We have not cached the DepNodeIndex for this upstream crate yet, - // so use the dep-graph to find it out and cache it. - // Note that multiple threads can enter this block concurrently. - // That is fine because the DepNodeIndex remains constant - // throughout the whole compilation session, and multiple stores - // would always write the same value. - - let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); - let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata); - - dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); - assert!(dep_node_index != DepNodeIndex::INVALID); - self.dep_node_index.store(dep_node_index); +impl CrateMetadata { + crate fn new( + sess: &Session, + blob: MetadataBlob, + root: CrateRoot<'static>, + raw_proc_macros: Option<&'static [ProcMacro]>, + cnum: CrateNum, + cnum_map: CrateNumMap, + dep_kind: DepKind, + source: CrateSource, + private_dep: bool, + host_hash: Option, + ) -> CrateMetadata { + let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || { + root.def_path_table.decode((&blob, sess)) + }); + let trait_impls = root + .impls + .decode((&blob, sess)) + .map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)) + .collect(); + let alloc_decoding_state = + AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); + let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + CrateMetadata { + blob, + root, + def_path_table, + trait_impls, + raw_proc_macros, + source_map_import_info: Once::new(), + alloc_decoding_state, + dep_node_index: AtomicCell::new(DepNodeIndex::INVALID), + cnum, + cnum_map, + dependencies, + dep_kind: Lock::new(dep_kind), + source, + private_dep, + host_hash, + extern_crate: Lock::new(None), } - - dep_node_index } -} -impl CrateMetadata { crate fn dependencies(&self) -> LockGuard<'_, Vec> { self.dependencies.borrow() } @@ -1618,6 +1571,51 @@ impl CrateMetadata { crate fn hash(&self) -> Svh { self.root.hash } + + fn local_def_id(&self, index: DefIndex) -> DefId { + DefId { krate: self.cnum, index } + } + + // Translate a DefId from the current compilation environment to a DefId + // for an external crate. + fn reverse_translate_def_id(&self, did: DefId) -> Option { + for (local, &global) in self.cnum_map.iter_enumerated() { + if global == did.krate { + return Some(DefId { krate: local, index: did.index }); + } + } + + None + } + + #[inline] + fn def_path_hash(&self, index: DefIndex) -> DefPathHash { + self.def_path_table.def_path_hash(index) + } + + /// Get the `DepNodeIndex` corresponding this crate. The result of this + /// method is cached in the `dep_node_index` field. + fn get_crate_dep_node_index(&self, tcx: TyCtxt<'tcx>) -> DepNodeIndex { + let mut dep_node_index = self.dep_node_index.load(); + + if unlikely!(dep_node_index == DepNodeIndex::INVALID) { + // We have not cached the DepNodeIndex for this upstream crate yet, + // so use the dep-graph to find it out and cache it. + // Note that multiple threads can enter this block concurrently. + // That is fine because the DepNodeIndex remains constant + // throughout the whole compilation session, and multiple stores + // would always write the same value. + + let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); + let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata); + + dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); + assert!(dep_node_index != DepNodeIndex::INVALID); + self.dep_node_index.store(dep_node_index); + } + + dep_node_index + } } // Cannot be implemented on 'ProcMacro', as libproc_macro From ebd941b890e4731aed0ea1f76f056c8a6394f251 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 5 Mar 2020 00:00:00 +0000 Subject: [PATCH 0809/1250] debuginfo: Generators use u32 as discriminant type repr --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 7beaf134e6b..095330a2e4b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1802,9 +1802,9 @@ fn prepare_enum_metadata( DIB(cx), name.as_ptr().cast(), name.len(), - // FIXME: what if enumeration has i128 discriminant? - variant_index.as_usize() as i64, - false, // FIXME: IsUnsigned. + // Generators use u32 as discriminant type. + variant_index.as_u32().into(), + true, // IsUnsigned )) } }) From 30650f867bb0a94b3378942487e78f3eb7eb868f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 5 Mar 2020 00:00:00 +0000 Subject: [PATCH 0810/1250] debuginfo: Use is unsigned flag when emitting enumerators --- .../debuginfo/metadata.rs | 7 ++++- src/test/codegen/enum-discriminant-value.rs | 27 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/enum-discriminant-value.rs diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 095330a2e4b..67529a82532 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1780,6 +1780,11 @@ fn prepare_enum_metadata( .zip(&def.variants) .map(|((_, discr), v)| { let name = v.ident.as_str(); + let is_unsigned = match discr.ty.kind { + ty::Int(_) => false, + ty::Uint(_) => true, + _ => bug!("non integer discriminant"), + }; unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( DIB(cx), @@ -1787,7 +1792,7 @@ fn prepare_enum_metadata( name.len(), // FIXME: what if enumeration has i128 discriminant? discr.val as i64, - false, // FIXME: IsUnsigned. + is_unsigned, )) } }) diff --git a/src/test/codegen/enum-discriminant-value.rs b/src/test/codegen/enum-discriminant-value.rs new file mode 100644 index 00000000000..f9da987765f --- /dev/null +++ b/src/test/codegen/enum-discriminant-value.rs @@ -0,0 +1,27 @@ +// Verify that DIEnumerator uses isUnsigned flag when appropriate. +// +// compile-flags: -g -C no-prepopulate-passes + +#[repr(i64)] +pub enum I64 { + I64Min = std::i64::MIN, + I64Max = std::i64::MAX, +} + +#[repr(u64)] +pub enum U64 { + U64Min = std::u64::MIN, + U64Max = std::u64::MAX, +} + +fn main() { + let _a = I64::I64Min; + let _b = I64::I64Max; + let _c = U64::U64Min; + let _d = U64::U64Max; +} + +// CHECK: !DIEnumerator(name: "I64Min", value: -9223372036854775808) +// CHECK: !DIEnumerator(name: "I64Max", value: 9223372036854775807) +// CHECK: !DIEnumerator(name: "U64Min", value: 0, isUnsigned: true) +// CHECK: !DIEnumerator(name: "U64Max", value: 18446744073709551615, isUnsigned: true) From 79bc934ff3ec527a8ec17aa7b1a20ed271ca7508 Mon Sep 17 00:00:00 2001 From: TrolledWoods Date: Thu, 5 Mar 2020 20:20:02 +0100 Subject: [PATCH 0811/1250] Fixed a typo "vector" was used instead of "string" --- src/liballoc/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index f5afea15d65..c95f79472fe 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -407,7 +407,7 @@ impl String { /// /// assert_eq!(s.capacity(), cap); /// - /// // ...but this may make the vector reallocate + /// // ...but this may make the string reallocate /// s.push('a'); /// ``` #[inline] From 2070ea26e1747f9cb1fb8266bbfe48d79a5ada87 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Wed, 4 Mar 2020 22:44:28 +0100 Subject: [PATCH 0812/1250] Move stray generator test into the `generator` dir --- .../ui/{ => generator}/generator-yielding-or-returning-itself.rs | 0 .../{ => generator}/generator-yielding-or-returning-itself.stderr | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => generator}/generator-yielding-or-returning-itself.rs (100%) rename src/test/ui/{ => generator}/generator-yielding-or-returning-itself.stderr (100%) diff --git a/src/test/ui/generator-yielding-or-returning-itself.rs b/src/test/ui/generator/generator-yielding-or-returning-itself.rs similarity index 100% rename from src/test/ui/generator-yielding-or-returning-itself.rs rename to src/test/ui/generator/generator-yielding-or-returning-itself.rs diff --git a/src/test/ui/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr similarity index 100% rename from src/test/ui/generator-yielding-or-returning-itself.stderr rename to src/test/ui/generator/generator-yielding-or-returning-itself.stderr From 2770f300b12268925922152de1e53a2b9e2557a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Mar 2020 23:38:48 +0100 Subject: [PATCH 0813/1250] reduce test size for Miri --- src/liballoc/tests/slice.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/liballoc/tests/slice.rs b/src/liballoc/tests/slice.rs index 3d6b4bff5e0..8e49e6d8eba 100644 --- a/src/liballoc/tests/slice.rs +++ b/src/liballoc/tests/slice.rs @@ -1733,9 +1733,9 @@ fn panic_safe() { let moduli = &[5, 20, 50]; #[cfg(miri)] - let lens = 1..13; + let lens = 1..10; #[cfg(miri)] - let moduli = &[10]; + let moduli = &[5]; for len in lens { for &modulus in moduli { From 713a291441d2c71e74141ddc9387166bd6755d9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 5 Mar 2020 15:39:35 -0800 Subject: [PATCH 0814/1250] review comments --- src/librustc_ast_passes/ast_validation.rs | 52 +++++++++---------- src/librustc_parse/parser/item.rs | 18 ++++--- .../coherence-negative-impls-safe.stderr | 5 +- src/test/ui/error-codes/E0197.stderr | 4 +- src/test/ui/error-codes/E0198.stderr | 5 +- .../inherent-impl.stderr | 8 +-- .../defaultimpl/validation.stderr | 4 +- src/test/ui/syntax-trait-polarity.stderr | 22 +++++--- .../traits/trait-safety-inherent-impl.stderr | 4 +- 9 files changed, 65 insertions(+), 57 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 1070043458a..d90e9c4df26 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -801,6 +801,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { E0198, "negative impls cannot be unsafe" ) + .span_label(sp, "negative because of this") .span_label(span, "unsafe because of this") .emit(); } @@ -819,45 +820,40 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ref self_ty, items: _, } => { + let error = |annotation_span, annotation, note, code| { + let mut err = self.err_handler().struct_span_err( + self_ty.span, + &format!("inherent impls cannot be {}", annotation), + ); + err.span_label(annotation_span, &format!("{} because of this", annotation)); + err.span_label(self_ty.span, "inherent impl for this type"); + if note { + err.note(&format!( + "only trait implementations may be annotated with {}", + annotation + )); + } + if code { + err.code(error_code!(E0197)); + } + err.emit(); + }; + self.invalid_visibility( &item.vis, Some("place qualifiers on individual impl items instead"), ); if let Unsafe::Yes(span) = unsafety { - struct_span_err!( - self.session, - vec![span, self_ty.span], - E0197, - "inherent impls cannot be unsafe" - ) - .span_label(span, "unsafe because of this") - .span_label(self_ty.span, "inherent impl for this type") - .emit(); + error(span, "unsafe", false, true) } if let ImplPolarity::Negative(span) = polarity { - self.err_handler().span_err(span, "inherent impls cannot be negative"); + error(span, "negative", false, false); } if let Defaultness::Default(def_span) = defaultness { - self.err_handler() - .struct_span_err( - vec![def_span, self_ty.span], - "inherent impls cannot be `default`", - ) - .span_label(def_span, "`default` because of this") - .span_label(self_ty.span, "inherent impl for this type") - .note("only trait implementations may be annotated with `default`") - .emit(); + error(def_span, "`default`", true, false); } if let Const::Yes(span) = constness { - self.err_handler() - .struct_span_err( - vec![span, self_ty.span], - "inherent impls cannot be `const`", - ) - .span_label(span, "`const` because of this") - .span_label(self_ty.span, "inherent impl for this type") - .note("only trait implementations may be annotated with `const`") - .emit(); + error(span, "`const`", true, false); } } ItemKind::Fn(def, ref sig, ref generics, ref body) => { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 09c512f3254..85bb546b748 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -373,6 +373,16 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Async) && self.is_keyword_ahead(1, &[kw::Fn]) } + fn parse_polarity(&mut self) -> ast::ImplPolarity { + // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. + if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) { + self.bump(); // `!` + ast::ImplPolarity::Negative(self.prev_token.span) + } else { + ast::ImplPolarity::Positive + } + } + /// Parses an implementation item. /// /// ``` @@ -411,13 +421,7 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::const_trait_impl, span); } - // Disambiguate `impl !Trait for Type { ... }` and `impl ! { ... }` for the never type. - let polarity = if self.check(&token::Not) && self.look_ahead(1, |t| t.can_begin_type()) { - self.bump(); // `!` - ast::ImplPolarity::Negative(self.prev_token.span) - } else { - ast::ImplPolarity::Positive - }; + let polarity = self.parse_polarity(); // Parse both types and traits as a type, then reinterpret if necessary. let err_path = |span| ast::Path::from_ident(Ident::new(kw::Invalid, span)); diff --git a/src/test/ui/coherence/coherence-negative-impls-safe.stderr b/src/test/ui/coherence/coherence-negative-impls-safe.stderr index eebd1de277e..1bd37f39590 100644 --- a/src/test/ui/coherence/coherence-negative-impls-safe.stderr +++ b/src/test/ui/coherence/coherence-negative-impls-safe.stderr @@ -2,8 +2,9 @@ error[E0198]: negative impls cannot be unsafe --> $DIR/coherence-negative-impls-safe.rs:7:13 | LL | unsafe impl !Send for TestType {} - | ------ ^^^^^ - | | + | ------ -^^^^ + | | | + | | negative because of this | unsafe because of this error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0197.stderr b/src/test/ui/error-codes/E0197.stderr index bc3c2857958..35e1042649e 100644 --- a/src/test/ui/error-codes/E0197.stderr +++ b/src/test/ui/error-codes/E0197.stderr @@ -1,8 +1,8 @@ error[E0197]: inherent impls cannot be unsafe - --> $DIR/E0197.rs:3:1 + --> $DIR/E0197.rs:3:13 | LL | unsafe impl Foo { } - | ^^^^^^ ^^^ inherent impl for this type + | ------ ^^^ inherent impl for this type | | | unsafe because of this diff --git a/src/test/ui/error-codes/E0198.stderr b/src/test/ui/error-codes/E0198.stderr index 43304768700..bb2efefb427 100644 --- a/src/test/ui/error-codes/E0198.stderr +++ b/src/test/ui/error-codes/E0198.stderr @@ -2,8 +2,9 @@ error[E0198]: negative impls cannot be unsafe --> $DIR/E0198.rs:5:13 | LL | unsafe impl !Send for Foo { } - | ------ ^^^^^ - | | + | ------ -^^^^ + | | | + | | negative because of this | unsafe because of this error: aborting due to previous error diff --git a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr index 0a76c70b97d..834f6a409f5 100644 --- a/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr +++ b/src/test/ui/rfc-2632-const-trait-impl/inherent-impl.stderr @@ -1,18 +1,18 @@ error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:9:6 + --> $DIR/inherent-impl.rs:9:12 | LL | impl const S {} - | ^^^^^ ^ inherent impl for this type + | ----- ^ inherent impl for this type | | | `const` because of this | = note: only trait implementations may be annotated with `const` error: inherent impls cannot be `const` - --> $DIR/inherent-impl.rs:12:6 + --> $DIR/inherent-impl.rs:12:12 | LL | impl const T {} - | ^^^^^ ^ inherent impl for this type + | ----- ^ inherent impl for this type | | | `const` because of this | diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr index 2a96f41a249..6e19d79e48f 100644 --- a/src/test/ui/specialization/defaultimpl/validation.stderr +++ b/src/test/ui/specialization/defaultimpl/validation.stderr @@ -1,8 +1,8 @@ error: inherent impls cannot be `default` - --> $DIR/validation.rs:7:1 + --> $DIR/validation.rs:7:14 | LL | default impl S {} - | ^^^^^^^ ^ inherent impl for this type + | ------- ^ inherent impl for this type | | | `default` because of this | diff --git a/src/test/ui/syntax-trait-polarity.stderr b/src/test/ui/syntax-trait-polarity.stderr index b7d5b4570aa..5777e0ade90 100644 --- a/src/test/ui/syntax-trait-polarity.stderr +++ b/src/test/ui/syntax-trait-polarity.stderr @@ -1,29 +1,35 @@ error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:7:6 + --> $DIR/syntax-trait-polarity.rs:7:7 | LL | impl !TestType {} - | ^ + | -^^^^^^^^ inherent impl for this type + | | + | negative because of this error[E0198]: negative impls cannot be unsafe --> $DIR/syntax-trait-polarity.rs:12:13 | LL | unsafe impl !Send for TestType {} - | ------ ^^^^^ - | | + | ------ -^^^^ + | | | + | | negative because of this | unsafe because of this error: inherent impls cannot be negative - --> $DIR/syntax-trait-polarity.rs:19:9 + --> $DIR/syntax-trait-polarity.rs:19:10 | LL | impl !TestType2 {} - | ^ + | -^^^^^^^^^^^^ inherent impl for this type + | | + | negative because of this error[E0198]: negative impls cannot be unsafe --> $DIR/syntax-trait-polarity.rs:22:16 | LL | unsafe impl !Send for TestType2 {} - | ------ ^^^^^ - | | + | ------ -^^^^ + | | | + | | negative because of this | unsafe because of this error[E0192]: negative impls are only allowed for auto traits (e.g., `Send` and `Sync`) diff --git a/src/test/ui/traits/trait-safety-inherent-impl.stderr b/src/test/ui/traits/trait-safety-inherent-impl.stderr index 09ad4585ab1..0738d2973e2 100644 --- a/src/test/ui/traits/trait-safety-inherent-impl.stderr +++ b/src/test/ui/traits/trait-safety-inherent-impl.stderr @@ -1,8 +1,8 @@ error[E0197]: inherent impls cannot be unsafe - --> $DIR/trait-safety-inherent-impl.rs:5:1 + --> $DIR/trait-safety-inherent-impl.rs:5:13 | LL | unsafe impl SomeStruct { - | ^^^^^^ ^^^^^^^^^^ inherent impl for this type + | ------ ^^^^^^^^^^ inherent impl for this type | | | unsafe because of this From 818934b9b418e16e6d60fb061e1e712f48c33216 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 6 Mar 2020 00:32:06 +0100 Subject: [PATCH 0815/1250] Model generator resumption in dataflow We now have a way to apply an effect only *after* a `yield` resumes, similar to calls (which can either return or unwind). --- src/librustc_mir/dataflow/generic/cursor.rs | 50 +++++++++++-------- src/librustc_mir/dataflow/generic/engine.rs | 9 ++-- src/librustc_mir/dataflow/generic/graphviz.rs | 2 +- src/librustc_mir/dataflow/generic/mod.rs | 32 ++++++++++++ src/librustc_mir/dataflow/generic/tests.rs | 4 +- .../dataflow/impls/storage_liveness.rs | 18 ++++++- src/librustc_mir/transform/generator.rs | 4 +- 7 files changed, 88 insertions(+), 31 deletions(-) diff --git a/src/librustc_mir/dataflow/generic/cursor.rs b/src/librustc_mir/dataflow/generic/cursor.rs index 8c0ab150528..170157aca5d 100644 --- a/src/librustc_mir/dataflow/generic/cursor.rs +++ b/src/librustc_mir/dataflow/generic/cursor.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; -use rustc::mir::{self, BasicBlock, Location}; +use rustc::mir::{self, BasicBlock, Location, TerminatorKind}; use rustc_index::bit_set::BitSet; use super::{Analysis, Results}; @@ -29,14 +29,14 @@ where pos: CursorPosition, - /// When this flag is set, the cursor is pointing at a `Call` terminator whose call return - /// effect has been applied to `state`. + /// When this flag is set, the cursor is pointing at a `Call` or `Yield` terminator whose call + /// return or resume effect has been applied to `state`. /// - /// This flag helps to ensure that multiple calls to `seek_after_assume_call_returns` with the + /// This flag helps to ensure that multiple calls to `seek_after_assume_success` with the /// same target will result in exactly one invocation of `apply_call_return_effect`. It is /// sufficient to clear this only in `seek_to_block_start`, since seeking away from a /// terminator will always require a cursor reset. - call_return_effect_applied: bool, + success_effect_applied: bool, } impl<'mir, 'tcx, A, R> ResultsCursor<'mir, 'tcx, A, R> @@ -50,7 +50,7 @@ where body, pos: CursorPosition::BlockStart(mir::START_BLOCK), state: results.borrow().entry_sets[mir::START_BLOCK].clone(), - call_return_effect_applied: false, + success_effect_applied: false, results, } } @@ -76,14 +76,14 @@ where pub fn seek_to_block_start(&mut self, block: BasicBlock) { self.state.overwrite(&self.results.borrow().entry_sets[block]); self.pos = CursorPosition::BlockStart(block); - self.call_return_effect_applied = false; + self.success_effect_applied = false; } /// Advances the cursor to hold all effects up to and including to the "before" effect of the /// statement (or terminator) at the given location. /// /// If you wish to observe the full effect of a statement or terminator, not just the "before" - /// effect, use `seek_after` or `seek_after_assume_call_returns`. + /// effect, use `seek_after` or `seek_after_assume_success`. pub fn seek_before(&mut self, target: Location) { assert!(target <= self.body.terminator_loc(target.block)); self.seek_(target, false); @@ -93,7 +93,7 @@ where /// terminators) up to and including the `target`. /// /// If the `target` is a `Call` terminator, any call return effect for that terminator will - /// **not** be observed. Use `seek_after_assume_call_returns` if you wish to observe the call + /// **not** be observed. Use `seek_after_assume_success` if you wish to observe the call /// return effect. pub fn seek_after(&mut self, target: Location) { assert!(target <= self.body.terminator_loc(target.block)); @@ -101,7 +101,7 @@ where // If we have already applied the call return effect, we are currently pointing at a `Call` // terminator. Unconditionally reset the dataflow cursor, since there is no way to "undo" // the call return effect. - if self.call_return_effect_applied { + if self.success_effect_applied { self.seek_to_block_start(target.block); } @@ -111,25 +111,25 @@ where /// Advances the cursor to hold all effects up to and including of the statement (or /// terminator) at the given location. /// - /// If the `target` is a `Call` terminator, any call return effect for that terminator will - /// be observed. Use `seek_after` if you do **not** wish to observe the call return effect. - pub fn seek_after_assume_call_returns(&mut self, target: Location) { + /// If the `target` is a `Call` or `Yield` terminator, any call return or resume effect for that + /// terminator will be observed. Use `seek_after` if you do **not** wish to observe the + /// "success" effect. + pub fn seek_after_assume_success(&mut self, target: Location) { let terminator_loc = self.body.terminator_loc(target.block); assert!(target.statement_index <= terminator_loc.statement_index); self.seek_(target, true); - if target != terminator_loc { + if target != terminator_loc || self.success_effect_applied { return; } + // Apply the effect of the "success" path of the terminator. + + self.success_effect_applied = true; let terminator = self.body.basic_blocks()[target.block].terminator(); - if let mir::TerminatorKind::Call { - destination: Some((return_place, _)), func, args, .. - } = &terminator.kind - { - if !self.call_return_effect_applied { - self.call_return_effect_applied = true; + match &terminator.kind { + TerminatorKind::Call { destination: Some((return_place, _)), func, args, .. } => { self.results.borrow().analysis.apply_call_return_effect( &mut self.state, target.block, @@ -138,6 +138,14 @@ where return_place, ); } + TerminatorKind::Yield { resume, resume_arg, .. } => { + self.results.borrow().analysis.apply_yield_resume_effect( + &mut self.state, + *resume, + resume_arg, + ); + } + _ => {} } } @@ -172,7 +180,7 @@ where self.seek_to_block_start(target.block) } - // N.B., `call_return_effect_applied` is checked in `seek_after`, not here. + // N.B., `success_effect_applied` is checked in `seek_after`, not here. _ => (), } diff --git a/src/librustc_mir/dataflow/generic/engine.rs b/src/librustc_mir/dataflow/generic/engine.rs index 1487129f6c7..606e7eb52b5 100644 --- a/src/librustc_mir/dataflow/generic/engine.rs +++ b/src/librustc_mir/dataflow/generic/engine.rs @@ -218,15 +218,18 @@ where Goto { target } | Assert { target, cleanup: None, .. } - | Yield { resume: target, drop: None, .. } | Drop { target, location: _, unwind: None } | DropAndReplace { target, value: _, location: _, unwind: None } => { self.propagate_bits_into_entry_set_for(in_out, target, dirty_list) } - Yield { resume: target, drop: Some(drop), .. } => { + Yield { resume: target, drop, resume_arg, .. } => { + if let Some(drop) = drop { + self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list); + } + + self.analysis.apply_yield_resume_effect(in_out, target, &resume_arg); self.propagate_bits_into_entry_set_for(in_out, target, dirty_list); - self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list); } Assert { target, cleanup: Some(unwind), .. } diff --git a/src/librustc_mir/dataflow/generic/graphviz.rs b/src/librustc_mir/dataflow/generic/graphviz.rs index 157526d3c51..d2aeba3644a 100644 --- a/src/librustc_mir/dataflow/generic/graphviz.rs +++ b/src/librustc_mir/dataflow/generic/graphviz.rs @@ -241,7 +241,7 @@ where )?; let state_on_unwind = this.results.get().clone(); - this.results.seek_after_assume_call_returns(terminator_loc); + this.results.seek_after_assume_success(terminator_loc); write_diff(w, this.results.analysis(), &state_on_unwind, this.results.get())?; write!(w, "") diff --git a/src/librustc_mir/dataflow/generic/mod.rs b/src/librustc_mir/dataflow/generic/mod.rs index 9a102c9a3d0..fb4b7b9c5be 100644 --- a/src/librustc_mir/dataflow/generic/mod.rs +++ b/src/librustc_mir/dataflow/generic/mod.rs @@ -191,6 +191,20 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> { return_place: &mir::Place<'tcx>, ); + /// Updates the current dataflow state with the effect of resuming from a `Yield` terminator. + /// + /// This is similar to `apply_call_return_effect` in that it only takes place after the + /// generator is resumed, not when it is dropped. + /// + /// By default, no effects happen. + fn apply_yield_resume_effect( + &self, + _state: &mut BitSet, + _resume_block: BasicBlock, + _resume_place: &mir::Place<'tcx>, + ) { + } + /// Updates the current dataflow state with the effect of taking a particular branch in a /// `SwitchInt` terminator. /// @@ -284,6 +298,15 @@ pub trait GenKillAnalysis<'tcx>: Analysis<'tcx> { return_place: &mir::Place<'tcx>, ); + /// See `Analysis::apply_yield_resume_effect`. + fn yield_resume_effect( + &self, + _trans: &mut BitSet, + _resume_block: BasicBlock, + _resume_place: &mir::Place<'tcx>, + ) { + } + /// See `Analysis::apply_discriminant_switch_effect`. fn discriminant_switch_effect( &self, @@ -347,6 +370,15 @@ where self.call_return_effect(state, block, func, args, return_place); } + fn apply_yield_resume_effect( + &self, + state: &mut BitSet, + resume_block: BasicBlock, + resume_place: &mir::Place<'tcx>, + ) { + self.yield_resume_effect(state, resume_block, resume_place); + } + fn apply_discriminant_switch_effect( &self, state: &mut BitSet, diff --git a/src/librustc_mir/dataflow/generic/tests.rs b/src/librustc_mir/dataflow/generic/tests.rs index 50d4bdb67f7..8f07a10e1b0 100644 --- a/src/librustc_mir/dataflow/generic/tests.rs +++ b/src/librustc_mir/dataflow/generic/tests.rs @@ -294,7 +294,7 @@ fn cursor_seek() { cursor.seek_after(call_terminator_loc); assert!(!cursor.get().contains(call_return_effect)); - cursor.seek_after_assume_call_returns(call_terminator_loc); + cursor.seek_after_assume_success(call_terminator_loc); assert!(cursor.get().contains(call_return_effect)); let every_target = || { @@ -310,7 +310,7 @@ fn cursor_seek() { BlockStart(block) => cursor.seek_to_block_start(block), Before(loc) => cursor.seek_before(loc), After(loc) => cursor.seek_after(loc), - AfterAssumeCallReturns(loc) => cursor.seek_after_assume_call_returns(loc), + AfterAssumeCallReturns(loc) => cursor.seek_after_assume_success(loc), } assert_eq!(cursor.get(), &cursor.analysis().expected_state_at_target(targ)); diff --git a/src/librustc_mir/dataflow/impls/storage_liveness.rs b/src/librustc_mir/dataflow/impls/storage_liveness.rs index fabe562e68a..5341d661b1d 100644 --- a/src/librustc_mir/dataflow/impls/storage_liveness.rs +++ b/src/librustc_mir/dataflow/impls/storage_liveness.rs @@ -161,11 +161,16 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, self.borrowed_locals.borrow().analysis().terminator_effect(trans, terminator, loc); match &terminator.kind { - TerminatorKind::Call { destination: Some((place, _)), .. } - | TerminatorKind::Yield { resume_arg: place, .. } => { + TerminatorKind::Call { destination: Some((place, _)), .. } => { trans.gen(place.local); } + // Note that we do *not* gen the `resume_arg` of `Yield` terminators. The reason for + // that is that a `yield` will return from the function, and `resume_arg` is written + // only when the generator is later resumed. Unlike `Call`, this doesn't require the + // place to have storage *before* the yield, only after. + TerminatorKind::Yield { .. } => {} + // Nothing to do for these. Match exhaustively so this fails to compile when new // variants are added. TerminatorKind::Call { destination: None, .. } @@ -230,6 +235,15 @@ impl<'mir, 'tcx> dataflow::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, ) { trans.gen(return_place.local); } + + fn yield_resume_effect( + &self, + trans: &mut BitSet, + _resume_block: BasicBlock, + resume_place: &mir::Place<'tcx>, + ) { + trans.gen(resume_place.local); + } } impl<'mir, 'tcx> MaybeRequiresStorage<'mir, 'tcx> { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 3107be1b622..ce17e8db3fd 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -506,7 +506,7 @@ fn locals_live_across_suspend_points( for (block, data) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { - let loc = Location { block: block, statement_index: data.statements.len() }; + let loc = Location { block, statement_index: data.statements.len() }; if !movable { // The `liveness` variable contains the liveness of MIR locals ignoring borrows. @@ -539,7 +539,7 @@ fn locals_live_across_suspend_points( let mut live_locals_here = storage_required; live_locals_here.intersect(&liveness.outs[block]); - // The generator argument is ignored + // The generator argument is ignored. live_locals_here.remove(self_arg()); debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here); From b26e27c5f3e7f24982f90183630b3fcffc3f7b8a Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 6 Mar 2020 00:32:21 +0100 Subject: [PATCH 0816/1250] Add test for generator sizes with resume arguments --- src/test/ui/generator/resume-arg-size.rs | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/test/ui/generator/resume-arg-size.rs diff --git a/src/test/ui/generator/resume-arg-size.rs b/src/test/ui/generator/resume-arg-size.rs new file mode 100644 index 00000000000..ffdc98d6f19 --- /dev/null +++ b/src/test/ui/generator/resume-arg-size.rs @@ -0,0 +1,28 @@ +#![feature(generators)] + +// run-pass + +use std::mem::size_of_val; + +fn main() { + // Generator taking a `Copy`able resume arg. + let gen_copy = |mut x: usize| { + loop { + drop(x); + x = yield; + } + }; + + // Generator taking a non-`Copy` resume arg. + let gen_move = |mut x: Box| { + loop { + drop(x); + x = yield; + } + }; + + // Neither of these generators have the resume arg live across the `yield`, so they should be + // 4 Bytes in size (only storing the discriminant) + assert_eq!(size_of_val(&gen_copy), 4); + assert_eq!(size_of_val(&gen_move), 4); +} From 9712fa405944cb8d5416556ac4b1f26365a10658 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Thu, 5 Mar 2020 21:53:26 -0500 Subject: [PATCH 0817/1250] Fix #69191 --- src/librustc_mir/interpret/place.rs | 6 ++++ ...sue-69191-ice-on-uninhabited-enum-field.rs | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4f96cb69891..33161dfa52c 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -410,6 +410,12 @@ where stride * field } layout::FieldPlacement::Union(count) => { + // This is a narrow bug-fix for rust-lang/rust#69191: if we are + // trying to access absent field of uninhabited variant, then + // signal UB (but don't ICE the compiler). + if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited { + throw_ub!(Unreachable); + } assert!( field < count as u64, "Tried to access field {} of union {:#?} with {} fields", diff --git a/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs new file mode 100644 index 00000000000..e22ddb0f5ae --- /dev/null +++ b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs @@ -0,0 +1,31 @@ +// build-pass +// +// (this is deliberately *not* check-pass; I have confirmed that the bug in +// question does not replicate when one uses `cargo check` alone.) + +pub enum Void {} + +enum UninhabitedUnivariant { _Variant(Void), } + +#[repr(C)] +enum UninhabitedUnivariantC { _Variant(Void), } + +#[repr(i32)] +enum UninhabitedUnivariant32 { _Variant(Void), } + +fn main() { + let _seed: UninhabitedUnivariant = None.unwrap(); + match _seed { + UninhabitedUnivariant::_Variant(_x) => {} + } + + let _seed: UninhabitedUnivariantC = None.unwrap(); + match _seed { + UninhabitedUnivariantC::_Variant(_x) => {} + } + + let _seed: UninhabitedUnivariant32 = None.unwrap(); + match _seed { + UninhabitedUnivariant32::_Variant(_x) => {} + } +} From 9afbf28ef607b769dc666d93f371459aa727f1d7 Mon Sep 17 00:00:00 2001 From: Dylan Nugent Date: Thu, 5 Mar 2020 21:55:36 -0500 Subject: [PATCH 0818/1250] Update deprecation version to 1.42 for Error::description Error::description is deprecated as of version 1.42, as the commit was not in the release for 1.41. --- src/libstd/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/error.rs b/src/libstd/error.rs index b480581e21b..3f6501bc7b4 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -135,7 +135,7 @@ pub trait Error: Debug + Display { /// } /// ``` #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_deprecated(since = "1.41.0", reason = "use the Display impl or to_string()")] + #[rustc_deprecated(since = "1.42.0", reason = "use the Display impl or to_string()")] fn description(&self) -> &str { "description() is deprecated; use Display" } From 3d146a3d1a58d35fb9198472ab2ccfb5eef9d1c9 Mon Sep 17 00:00:00 2001 From: Phoebe Bell Date: Sun, 9 Feb 2020 16:45:29 -0800 Subject: [PATCH 0819/1250] Document unsafe blocks in core::fmt --- src/libcore/fmt/float.rs | 6 ++++-- src/libcore/fmt/mod.rs | 18 ++++++++++++++++-- src/libcore/fmt/num.rs | 27 +++++++++++++++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 5ef673009bb..52d8349bc9a 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -2,8 +2,6 @@ use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp}; use crate::mem::MaybeUninit; use crate::num::flt2dec; -// ignore-tidy-undocumented-unsafe - // Don't inline this so callers don't use the stack space this function // requires unless they have to. #[inline(never)] @@ -16,6 +14,7 @@ fn float_to_decimal_common_exact( where T: flt2dec::DecodableFloat, { + // SAFETY: Possible undefined behavior, see FIXME(#53491) unsafe { let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 4]>::uninit(); @@ -48,6 +47,7 @@ fn float_to_decimal_common_shortest( where T: flt2dec::DecodableFloat, { + // SAFETY: Possible undefined behavior, see FIXME(#53491) unsafe { // enough for f32 and f64 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); @@ -103,6 +103,7 @@ fn float_to_exponential_common_exact( where T: flt2dec::DecodableFloat, { + // SAFETY: Possible undefined behavior, see FIXME(#53491) unsafe { let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64 let mut parts = MaybeUninit::<[flt2dec::Part<'_>; 6]>::uninit(); @@ -132,6 +133,7 @@ fn float_to_exponential_common_shortest( where T: flt2dec::DecodableFloat, { + // SAFETY: Possible undefined behavior, see FIXME(#53491) unsafe { // enough for f32 and f64 let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit(); diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 993b1073493..a7b34e5f2f1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1,7 +1,5 @@ //! Utilities for formatting and printing strings. -// ignore-tidy-undocumented-unsafe - #![stable(feature = "rust1", since = "1.0.0")] use crate::cell::{Cell, Ref, RefCell, RefMut, UnsafeCell}; @@ -271,6 +269,14 @@ impl<'a> ArgumentV1<'a> { #[doc(hidden)] #[unstable(feature = "fmt_internals", reason = "internal to format_args!", issue = "none")] pub fn new<'b, T>(x: &'b T, f: fn(&T, &mut Formatter<'_>) -> Result) -> ArgumentV1<'b> { + // SAFETY: `mem::transmute(x)` is safe because + // 1. `&'b T` keeps the lifetime it originated with `'b` + // (so as to not have an unbounded lifetime) + // 2. `&'b T` and `&'b Void` have the same memory layout + // (when `T` is `Sized`, as it is here) + // `mem::transmute(f)` is safe since `fn(&T, &mut Formatter<'_>) -> Result` + // and `fn(&Void, &mut Formatter<'_>) -> Result` have the same ABI + // (as long as `T` is `Sized`) unsafe { ArgumentV1 { formatter: mem::transmute(f), value: mem::transmute(x) } } } @@ -1389,6 +1395,14 @@ impl<'a> Formatter<'a> { fn write_formatted_parts(&mut self, formatted: &flt2dec::Formatted<'_>) -> Result { fn write_bytes(buf: &mut dyn Write, s: &[u8]) -> Result { + // SAFETY: This is used for `flt2dec::Part::Num` and `flt2dec::Part::Copy`. + // It's safe to use for `flt2dec::Part::Num` since every char `c` is between + // `b'0'` and `b'9'`, which means `s` is valid UTF-8. + // It's also probably safe in practice to use for `flt2dec::Part::Copy(buf)` + // since `buf` should be plain ASCII, but it's possible for someone to pass + // in a bad value for `buf` into `flt2dec::to_shortest_str` since it is a + // public function. + // FIXME: Determine whether this could result in UB. buf.write_str(unsafe { str::from_utf8_unchecked(s) }) } diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 5dfd3a8ecdb..7d77e33d743 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -1,7 +1,5 @@ //! Integer and floating-point number formatting -// ignore-tidy-undocumented-unsafe - use crate::fmt; use crate::mem::MaybeUninit; use crate::num::flt2dec; @@ -84,6 +82,8 @@ trait GenericRadix { } } let buf = &buf[curr..]; + // SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be + // valid UTF-8 let buf = unsafe { str::from_utf8_unchecked(slice::from_raw_parts(MaybeUninit::first_ptr(buf), buf.len())) }; @@ -189,11 +189,19 @@ static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\ macro_rules! impl_Display { ($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => { fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // 2^128 is about 3*10^38, so 39 gives an extra byte of space let mut buf = [MaybeUninit::::uninit(); 39]; let mut curr = buf.len() as isize; let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); let lut_ptr = DEC_DIGITS_LUT.as_ptr(); + // SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we + // can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show + // that it's OK to copy into `buf_ptr`, notice that at the beginning + // `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at + // each step this is kept the same as `n` is divided. Since `n` is always + // non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]` + // is safe to access. unsafe { // need at least 16 bits for the 4-characters-at-a-time to work. assert!(crate::mem::size_of::<$u>() >= 2); @@ -206,6 +214,10 @@ macro_rules! impl_Display { let d1 = (rem / 100) << 1; let d2 = (rem % 100) << 1; curr -= 4; + + // We are allowed to copy to `buf_ptr[curr..curr + 3]` here since + // otherwise `curr < 0`. But then `n` was originally at least `10000^10` + // which is `10^40 > 2^128 > n`. ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2); } @@ -232,6 +244,8 @@ macro_rules! impl_Display { } } + // SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid + // UTF-8 since `DEC_DIGITS_LUT` is let buf_slice = unsafe { str::from_utf8_unchecked( slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize)) @@ -304,6 +318,8 @@ macro_rules! impl_Exp { }; // 39 digits (worst case u128) + . = 40 + // Since `curr` always decreases by the number of digits copied, this means + // that `curr >= 0`. let mut buf = [MaybeUninit::::uninit(); 40]; let mut curr = buf.len() as isize; //index for buf let buf_ptr = MaybeUninit::first_ptr_mut(&mut buf); @@ -313,6 +329,8 @@ macro_rules! impl_Exp { while n >= 100 { let d1 = ((n % 100) as isize) << 1; curr -= 2; + // SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since + // `DEC_DIGITS_LUT` has a length of 200. unsafe { ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2); } @@ -324,6 +342,7 @@ macro_rules! impl_Exp { // decode second-to-last character if n >= 10 { curr -= 1; + // SAFETY: Safe since `40 > curr >= 0` (see comment) unsafe { *buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0'; } @@ -333,11 +352,13 @@ macro_rules! impl_Exp { // add decimal point iff >1 mantissa digit will be printed if exponent != trailing_zeros || added_precision != 0 { curr -= 1; + // SAFETY: Safe since `40 > curr >= 0` unsafe { *buf_ptr.offset(curr) = b'.'; } } + // SAFETY: Safe since `40 > curr >= 0` let buf_slice = unsafe { // decode last character curr -= 1; @@ -350,6 +371,8 @@ macro_rules! impl_Exp { // stores 'e' (or 'E') and the up to 2-digit exponent let mut exp_buf = [MaybeUninit::::uninit(); 3]; let exp_ptr = MaybeUninit::first_ptr_mut(&mut exp_buf); + // SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]` + // is contained within `exp_buf` since `len <= 3`. let exp_slice = unsafe { *exp_ptr.offset(0) = if upper {b'E'} else {b'e'}; let len = if exponent < 10 { From 40809b0585d5fe3ddad39fe00a608394ad1dec30 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Fri, 6 Mar 2020 08:48:58 +0100 Subject: [PATCH 0820/1250] Add FIXME --- src/librustc_mir/interpret/place.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 33161dfa52c..721766cc932 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -413,6 +413,8 @@ where // This is a narrow bug-fix for rust-lang/rust#69191: if we are // trying to access absent field of uninhabited variant, then // signal UB (but don't ICE the compiler). + // FIXME temporary hack to work around incoherence between + // layout computation and MIR building if field >= count as u64 && base.layout.abi == layout::Abi::Uninhabited { throw_ub!(Unreachable); } From b4422fb14b9e0c030e9da6fa943f0e4850b25a85 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 6 Mar 2020 06:43:11 -0500 Subject: [PATCH 0821/1250] Added oli's multivariant test case (alpha renaming the enum name itself). (And added Ralf's suggested test.) Added my own three-variant multi-variant as well. --- ...sue-69191-ice-on-uninhabited-enum-field.rs | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs index e22ddb0f5ae..5b7c7be42cf 100644 --- a/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs +++ b/src/test/ui/consts/issue-69191-ice-on-uninhabited-enum-field.rs @@ -5,13 +5,30 @@ pub enum Void {} -enum UninhabitedUnivariant { _Variant(Void), } +enum UninhabitedUnivariant { + _Variant(Void), +} + +enum UninhabitedMultivariant2 { + _Variant(Void), + _Warriont(Void), +} + +enum UninhabitedMultivariant3 { + _Variant(Void), + _Warriont(Void), + _Worrynot(Void), +} #[repr(C)] -enum UninhabitedUnivariantC { _Variant(Void), } +enum UninhabitedUnivariantC { + _Variant(Void), +} #[repr(i32)] -enum UninhabitedUnivariant32 { _Variant(Void), } +enum UninhabitedUnivariant32 { + _Variant(Void), +} fn main() { let _seed: UninhabitedUnivariant = None.unwrap(); @@ -19,6 +36,49 @@ fn main() { UninhabitedUnivariant::_Variant(_x) => {} } + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Variant(_x) => {} + UninhabitedMultivariant2::_Warriont(_x) => {} + } + + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Variant(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant2 = None.unwrap(); + match _seed { + UninhabitedMultivariant2::_Warriont(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Variant(_x) => {} + UninhabitedMultivariant3::_Warriont(_x) => {} + UninhabitedMultivariant3::_Worrynot(_x) => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Variant(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Warriont(_x) => {} + _ => {} + } + + let _seed: UninhabitedMultivariant3 = None.unwrap(); + match _seed { + UninhabitedMultivariant3::_Worrynot(_x) => {} + _ => {} + } + let _seed: UninhabitedUnivariantC = None.unwrap(); match _seed { UninhabitedUnivariantC::_Variant(_x) => {} From 13d5ee1c4f36cc05e87b23657fa934fe2d02f73c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Mar 2020 12:52:16 +0100 Subject: [PATCH 0822/1250] Cleanup E0390 explanation --- src/librustc_error_codes/error_codes/E0390.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0390.md b/src/librustc_error_codes/error_codes/E0390.md index 9d05740d6f5..ecc5b5568ad 100644 --- a/src/librustc_error_codes/error_codes/E0390.md +++ b/src/librustc_error_codes/error_codes/E0390.md @@ -1,4 +1,6 @@ -You tried to implement methods for a primitive type. Erroneous code example: +A method was implemented on a primitive type. + +Erroneous code example: ```compile_fail,E0390 struct Foo { From 44c97c43b5d3df5d76381f80fb8ad0042c6ccf55 Mon Sep 17 00:00:00 2001 From: Stein Somers Date: Fri, 6 Mar 2020 14:32:54 +0100 Subject: [PATCH 0823/1250] Fix & test leak of some BTreeMap nodes on panic during `into_iter` --- src/liballoc/collections/btree/map.rs | 11 ++++++++++- src/liballoc/tests/btree/map.rs | 26 +++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 8b9ffdfb49b..9da324ba2d4 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -1477,6 +1477,14 @@ impl Drop for IntoIter { // Continue the same loop we perform below. This only runs when unwinding, so we // don't have to care about panics this time (they'll abort). while let Some(_) = self.0.next() {} + + // No need to avoid the shared root, because the tree was definitely not empty. + unsafe { + let mut node = ptr::read(&self.0.front).into_node().forget_type(); + while let Some(parent) = node.deallocate_and_ascend() { + node = parent.into_node().forget_type(); + } + } } } @@ -1491,7 +1499,8 @@ impl Drop for IntoIter { if node.is_shared_root() { return; } - + // Most of the nodes have been deallocated while traversing + // but one pile from a leaf up to the root is left standing. while let Some(parent) = node.deallocate_and_ascend() { node = parent.into_node().forget_type(); } diff --git a/src/liballoc/tests/btree/map.rs b/src/liballoc/tests/btree/map.rs index fd07a4d3926..d05eec19346 100644 --- a/src/liballoc/tests/btree/map.rs +++ b/src/liballoc/tests/btree/map.rs @@ -1021,7 +1021,7 @@ fn test_split_off_large_random_sorted() { } #[test] -fn test_into_iter_drop_leak() { +fn test_into_iter_drop_leak_1() { static DROPS: AtomicU32 = AtomicU32::new(0); struct D; @@ -1045,3 +1045,27 @@ fn test_into_iter_drop_leak() { assert_eq!(DROPS.load(Ordering::SeqCst), 5); } + +#[test] +fn test_into_iter_drop_leak_2() { + let size = 12; // to obtain tree with 2 levels (having edges to leaf nodes) + static DROPS: AtomicU32 = AtomicU32::new(0); + static PANIC_POINT: AtomicU32 = AtomicU32::new(0); + + struct D; + impl Drop for D { + fn drop(&mut self) { + if DROPS.fetch_add(1, Ordering::SeqCst) == PANIC_POINT.load(Ordering::SeqCst) { + panic!("panic in `drop`"); + } + } + } + + for panic_point in vec![0, 1, size - 2, size - 1] { + DROPS.store(0, Ordering::SeqCst); + PANIC_POINT.store(panic_point, Ordering::SeqCst); + let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect(); + catch_unwind(move || drop(map.into_iter())).ok(); + assert_eq!(DROPS.load(Ordering::SeqCst), size); + } +} From 136ad015b6862274bf8c161dc5d2955409ed1465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 12:13:55 +0100 Subject: [PATCH 0824/1250] fix various typos --- config.toml.example | 2 +- src/bootstrap/compile.rs | 2 +- src/bootstrap/flags.rs | 2 +- src/ci/azure-pipelines/try.yml | 2 +- src/doc/rustdoc/src/unstable-features.md | 2 +- .../src/language-features/marker-trait-attr.md | 2 +- src/liballoc/collections/btree/node.rs | 2 +- src/liballoc/collections/linked_list.rs | 6 +++--- src/liballoc/collections/vec_deque.rs | 2 +- src/liballoc/vec.rs | 2 +- src/libcore/fmt/mod.rs | 2 +- src/libcore/mem/manually_drop.rs | 2 +- src/libcore/mem/mod.rs | 2 +- src/libcore/pin.rs | 4 ++-- src/libcore/ptr/const_ptr.rs | 8 ++++---- src/libcore/ptr/mod.rs | 2 +- src/libcore/ptr/mut_ptr.rs | 10 +++++----- src/libcore/tests/num/dec2flt/mod.rs | 2 +- src/libfmt_macros/lib.rs | 2 +- src/libproc_macro/bridge/client.rs | 4 ++-- src/librustc/hir/map/mod.rs | 2 +- src/librustc/mir/interpret/allocation.rs | 2 +- src/librustc/ty/layout.rs | 2 +- src/librustc/ty/print/mod.rs | 2 +- src/librustc/ty/print/pretty.rs | 6 +++--- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/librustc/ty/query/plumbing.rs | 2 +- src/librustc/ty/relate.rs | 2 +- src/librustc_ast/ast.rs | 4 ++-- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_builtin_macros/format.rs | 2 +- src/librustc_codegen_llvm/back/lto.rs | 4 ++-- src/librustc_codegen_llvm/back/profiling.rs | 4 ++-- src/librustc_codegen_llvm/debuginfo/metadata.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 2 +- src/librustc_codegen_ssa/traits/mod.rs | 2 +- src/librustc_codegen_utils/symbol_names.rs | 2 +- src/librustc_data_structures/graph/vec_graph/tests.rs | 2 +- src/librustc_data_structures/sharded.rs | 4 ++-- src/librustc_error_codes/error_codes/E0326.md | 2 +- src/librustc_error_codes/error_codes/E0591.md | 2 +- src/librustc_expand/mbe/macro_rules.rs | 2 +- src/librustc_expand/proc_macro.rs | 2 +- src/librustc_feature/active.rs | 2 +- src/librustc_feature/builtin_attrs.rs | 2 +- src/librustc_infer/infer/error_reporting/mod.rs | 2 +- .../infer/error_reporting/need_type_info.rs | 2 +- src/librustc_infer/infer/mod.rs | 4 ++-- src/librustc_infer/infer/opaque_types/mod.rs | 2 +- src/librustc_infer/infer/resolve.rs | 2 +- src/librustc_infer/traits/auto_trait.rs | 4 ++-- src/librustc_infer/traits/coherence.rs | 2 +- src/librustc_infer/traits/error_reporting/mod.rs | 2 +- src/librustc_infer/traits/object_safety.rs | 2 +- src/librustc_lexer/src/unescape.rs | 4 ++-- src/librustc_macros/src/query.rs | 4 ++-- src/librustc_metadata/locator.rs | 2 +- src/librustc_metadata/rmeta/mod.rs | 2 +- .../borrow_check/diagnostics/conflict_errors.rs | 2 +- .../borrow_check/diagnostics/mutability_errors.rs | 2 +- src/librustc_mir/borrow_check/invalidation.rs | 2 +- src/librustc_mir/borrow_check/member_constraints.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/type_check/mod.rs | 2 +- src/librustc_mir/const_eval/eval_queries.rs | 4 ++-- src/librustc_mir/interpret/eval_context.rs | 2 +- src/librustc_mir/interpret/machine.rs | 2 +- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/interpret/snapshot.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- src/librustc_mir/util/pretty.rs | 2 +- src/librustc_mir_build/hair/pattern/_match.rs | 2 +- src/librustc_parse/config.rs | 2 +- src/librustc_parse/parser/attr.rs | 2 +- src/librustc_parse/parser/diagnostics.rs | 2 +- src/librustc_parse/parser/expr.rs | 2 +- src/librustc_passes/region.rs | 2 +- src/librustc_passes/stability.rs | 2 +- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/imports.rs | 2 +- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 2 +- src/librustc_target/abi/call/mod.rs | 6 +++--- src/librustc_target/abi/mod.rs | 2 +- src/librustc_target/spec/i686_unknown_uefi.rs | 4 ++-- src/librustc_target/spec/nvptx64_nvidia_cuda.rs | 4 ++-- src/librustc_typeck/astconv.rs | 4 ++-- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 8 ++++---- src/librustc_typeck/check/pat.rs | 4 ++-- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/collect.rs | 2 +- src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/html/highlight.rs | 2 +- src/librustdoc/html/render.rs | 2 +- src/libstd/net/ip.rs | 2 +- src/libstd/os/linux/fs.rs | 2 +- src/libstd/sync/mpsc/spsc_queue.rs | 2 +- src/libstd/sys/sgx/abi/usercalls/alloc.rs | 2 +- src/libstd/sys/unix/mod.rs | 2 +- src/libstd/sys/vxworks/mod.rs | 2 +- src/libtest/cli.rs | 2 +- src/libtest/options.rs | 2 +- src/libtest/test_result.rs | 2 +- src/test/incremental/cyclic-trait-hierarchy.rs | 2 +- .../thinlto/cgu_invalidated_when_import_added.rs | 2 +- .../thinlto/cgu_invalidated_when_import_removed.rs | 2 +- src/test/ui/consts/const-int-arithmetic-overflow.rs | 2 +- src/test/ui/definition-reachable/nested-fn.rs | 2 +- .../impl-trait/must_outlive_least_region_or_bound.rs | 2 +- src/test/ui/mir/mir_assign_eval_order.rs | 2 +- src/test/ui/nll/issue-54556-used-vs-unused-tails.rs | 2 +- src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs | 2 +- src/test/ui/type-alias-impl-trait/issue-65918.rs | 2 +- .../type-alias-impl-trait/issue-67844-nested-opaque.rs | 2 +- .../issue-52082-type-param-shadows-existing-type.rs | 2 +- src/test/ui/wf/wf-array-elem-sized.rs | 2 +- src/tools/compiletest/src/errors.rs | 2 +- src/tools/compiletest/src/runtest.rs | 2 +- src/tools/tidy/src/pal.rs | 2 +- 122 files changed, 153 insertions(+), 153 deletions(-) diff --git a/config.toml.example b/config.toml.example index 9b7327ea69e..ce21b63467f 100644 --- a/config.toml.example +++ b/config.toml.example @@ -315,7 +315,7 @@ # `0` - no debug info # `1` - line tables only # `2` - full debug info with variable and type information -# Can be overriden for specific subsets of Rust code (rustc, std or tools). +# Can be overridden for specific subsets of Rust code (rustc, std or tools). # Debuginfo for tests run with compiletest is not controlled by this option # and needs to be enabled separately with `debuginfo-level-tests`. #debuginfo-level = if debug { 2 } else { 0 } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 7dded96e18e..65a00db3394 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -141,7 +141,7 @@ fn copy_third_party_objects( copy_and_stamp(&srcdir, "crt1.o"); } - // Copies libunwind.a compiled to be linked wit x86_64-fortanix-unknown-sgx. + // Copies libunwind.a compiled to be linked with x86_64-fortanix-unknown-sgx. // // This target needs to be linked to Fortanix's port of llvm's libunwind. // libunwind requires support for rwlock and printing to stderr, diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 516be6a30c2..0b2ab6bbbc0 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -33,7 +33,7 @@ pub struct Flags { pub rustc_error_format: Option, pub dry_run: bool, - // This overrides the deny-warnings configuation option, + // This overrides the deny-warnings configuration option, // which passes -Dwarnings to the compiler invocations. // // true => deny, false => warn diff --git a/src/ci/azure-pipelines/try.yml b/src/ci/azure-pipelines/try.yml index f8ddf0eb46c..a29d6f9ae1e 100644 --- a/src/ci/azure-pipelines/try.yml +++ b/src/ci/azure-pipelines/try.yml @@ -20,7 +20,7 @@ jobs: # The macOS and Windows builds here are currently disabled due to them not being # overly necessary on `try` builds. We also don't actually have anything that -# consumes the artifacts currently. Perhaps one day we can reenable, but for now +# consumes the artifacts currently. Perhaps one day we can re-enable, but for now # it helps free up capacity on Azure. # - job: macOS # timeoutInMinutes: 600 diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index a48526d39fd..22d2e297da3 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -453,7 +453,7 @@ override `ignore`. ### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it -Using thses options looks like this: +Using these options looks like this: ```bash $ rustdoc src/lib.rs -Z unstable-options --runtool runner --runtool-arg --do-thing --runtool-arg --do-other-thing diff --git a/src/doc/unstable-book/src/language-features/marker-trait-attr.md b/src/doc/unstable-book/src/language-features/marker-trait-attr.md index dedc7d3015d..be350cd6169 100644 --- a/src/doc/unstable-book/src/language-features/marker-trait-attr.md +++ b/src/doc/unstable-book/src/language-features/marker-trait-attr.md @@ -21,7 +21,7 @@ when they'd need to do the same thing for every type anyway). impl CheapToClone for T {} -// These could potentally overlap with the blanket implementation above, +// These could potentially overlap with the blanket implementation above, // so are only allowed because CheapToClone is a marker trait. impl CheapToClone for (T, U) {} impl CheapToClone for std::ops::Range {} diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 362755f8b7f..edeb87a908d 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -306,7 +306,7 @@ impl Root { /// `NodeRef` could be pointing to either type of node. /// Note that in case of a leaf node, this might still be the shared root! /// Only turn this into a `LeafNode` reference if you know it is not the shared root! -/// Shared references must be dereferencable *for the entire size of their pointee*, +/// Shared references must be dereferenceable *for the entire size of their pointee*, /// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior. /// Turning this into a `NodeHeader` reference is always safe. pub struct NodeRef { diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index a9b4e3e4706..e10d0db9d9a 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -841,10 +841,10 @@ impl LinkedList { /// d.push_front(2); /// d.push_front(3); /// - /// let mut splitted = d.split_off(2); + /// let mut split = d.split_off(2); /// - /// assert_eq!(splitted.pop_front(), Some(1)); - /// assert_eq!(splitted.pop_front(), None); + /// assert_eq!(split.pop_front(), Some(1)); + /// assert_eq!(split.pop_front(), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn split_off(&mut self, at: usize) -> LinkedList { diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 85d1d98b8a9..9d56f17700a 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -2132,7 +2132,7 @@ impl VecDeque { // Safety: the following two methods require that the rotation amount // be less than half the length of the deque. // - // `wrap_copy` requres that `min(x, cap() - x) + copy_len <= cap()`, + // `wrap_copy` requires that `min(x, cap() - x) + copy_len <= cap()`, // but than `min` is never more than half the capacity, regardless of x, // so it's sound to call here because we're calling with something // less than half the length, which is never above half the capacity. diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3fd7be06fd4..05f3dd28e98 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2894,7 +2894,7 @@ where /// The filter test predicate. pred: F, /// A flag that indicates a panic has occurred in the filter test prodicate. - /// This is used as a hint in the drop implmentation to prevent consumption + /// This is used as a hint in the drop implementation to prevent consumption /// of the remainder of the `DrainFilter`. Any unprocessed items will be /// backshifted in the `vec`, but no further items will be dropped or /// tested by the filter predicate. diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 993b1073493..b13e9bcc6b4 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -255,7 +255,7 @@ pub struct ArgumentV1<'a> { formatter: fn(&Opaque, &mut Formatter<'_>) -> Result, } -// This gurantees a single stable value for the function pointer associated with +// This guarantees a single stable value for the function pointer associated with // indices/counts in the formatting infrastructure. // // Note that a function defined as such would not be correct as functions are diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 4c3b81ea5ec..9e5c2b10d0d 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -93,7 +93,7 @@ impl ManuallyDrop { /// Instead of using [`ManuallyDrop::drop`] to manually drop the value, /// you can use this method to take the value and use it however desired. /// - /// Whenever possible, it is preferrable to use [`into_inner`][`ManuallyDrop::into_inner`] + /// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`] /// instead, which prevents duplicating the content of the `ManuallyDrop`. /// /// # Safety diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 1120d6d4bc5..90144d11dc9 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -91,7 +91,7 @@ pub use crate::intrinsics::transmute; /// Using `ManuallyDrop` here has two advantages: /// /// * We do not "touch" `v` after disassembling it. For some types, operations -/// such as passing ownership (to a funcion like `mem::forget`) requires them to actually +/// such as passing ownership (to a function like `mem::forget`) requires them to actually /// be fully owned right now; that is a promise we do not want to make here as we are /// in the process of transferring ownership to the new `String` we are building. /// * In case of an unexpected panic, `ManuallyDrop` is not dropped, but if the panic diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs index 676d2c784ac..774ecd997c2 100644 --- a/src/libcore/pin.rs +++ b/src/libcore/pin.rs @@ -312,7 +312,7 @@ //! //! ## Examples //! -//! For a type like [`Vec`], both possibilites (structural pinning or not) make sense. +//! For a type like [`Vec`], both possibilities (structural pinning or not) make sense. //! A [`Vec`] with structural pinning could have `get_pin`/`get_pin_mut` methods to get //! pinned references to elements. However, it could *not* allow calling //! [`pop`][Vec::pop] on a pinned [`Vec`] because that would move the (structurally pinned) @@ -539,7 +539,7 @@ impl Pin

{ /// ``` /// A value, once pinned, must remain pinned forever (unless its type implements `Unpin`). /// - /// Similarily, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be + /// Similarly, calling `Pin::new_unchecked` on an `Rc` is unsafe because there could be /// aliases to the same data that are not subject to the pinning restrictions: /// ``` /// use std::rc::Rc; diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs index fc3c02e1f06..a540016854d 100644 --- a/src/libcore/ptr/const_ptr.rs +++ b/src/libcore/ptr/const_ptr.rs @@ -53,7 +53,7 @@ impl *const T { /// all of the following is true: /// - it is properly aligned /// - it must point to an initialized instance of T; in particular, the pointer must be - /// "dereferencable" in the sense defined [here]. + /// "dereferenceable" in the sense defined [here]. /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until @@ -183,7 +183,7 @@ impl *const T { /// within the same allocated object: [`offset`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -480,7 +480,7 @@ impl *const T { /// within the same allocated object: [`add`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_add` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -535,7 +535,7 @@ impl *const T { /// within the same allocated object: [`sub`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index fcfa98d8507..72c46f58fcc 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -19,7 +19,7 @@ //! * All pointers (except for the null pointer) are valid for all operations of //! [size zero][zst]. //! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer -//! be *dereferencable*: the memory range of the given size starting at the pointer must all be +//! be *dereferenceable*: the memory range of the given size starting at the pointer must all be //! within the bounds of a single allocated object. Note that in Rust, //! every (stack-allocated) variable is considered a separate allocated object. //! * All accesses performed by functions in this module are *non-atomic* in the sense diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs index 4bc0a3e9faa..01d830ca186 100644 --- a/src/libcore/ptr/mut_ptr.rs +++ b/src/libcore/ptr/mut_ptr.rs @@ -49,7 +49,7 @@ impl *mut T { /// memory. /// /// When calling this method, you have to ensure that if the pointer is - /// non-NULL, then it is properly aligned, dereferencable (for the whole + /// non-NULL, then it is properly aligned, dereferenceable (for the whole /// size of `T`) and points to an initialized instance of `T`. This applies /// even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until @@ -176,7 +176,7 @@ impl *mut T { /// within the same allocated object: [`offset`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_offset` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -224,7 +224,7 @@ impl *mut T { /// all of the following is true: /// - it is properly aligned /// - it must point to an initialized instance of T; in particular, the pointer must be - /// "dereferencable" in the sense defined [here]. + /// "dereferenceable" in the sense defined [here]. /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until @@ -526,7 +526,7 @@ impl *mut T { /// within the same allocated object: [`add`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_add` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. @@ -581,7 +581,7 @@ impl *mut T { /// within the same allocated object: [`sub`] is immediate Undefined Behavior when /// crossing object boundaries; `wrapping_sub` produces a pointer but still leads /// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized - /// better and is thus preferrable in performance-sensitive code. + /// better and is thus preferable in performance-sensitive code. /// /// If you need to cross object boundaries, cast the pointer to an integer and /// do the arithmetic there. diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index a1fa5556ae5..509097fdb54 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -44,7 +44,7 @@ fn ordinary() { #[test] fn special_code_paths() { test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand - test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32) + test_literal!(101e-33); // Triggers the tricky underflow case in algorithm (for f32) test_literal!(1e23); // Triggers AlgorithmR test_literal!(2075e23); // Triggers another path through AlgorithmR test_literal!(8713e-23); // ... and yet another. diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 9ca7eee999f..e138503b508 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -176,7 +176,7 @@ pub struct Parser<'a> { skips: Vec, /// Span of the last opening brace seen, used for error reporting last_opening_brace: Option, - /// Wether the source string is comes from `println!` as opposed to `format!` or `print!` + /// Whether the source string is comes from `println!` as opposed to `format!` or `print!` append_newline: bool, } diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index dd948025c91..088db92253a 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -15,7 +15,7 @@ macro_rules! define_handles { } impl HandleCounters { - // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of + // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of // a wrapper `fn` pointer, once `const fn` can reference `static`s. extern "C" fn get() -> &'static Self { static COUNTERS: HandleCounters = HandleCounters { @@ -334,7 +334,7 @@ impl Bridge<'_> { #[repr(C)] #[derive(Copy, Clone)] pub struct Client { - // FIXME(eddyb) use a reference to the `static COUNTERS`, intead of + // FIXME(eddyb) use a reference to the `static COUNTERS`, instead of // a wrapper `fn` pointer, once `const fn` can reference `static`s. pub(super) get_handle_counters: extern "C" fn() -> &'static HandleCounters, pub(super) run: extern "C" fn(Bridge<'_>, F) -> Buffer, diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index bd26e02efb7..0f129904b43 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -653,7 +653,7 @@ impl<'hir> Map<'hir> { } } - /// Wether `hir_id` corresponds to a `mod` or a crate. + /// Whether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { match self.lookup(hir_id) { Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) diff --git a/src/librustc/mir/interpret/allocation.rs b/src/librustc/mir/interpret/allocation.rs index c8d35db0ade..546ba586d30 100644 --- a/src/librustc/mir/interpret/allocation.rs +++ b/src/librustc/mir/interpret/allocation.rs @@ -610,7 +610,7 @@ impl Allocation { // a naive undef mask copying algorithm would repeatedly have to read the undef mask from // the source and write it to the destination. Even if we optimized the memory accesses, // we'd be doing all of this `repeat` times. - // Therefor we precompute a compressed version of the undef mask of the source value and + // Therefore we precompute a compressed version of the undef mask of the source value and // then write it back `repeat` times without computing any more information from the source. // A precomputed cache for ranges of defined/undefined bits diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 7a5a417919d..e257b48f111 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2579,7 +2579,7 @@ where if let Some(kind) = pointee.safe { attrs.pointee_align = Some(pointee.align); - // `Box` (`UniqueBorrowed`) are not necessarily dereferencable + // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable // for the entire duration of the function as they can be deallocated // any time. Set their valid size to 0. attrs.pointee_size = match kind { diff --git a/src/librustc/ty/print/mod.rs b/src/librustc/ty/print/mod.rs index 3ade9661917..8d784833bd3 100644 --- a/src/librustc/ty/print/mod.rs +++ b/src/librustc/ty/print/mod.rs @@ -97,7 +97,7 @@ pub trait Printer<'tcx>: Sized { args: &[GenericArg<'tcx>], ) -> Result; - // Defaults (should not be overriden): + // Defaults (should not be overridden): fn default_print_def_path( self, diff --git a/src/librustc/ty/print/pretty.rs b/src/librustc/ty/print/pretty.rs index 4829955cb70..05dcc9e85ac 100644 --- a/src/librustc/ty/print/pretty.rs +++ b/src/librustc/ty/print/pretty.rs @@ -221,7 +221,7 @@ pub trait PrettyPrinter<'tcx>: /// This is typically the case for all non-`'_` regions. fn region_should_not_be_omitted(&self, region: ty::Region<'_>) -> bool; - // Defaults (should not be overriden): + // Defaults (should not be overridden): /// If possible, this returns a global path resolving to `def_id` that is visible /// from at least one local module, and returns `true`. If the crate defining `def_id` is @@ -236,7 +236,7 @@ pub trait PrettyPrinter<'tcx>: /// post-process it into the valid and visible version that /// accounts for re-exports. /// - /// This method should only be callled by itself or + /// This method should only be called by itself or /// `try_print_visible_def_path`. /// /// `callers` is a chain of visible_parent's leading to `def_id`, @@ -685,7 +685,7 @@ pub trait PrettyPrinter<'tcx>: if self.tcx().sess.verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.val { - // do not try to evalute unevaluated constants. If we are const evaluating an + // do not try to evaluate unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!(write("_")); diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 5e36e4df698..9c1db7c5f2b 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -425,7 +425,7 @@ impl<'sess> OnDiskCache<'sess> { //- DECODING ------------------------------------------------------------------- -/// A decoder that can read fro the incr. comp. cache. It is similar to the one +/// A decoder that can read from the incr. comp. cache. It is similar to the one /// we use for crate metadata decoding in that it can rebase spans and eventually /// will also handle things that contain `Ty` instances. struct CacheDecoder<'a, 'tcx> { diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index a61256b9fcb..c94909549df 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1053,7 +1053,7 @@ macro_rules! define_queries_inner { impl TyCtxt<$tcx> { /// Returns a transparent wrapper for `TyCtxt`, which ensures queries - /// are executed instead of just returing their results. + /// are executed instead of just returning their results. #[inline(always)] pub fn ensure(self) -> TyCtxtEnsure<$tcx> { TyCtxtEnsure { diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 3b9df72266f..8da82a80dd3 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -72,7 +72,7 @@ pub trait TypeRelation<'tcx>: Sized { b: &T, ) -> RelateResult<'tcx, T>; - // Overrideable relations. You shouldn't typically call these + // Overridable relations. You shouldn't typically call these // directly, instead call `relate()`, which in turn calls // these. This is both more uniform but also allows us to add // additional hooks for other types in the future if needed diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 7cc045ef344..88a96dc6c69 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -1078,7 +1078,7 @@ impl Expr { // If binary operator is `Add` and both `lhs` and `rhs` are trait bounds, // then type of result is trait object. - // Othewise we don't assume the result type. + // Otherwise we don't assume the result type. ExprKind::Binary(binop, lhs, rhs) if binop.node == BinOpKind::Add => { if let (Some(lhs), Some(rhs)) = (lhs.to_bound(), rhs.to_bound()) { TyKind::TraitObject(vec![lhs, rhs], TraitObjectSyntax::None) @@ -2089,7 +2089,7 @@ impl Async { if let Async::Yes { .. } = self { true } else { false } } - /// In ths case this is an `async` return, the `NodeId` for the generated `impl Trait` item. + /// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item. pub fn opt_return_id(self) -> Option { match self { Async::Yes { return_impl_trait_id, .. } => Some(return_impl_trait_id), diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index df71b05ac2c..dd9526ccee4 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -1096,7 +1096,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { match arg { ast::GenericArg::Lifetime(lt) => GenericArg::Lifetime(self.lower_lifetime(<)), ast::GenericArg::Type(ty) => { - // We parse const arguments as path types as we cannot distiguish them durring + // We parse const arguments as path types as we cannot distinguish them during // parsing. We try to resolve that ambiguity by attempting resolution in both the // type and value namespaces. If we resolved the path in the value namespace, we // transform it into a generic const argument. diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index d6b8b8cafb7..1baec5eafe6 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -904,7 +904,7 @@ pub fn expand_preparsed_format_args( }; /// Finds the indices of all characters that have been processed and differ between the actual - /// written code (code snippet) and the `InternedString` that get's processed in the `Parser` + /// written code (code snippet) and the `InternedString` that gets processed in the `Parser` /// in order to properly synthethise the intra-string `Span`s for error diagnostics. fn find_skips(snippet: &str, is_raw: bool) -> Vec { let mut eat_ws = false; diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index a39c25f6693..310cae978bf 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -504,7 +504,7 @@ fn thin_lto( // // This strategy means we can always save the computed imports as // canon: when we reuse the post-ThinLTO version, condition (3.) - // ensures that the curent import set is the same as the previous + // ensures that the current import set is the same as the previous // one. (And of course, when we don't reuse the post-ThinLTO // version, the current import set *is* the correct one, since we // are doing the ThinLTO in this current compilation cycle.) @@ -538,7 +538,7 @@ fn thin_lto( })); } - // Save the curent ThinLTO import information for the next compilation + // Save the current ThinLTO import information for the next compilation // session, overwriting the previous serialized imports (if any). if let Some(path) = import_map_path { if let Err(err) = curr_import_map.save_to_file(&path) { diff --git a/src/librustc_codegen_llvm/back/profiling.rs b/src/librustc_codegen_llvm/back/profiling.rs index d56ddac699b..2741f7d848e 100644 --- a/src/librustc_codegen_llvm/back/profiling.rs +++ b/src/librustc_codegen_llvm/back/profiling.rs @@ -9,8 +9,8 @@ fn llvm_args_to_string_id(profiler: &SelfProfiler, pass_name: &str, ir_name: &st let mut components = vec![StringComponent::Ref(pass_name)]; // handle that LazyCallGraph::SCC is a comma separated list within parentheses let parentheses: &[_] = &['(', ')']; - let trimed = ir_name.trim_matches(parentheses); - for part in trimed.split(", ") { + let trimmed = ir_name.trim_matches(parentheses); + for part in trimmed.split(", ") { let demangled_ir_name = rustc_demangle::demangle(part).to_string(); let ir_name = profiler.get_or_alloc_cached_string(demangled_ir_name); components.push(StringComponent::Value(SEPARATOR_BYTE)); diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 3916653eb1d..cc9a51cf26b 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -637,7 +637,7 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp unsafe { // The choice of type here is pretty arbitrary - // anything reading the debuginfo for a recursive - // type is going to see *somthing* weird - the only + // type is going to see *something* weird - the only // question is what exactly it will see. let (size, align) = cx.size_and_align_of(t); llvm::LLVMRustDIBuilderCreateBasicType( diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index b313bf57d4a..3afa4758253 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -736,7 +736,7 @@ fn execute_work_item( } } -// Actual LTO type we end up chosing based on multiple factors. +// Actual LTO type we end up choosing based on multiple factors. enum ComputedLtoType { No, Thin, diff --git a/src/librustc_codegen_ssa/traits/mod.rs b/src/librustc_codegen_ssa/traits/mod.rs index b8afadaadef..d03ff8d4d37 100644 --- a/src/librustc_codegen_ssa/traits/mod.rs +++ b/src/librustc_codegen_ssa/traits/mod.rs @@ -8,7 +8,7 @@ //! actual codegen, while the builder stores the information about the function during codegen and //! is used to produce the instructions of the backend IR. //! -//! Finaly, a third `Backend` structure has to implement methods related to how codegen information +//! Finally, a third `Backend` structure has to implement methods related to how codegen information //! is passed to the backend, especially for asynchronous compilation. //! //! The traits contain associated types that are backend-specific, such as the backend's value or diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index 6713459f627..cfde09fad62 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -185,7 +185,7 @@ fn compute_symbol_name( // // * On the wasm32 targets there is a bug (or feature) in LLD [1] where the // same-named symbol when imported from different wasm modules will get - // hooked up incorectly. As a result foreign symbols, on the wasm target, + // hooked up incorrectly. As a result foreign symbols, on the wasm target, // with a wasm import module, get mangled. Additionally our codegen will // deduplicate symbols based purely on the symbol name, but for wasm this // isn't quite right because the same-named symbol on wasm can come from diff --git a/src/librustc_data_structures/graph/vec_graph/tests.rs b/src/librustc_data_structures/graph/vec_graph/tests.rs index 1db8bd4b102..c8f97926717 100644 --- a/src/librustc_data_structures/graph/vec_graph/tests.rs +++ b/src/librustc_data_structures/graph/vec_graph/tests.rs @@ -23,7 +23,7 @@ fn num_nodes() { } #[test] -fn succesors() { +fn successors() { let graph = create_graph(); assert_eq!(graph.successors(0), &[1]); assert_eq!(graph.successors(1), &[2, 3]); diff --git a/src/librustc_data_structures/sharded.rs b/src/librustc_data_structures/sharded.rs index 15d1e2dd0b6..d08d46a7414 100644 --- a/src/librustc_data_structures/sharded.rs +++ b/src/librustc_data_structures/sharded.rs @@ -13,7 +13,7 @@ struct CacheAligned(T); #[cfg(parallel_compiler)] // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700, // but this should be tested on higher core count CPUs. How the `Sharded` type gets used -// may also affect the ideal nunber of shards. +// may also affect the ideal number of shards. const SHARD_BITS: usize = 5; #[cfg(not(parallel_compiler))] @@ -41,7 +41,7 @@ impl Sharded { let mut values: SmallVec<[_; SHARDS]> = (0..SHARDS).map(|_| CacheAligned(Lock::new(value()))).collect(); - // Create an unintialized array + // Create an uninitialized array let mut shards: mem::MaybeUninit<[CacheAligned>; SHARDS]> = mem::MaybeUninit::uninit(); diff --git a/src/librustc_error_codes/error_codes/E0326.md b/src/librustc_error_codes/error_codes/E0326.md index 3d357819c7f..bc522e9cf40 100644 --- a/src/librustc_error_codes/error_codes/E0326.md +++ b/src/librustc_error_codes/error_codes/E0326.md @@ -1,4 +1,4 @@ -An implementation of a trait doesn't match the type contraint. +An implementation of a trait doesn't match the type constraint. Erroneous code example: diff --git a/src/librustc_error_codes/error_codes/E0591.md b/src/librustc_error_codes/error_codes/E0591.md index 782d4cf29c3..7f68815b1c2 100644 --- a/src/librustc_error_codes/error_codes/E0591.md +++ b/src/librustc_error_codes/error_codes/E0591.md @@ -54,7 +54,7 @@ This pattern should be rewritten. There are a few possible ways to do this: - change the original fn declaration to match the expected signature, and do the cast in the fn body (the preferred option) -- cast the fn item fo a fn pointer before calling transmute, as shown here: +- cast the fn item of a fn pointer before calling transmute, as shown here: ``` # extern "C" fn foo(_: Box) {} diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index b02c9350395..51b172a2114 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -991,7 +991,7 @@ fn token_can_be_followed_by_any(tok: &mbe::TokenTree) -> bool { if let mbe::TokenTree::MetaVarDecl(_, _, frag_spec) = *tok { frag_can_be_followed_by_any(frag_spec.name) } else { - // (Non NT's can always be followed by anthing in matchers.) + // (Non NT's can always be followed by anything in matchers.) true } } diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index 84a546345bb..5404ee192a6 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -133,7 +133,7 @@ impl MultiItemModifier for ProcMacroDerive { }; let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparseable tokens"; + let msg = "proc-macro derive produced unparsable tokens"; let mut parser = rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 6517a22701b..642a3bf8964 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -387,7 +387,7 @@ declare_features! ( /// Allows defining `trait X = A + B;` alias items. (active, trait_alias, "1.24.0", Some(41517), None), - /// Allows infering `'static` outlives requirements (RFC 2093). + /// Allows inferring `'static` outlives requirements (RFC 2093). (active, infer_static_outlives_requirements, "1.26.0", Some(54185), None), /// Allows accessing fields of unions inside `const` functions. diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index c140adf64d5..9810c0cfe66 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -175,7 +175,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ // Stable attributes: // ========================================================================== - // Condtional compilation: + // Conditional compilation: ungated!(cfg, Normal, template!(List: "predicate")), ungated!(cfg_attr, Normal, template!(List: "predicate, attr1, attr2, ...")), diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index bd133738db7..40b493de9f4 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -1819,7 +1819,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { "{} may not live long enough", labeled_user_string ); - // Explicitely use the name instead of `sub`'s `Display` impl. The `Display` impl + // Explicitly use the name instead of `sub`'s `Display` impl. The `Display` impl // for the bound is not suitable for suggestions when `-Zverbose` is set because it // uses `Debug` output, so we handle it specially here so that suggestions are // always correct. diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index a1e6a0a325a..285f0c9cf51 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -391,7 +391,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.span_label(pattern.span, msg); } else if let Some(e) = local_visitor.found_method_call { if let ExprKind::MethodCall(segment, ..) = &e.kind { - // Suggest specifiying type params or point out the return type of the call: + // Suggest specifying type params or point out the return type of the call: // // error[E0282]: type annotations needed // --> $DIR/type-annotations-needed-expr.rs:2:39 diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 6adddf2500c..938a0e7ab39 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -1667,14 +1667,14 @@ impl<'a, 'tcx> ShallowResolver<'a, 'tcx> { ty::IntVar(v) => { // If inlined_probe_value returns a value it's always a - // `ty::Int(_)` or `ty::UInt(_)`, which nevers matches a + // `ty::Int(_)` or `ty::UInt(_)`, which never matches a // `ty::Infer(_)`. self.infcx.inner.borrow_mut().int_unification_table.inlined_probe_value(v).is_some() } ty::FloatVar(v) => { // If inlined_probe_value returns a value it's always a - // `ty::Float(_)`, which nevers matches a `ty::Infer(_)`. + // `ty::Float(_)`, which never matches a `ty::Infer(_)`. // // Not `inlined_probe_value(v)` because this call site is colder. self.infcx.inner.borrow_mut().float_unification_table.probe_value(v).is_some() diff --git a/src/librustc_infer/infer/opaque_types/mod.rs b/src/librustc_infer/infer/opaque_types/mod.rs index 06d45690e41..4d264008ee3 100644 --- a/src/librustc_infer/infer/opaque_types/mod.rs +++ b/src/librustc_infer/infer/opaque_types/mod.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// ``` /// /// Here we would report a more complex "in constraint", like `'r - /// in ['a, 'b, 'static]` (where `'r` is some regon appearing in + /// in ['a, 'b, 'static]` (where `'r` is some region appearing in /// the hidden type). /// /// # Constrain regions, not the hidden concrete type diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index e2207d08ee6..6bf123114dc 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -169,7 +169,7 @@ where } // N.B. This type is not public because the protocol around checking the -// `err` field is not enforcable otherwise. +// `err` field is not enforceable otherwise. struct FullTypeResolver<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, err: Option>, diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs index 3166fe06576..39be8fc1c0f 100644 --- a/src/librustc_infer/traits/auto_trait.rs +++ b/src/librustc_infer/traits/auto_trait.rs @@ -455,7 +455,7 @@ impl AutoTraitFinder<'tcx> { // predicate has some other kind of region. An region // variable isn't something we can actually display to a user, // so we choose their new predicate (which doesn't have a region - // varaible). + // variable). // // In both cases, we want to remove the old predicate, // from `user_computed_preds`, and replace it with the new @@ -701,7 +701,7 @@ impl AutoTraitFinder<'tcx> { // some subobligations. We then process these subobligations // like any other generated sub-obligations. // - // 3. We receieve an 'ambiguous' result (Ok(None)) + // 3. We receive an 'ambiguous' result (Ok(None)) // If we were actually trying to compile a crate, // we would need to re-process this obligation later. // However, all we care about is finding out what bounds diff --git a/src/librustc_infer/traits/coherence.rs b/src/librustc_infer/traits/coherence.rs index 0dec5ae6da5..15c5f4d402a 100644 --- a/src/librustc_infer/traits/coherence.rs +++ b/src/librustc_infer/traits/coherence.rs @@ -505,7 +505,7 @@ fn ty_is_non_local_constructor<'tcx>(ty: Ty<'tcx>, in_crate: InCrate) -> Option< // // We choose to treat all opaque types as non-local, even // those that appear within the same crate. This seems - // somewhat suprising at first, but makes sense when + // somewhat surprising at first, but makes sense when // you consider that opaque types are supposed to hide // the underlying type *within the same crate*. When an // opaque type is used from outside the module diff --git a/src/librustc_infer/traits/error_reporting/mod.rs b/src/librustc_infer/traits/error_reporting/mod.rs index 63c3f827c2e..10143ae015f 100644 --- a/src/librustc_infer/traits/error_reporting/mod.rs +++ b/src/librustc_infer/traits/error_reporting/mod.rs @@ -1142,7 +1142,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // we're only talking about builtin traits, which are known to be // inhabited. We used to check for `self.tcx.sess.has_errors()` to // avoid inundating the user with unnecessary errors, but we now - // check upstream for type errors and dont add the obligations to + // check upstream for type errors and don't add the obligations to // begin with in those cases. if self .tcx diff --git a/src/librustc_infer/traits/object_safety.rs b/src/librustc_infer/traits/object_safety.rs index f5bab7cfac9..6f20f5ac47e 100644 --- a/src/librustc_infer/traits/object_safety.rs +++ b/src/librustc_infer/traits/object_safety.rs @@ -612,7 +612,7 @@ fn receiver_is_dispatchable<'tcx>( }; // the type `U` in the query - // use a bogus type parameter to mimick a forall(U) query using u32::MAX for now. + // use a bogus type parameter to mimic a forall(U) query using u32::MAX for now. // FIXME(mikeyhew) this is a total hack. Once object_safe_for_dispatch is stabilized, we can // replace this with `dyn Trait` let unsized_self_ty: Ty<'tcx> = diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs index 4f5e03d008c..c51bf735fa7 100644 --- a/src/librustc_lexer/src/unescape.rs +++ b/src/librustc_lexer/src/unescape.rs @@ -17,7 +17,7 @@ pub enum EscapeError { /// Escaped '\' character without continuation. LoneSlash, - /// Invalid escape characted (e.g. '\z'). + /// Invalid escape character (e.g. '\z'). InvalidEscape, /// Raw '\r' encountered. BareCarriageReturn, @@ -43,7 +43,7 @@ pub enum EscapeError { UnclosedUnicodeEscape, /// '\u{_12}' LeadingUnderscoreUnicodeEscape, - /// More than 6 charactes in '\u{..}', e.g. '\u{10FFFF_FF}' + /// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}' OverlongUnicodeEscape, /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'. LoneSurrogateUnicodeEscape, diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 6362f3c2c49..97b800decc5 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -57,7 +57,7 @@ enum QueryModifier { /// Generate a dep node based on the dependencies of the query Anon, - /// Always evaluate the query, ignoring its depdendencies + /// Always evaluate the query, ignoring its dependencies EvalAlways, } @@ -228,7 +228,7 @@ struct QueryModifiers { /// Generate a dep node based on the dependencies of the query anon: bool, - // Always evaluate the query, ignoring its depdendencies + // Always evaluate the query, ignoring its dependencies eval_always: bool, } diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 2157b8ce159..efa259d0c4e 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -711,7 +711,7 @@ impl<'a> CrateLocator<'a> { // See also #68149 which provides more detail on why emitting the // dependency on the rlib is a bad thing. // - // We currenty do not verify that these other sources are even in sync, + // We currently do not verify that these other sources are even in sync, // and this is arguably a bug (see #10786), but because reading metadata // is quite slow (especially from dylibs) we currently do not read it // from the other crate sources. diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 9b05fd4734c..1553b6cf0af 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -201,7 +201,7 @@ crate struct CrateRoot<'tcx> { per_def: LazyPerDefTables<'tcx>, - /// The DefIndex's of any proc macros delcared by this crate. + /// The DefIndex's of any proc macros declared by this crate. proc_macro_data: Option>, compiler_builtins: bool, diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index ca51d16f9f2..6ed4a1d4914 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -1231,7 +1231,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { GeneratorKind::Async(async_kind) => match async_kind { AsyncGeneratorKind::Block => "async block", AsyncGeneratorKind::Closure => "async closure", - _ => bug!("async block/closure expected, but async funtion found."), + _ => bug!("async block/closure expected, but async function found."), }, GeneratorKind::Gen => "generator", }, diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index d91f6edc980..5c37faaa82a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -445,7 +445,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err.buffer(&mut self.errors_buffer); } - /// Targetted error when encountering an `FnMut` closure where an `Fn` closure was expected. + /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut DiagnosticBuilder<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {}", act)); diff --git a/src/librustc_mir/borrow_check/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs index 0bead27050c..d33639aa9d9 100644 --- a/src/librustc_mir/borrow_check/invalidation.rs +++ b/src/librustc_mir/borrow_check/invalidation.rs @@ -63,7 +63,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.mutate_place(location, lhs, Shallow(None), JustWrite); } StatementKind::FakeRead(_, _) => { - // Only relavent for initialized/liveness/safety checks. + // Only relevant for initialized/liveness/safety checks. } StatementKind::SetDiscriminant { ref place, variant_index: _ } => { self.mutate_place(location, place, Shallow(None), JustWrite); diff --git a/src/librustc_mir/borrow_check/member_constraints.rs b/src/librustc_mir/borrow_check/member_constraints.rs index aeb29d2e11e..4323e2db844 100644 --- a/src/librustc_mir/borrow_check/member_constraints.rs +++ b/src/librustc_mir/borrow_check/member_constraints.rs @@ -125,7 +125,7 @@ where // wind up mapped to the same key `S`, we would append the // linked list for `Ra` onto the end of the linked list for // `Rb` (or vice versa) -- this basically just requires - // rewriting the final link from one list to point at the othe + // rewriting the final link from one list to point at the other // other (see `append_list`). let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self; diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 28974dcd08b..f93f2acfa8a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -452,7 +452,7 @@ crate struct MirBorrowckCtxt<'cx, 'tcx> { /// for the activation of the borrow. reservation_warnings: FxHashMap, Span, Location, BorrowKind, BorrowData<'tcx>)>, - /// This field keeps track of move errors that are to be reported for given move indicies. + /// This field keeps track of move errors that are to be reported for given move indices. /// /// There are situations where many errors can be reported for a single move out (see #53807) /// and we want only the best of those errors. diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 652de6c7b6f..ace92949814 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -579,7 +579,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { | ConstraintCategory::UseAsConst | ConstraintCategory::UseAsStatic = constraint.category { - // "Returning" from a promoted is an assigment to a + // "Returning" from a promoted is an assignment to a // temporary from the user's point of view. constraint.category = ConstraintCategory::Boring; } diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 1bf748e66e2..7a8e61db6d0 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -226,7 +226,7 @@ pub fn const_eval_validated_provider<'tcx>( match tcx.const_eval_validated(key) { // try again with reveal all as requested Err(ErrorHandled::TooGeneric) => {} - // dedupliate calls + // deduplicate calls other => return other, } } @@ -267,7 +267,7 @@ pub fn const_eval_raw_provider<'tcx>( match tcx.const_eval_raw(key) { // try again with reveal all as requested Err(ErrorHandled::TooGeneric) => {} - // dedupliate calls + // deduplicate calls other => return other, } } diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 7a3f09ac80b..e683422e611 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -670,7 +670,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ); if cur_unwinding { // Follow the unwind edge. - let unwind = next_block.expect("Encounted StackPopCleanup::None when unwinding!"); + let unwind = next_block.expect("Encountered StackPopCleanup::None when unwinding!"); self.unwind_to_block(unwind); } else { // Follow the normal return edge. diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 69c9664b351..6615cc608fb 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -227,7 +227,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// it contains (in relocations) tagged. The way we construct allocations is /// to always first construct it without extra and then add the extra. /// This keeps uniform code paths for handling both allocations created by CTFE - /// for statics, and allocations ceated by Miri during evaluation. + /// for statics, and allocations created by Miri during evaluation. /// /// `kind` is the kind of the allocation being tagged; it can be `None` when /// it's a static and `STATIC_KIND` is `None`. diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 44b46d65bf1..22b1a7b7137 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -678,7 +678,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Then computing the absolute variant idx should not overflow any more. let variant_index = variants_start .checked_add(variant_index_relative) - .expect("oveflow computing absolute variant idx"); + .expect("overflow computing absolute variant idx"); let variants_len = rval .layout .ty diff --git a/src/librustc_mir/interpret/snapshot.rs b/src/librustc_mir/interpret/snapshot.rs index 2353b74016c..ee45179fd8b 100644 --- a/src/librustc_mir/interpret/snapshot.rs +++ b/src/librustc_mir/interpret/snapshot.rs @@ -292,7 +292,7 @@ where let all_bytes = 0..self.len(); // This 'inspect' is okay since following access respects undef and relocations. This does - // influence interpreter exeuction, but only to detect the error of cycles in evalution + // influence interpreter exeuction, but only to detect the error of cycles in evaluation // dependencies. let bytes = self.inspect_with_undef_and_ptr_outside_interpreter(all_bytes); diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index a5b467c1e10..67444a26782 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -20,7 +20,7 @@ fn is_stable(place: PlaceRef<'_, '_>) -> bool { // Which place this evaluates to can change with any memory write, // so cannot assume this to be stable. ProjectionElem::Deref => false, - // Array indices are intersting, but MIR building generates a *fresh* + // Array indices are interesting, but MIR building generates a *fresh* // temporary for every array access, so the index cannot be changed as // a side-effect. ProjectionElem::Index { .. } | diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index c196e748df3..0560f77f5c9 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -664,7 +664,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return; } - // FIXME> figure out what tho do when try_read_immediate fails + // FIXME> figure out what to do when try_read_immediate fails let imm = self.use_ecx(|this| this.ecx.try_read_immediate(value)); if let Some(Ok(imm)) = imm { diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f7239ae55fa..07b0765488d 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -731,7 +731,7 @@ where self.elaborator.patch().new_block(base_block) } - /// Ceates a pair of drop-loops of `place`, which drops its contents, even + /// Creates a pair of drop-loops of `place`, which drops its contents, even /// in the case of 1 panic. If `ptr_based`, creates a pointer loop, /// otherwise create an index loop. fn drop_loop_pair( diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6fd8f06fe8f..65cc6a90034 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -490,7 +490,7 @@ fn write_scope_tree( } let children = match scope_tree.get(&parent) { - Some(childs) => childs, + Some(children) => children, None => return Ok(()), }; diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 5b054c04522..066fd8281cc 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -837,7 +837,7 @@ impl<'tcx> Constructor<'tcx> { // eliminate it straight away. remaining_ranges = vec![]; } else { - // Otherwise explicitely compute the remaining ranges. + // Otherwise explicitly compute the remaining ranges. remaining_ranges = other_range.subtract_from(remaining_ranges); } diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index 17b9e78e5df..f42091e7c29 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -257,7 +257,7 @@ impl<'a> StripUnconfigured<'a> { /// Parse and expand all `cfg_attr` attributes into a list of attributes /// that are within each `cfg_attr` that has a true configuration predicate. /// - /// Gives compiler warnigns if any `cfg_attr` does not contain any + /// Gives compiler warnings if any `cfg_attr` does not contain any /// attributes and is in the original source code. Gives compiler errors if /// the syntax of any `cfg_attr` is incorrect. pub fn process_cfg_attrs(&mut self, node: &mut T) { diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index 2dccb04f6cc..bdd78e671a8 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -138,7 +138,7 @@ impl<'a> Parser<'a> { if let Some(prev_attr_sp) = prev_attr_sp { diagnostic - .span_label(attr_sp, "not permitted following an outer attibute") + .span_label(attr_sp, "not permitted following an outer attribute") .span_label(prev_attr_sp, prev_attr_note); } diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 8b43b424f55..6587e763d50 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -895,7 +895,7 @@ impl<'a> Parser<'a> { let msg = format!("expected `;`, found `{}`", super::token_descr(&self.token)); let appl = Applicability::MachineApplicable; if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP { - // Likely inside a macro, can't provide meaninful suggestions. + // Likely inside a macro, can't provide meaningful suggestions. return self.expect(&token::Semi).map(drop); } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) { // The current token is in the same line as the prior token, not recoverable. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 18ddd23588e..e9ee797b90f 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1373,7 +1373,7 @@ impl<'a> Parser<'a> { )) } - /// Parses an optional `move` prefix to a closure lke construct. + /// Parses an optional `move` prefix to a closure-like construct. fn parse_capture_clause(&mut self) -> CaptureBy { if self.eat_keyword(kw::Move) { CaptureBy::Value } else { CaptureBy::Ref } } diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index e636144794a..282bd20a9be 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -285,7 +285,7 @@ fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx h // Ordinarily, we can rely on the visit order of HIR intravisit // to correspond to the actual execution order of statements. - // However, there's a weird corner case with compund assignment + // However, there's a weird corner case with compound assignment // operators (e.g. `a += b`). The evaluation order depends on whether // or not the operator is overloaded (e.g. whether or not a trait // like AddAssign is implemented). diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index f075385ae18..7ea9ab5335d 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -655,7 +655,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { } // FIXME(#44232): the `used_features` table no longer exists, so we - // don't lint about unused features. We should reenable this one day! + // don't lint about unused features. We should re-enable this one day! } fn unnecessary_stable_feature_lint(tcx: TyCtxt<'_>, span: Span, feature: Symbol, since: Symbol) { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 18192a18cef..ab5816cb775 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1090,7 +1090,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } // Sort extern crate names in reverse order to get - // 1) some consistent ordering for emitted dignostics, and + // 1) some consistent ordering for emitted diagnostics, and // 2) `std` suggestions before `core` suggestions. let mut extern_crate_names = self.r.extern_prelude.iter().map(|(ident, _)| ident.name).collect::>(); diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 3b018005a88..5d4df992b94 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1075,7 +1075,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // single import (see test `issue-55884-2.rs`). In theory single imports should // always block globs, even if they are not yet resolved, so that this kind of // self-inconsistent resolution never happens. - // Reenable the assert when the issue is fixed. + // Re-enable the assert when the issue is fixed. // assert!(result[ns].get().is_err()); } } diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index a3554ea2ee0..ee67cecde9a 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -553,7 +553,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { let prev = replace(&mut self.diagnostic_metadata.currently_processing_generics, true); match arg { GenericArg::Type(ref ty) => { - // We parse const arguments as path types as we cannot distiguish them during + // We parse const arguments as path types as we cannot distinguish them during // parsing. We try to resolve that ambiguity by attempting resolution the type // namespace first, and if that fails we try again in the value namespace. If // resolution in the value namespace succeeds, we have an generic const argument on diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 193b6d75935..bd46e8e0869 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -540,7 +540,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { 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",); + span_bug!(ty.span, "object-lifetime-default expected, not implicit",); } LifetimeName::ImplicitObjectLifetimeDefault => { // If the user does not write *anything*, we diff --git a/src/librustc_target/abi/call/mod.rs b/src/librustc_target/abi/call/mod.rs index 8c7108229bd..77e7ff1e2a7 100644 --- a/src/librustc_target/abi/call/mod.rs +++ b/src/librustc_target/abi/call/mod.rs @@ -365,11 +365,11 @@ impl<'a, Ty> TyLayout<'a, Ty> { // // NB: for all tagged `enum`s (which include all non-C-like // `enum`s with defined FFI representation), this will - // match the homogenous computation on the equivalent + // match the homogeneous computation on the equivalent // `struct { tag; union { variant1; ... } }` and/or // `union { struct { tag; variant1; } ... }` // (the offsets of variant fields should be identical - // between the two for either to be a homogenous aggregate). + // between the two for either to be a homogeneous aggregate). let variant_start = total; for variant_idx in variants.indices() { let (variant_result, variant_total) = @@ -542,7 +542,7 @@ pub struct FnAbi<'a, Ty> { /// The count of non-variadic arguments. /// /// Should only be different from args.len() when c_variadic is true. - /// This can be used to know wether an argument is variadic or not. + /// This can be used to know whether an argument is variadic or not. pub fixed_count: usize, pub conv: Conv, diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index ffef38cedfc..e9bb94ca490 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -401,7 +401,7 @@ impl Align { } } -/// A pair of aligments, ABI-mandated and preferred. +/// A pair of alignments, ABI-mandated and preferred. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] #[derive(HashStable_Generic)] pub struct AbiAndPrefAlign { diff --git a/src/librustc_target/spec/i686_unknown_uefi.rs b/src/librustc_target/spec/i686_unknown_uefi.rs index 345590a00be..e299f92fdeb 100644 --- a/src/librustc_target/spec/i686_unknown_uefi.rs +++ b/src/librustc_target/spec/i686_unknown_uefi.rs @@ -29,7 +29,7 @@ pub fn target() -> TargetResult { base.abi_return_struct_as_int = true; // Use -GNU here, because of the reason below: - // Backgound and Problem: + // Background and Problem: // If we use i686-unknown-windows, the LLVM IA32 MSVC generates compiler intrinsic // _alldiv, _aulldiv, _allrem, _aullrem, _allmul, which will cause undefined symbol. // A real issue is __aulldiv() is referred by __udivdi3() - udivmod_inner!(), from @@ -64,7 +64,7 @@ pub fn target() -> TargetResult { // i386/umoddi3.S // Possible solution: // 1. Eliminate Intrinsics generation. - // 1.1 Choose differnt target to bypass isTargetKnownWindowsMSVC(). + // 1.1 Choose different target to bypass isTargetKnownWindowsMSVC(). // 1.2 Remove the "Setup Windows compiler runtime calls" in LLVM // 2. Implement Intrinsics. // We evaluated all options. diff --git a/src/librustc_target/spec/nvptx64_nvidia_cuda.rs b/src/librustc_target/spec/nvptx64_nvidia_cuda.rs index f070a3e5da4..e0a402533e7 100644 --- a/src/librustc_target/spec/nvptx64_nvidia_cuda.rs +++ b/src/librustc_target/spec/nvptx64_nvidia_cuda.rs @@ -23,7 +23,7 @@ pub fn target() -> TargetResult { // The linker can be installed from `crates.io`. linker: Some("rust-ptx-linker".to_string()), - // With `ptx-linker` approach, it can be later overriden via link flags. + // With `ptx-linker` approach, it can be later overridden via link flags. cpu: "sm_30".to_string(), // FIXME: create tests for the atomics. @@ -43,7 +43,7 @@ pub fn target() -> TargetResult { // Let the `ptx-linker` to handle LLVM lowering into MC / assembly. obj_is_bitcode: true, - // Convinient and predicable naming scheme. + // Convenient and predicable naming scheme. dll_prefix: "".to_string(), dll_suffix: ".ptx".to_string(), exe_suffix: ".ptx".to_string(), diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 199b476cb9a..c3cf0cdc61d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -661,7 +661,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete /// set of substitutions. This may involve applying defaulted type parameters. - /// Also returns back constriants on associated types. + /// Also returns back constraints on associated types. /// /// Example: /// @@ -2924,7 +2924,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); - // We proactively collect all the infered type params to emit a single error per fn def. + // We proactively collect all the inferred type params to emit a single error per fn def. let mut visitor = PlaceholderHirTyCollector::default(); for ty in decl.inputs { visitor.visit_ty(ty); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 40cafb626d7..b271bc95d94 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1040,7 +1040,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { return r; } - debug!("pick: actual search failed, assemble diagnotics"); + debug!("pick: actual search failed, assemble diagnostics"); let static_candidates = mem::take(&mut self.static_candidates); let private_candidate = self.private_candidate.take(); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d8b23998e72..1ec97a48001 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -457,7 +457,7 @@ pub enum Diverges { /// where all arms diverge), we may be /// able to provide a more informative /// message to the user. - /// If this is `None`, a default messsage + /// If this is `None`, a default message /// will be generated, which is suitable /// for most cases. custom_note: Option<&'static str>, @@ -896,7 +896,7 @@ where ty::Opaque(def_id, substs) => { debug!("fixup_opaque_types: found type {:?}", ty); // Here, we replace any inference variables that occur within - // the substs of an opaque type. By definition, any type occuring + // the substs of an opaque type. By definition, any type occurring // in the substs has a corresponding generic parameter, which is what // we replace it with. // This replacement is only run on the function signature, so any @@ -1937,7 +1937,7 @@ fn check_specialization_validity<'tcx>( } }); - // If `opt_result` is `None`, we have only encoutered `default impl`s that don't contain the + // If `opt_result` is `None`, we have only encountered `default impl`s that don't contain the // item. This is allowed, the item isn't actually getting specialized here. let result = opt_result.unwrap_or(Ok(())); @@ -3452,7 +3452,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // } // ``` // - // In the above snippet, the inference varaible created by + // In the above snippet, the inference variable created by // instantiating `Option` will be completely unconstrained. // We treat this as a non-defining use by making the inference // variable fall back to the opaque type itself. diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b7aac707a98..32f04f03a1d 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -98,7 +98,7 @@ const INITIAL_BM: BindingMode = BindingMode::BindByValue(hir::Mutability::Not); enum AdjustMode { /// Peel off all immediate reference types. Peel, - /// Reset binding mode to the inital mode. + /// Reset binding mode to the initial mode. Reset, /// Pass on the input binding mode and expected type. Pass, @@ -841,7 +841,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // N-arity-tuple, e.g., `V_i((p_0, .., p_N))`. Meanwhile, the user supplied a pattern // with the subpatterns directly in the tuple variant pattern, e.g., `V_i(p_0, .., p_N)`. let missing_parenthesis = match (&expected.kind, fields, had_err) { - // #67037: only do this if we could sucessfully type-check the expected type against + // #67037: only do this if we could successfully type-check the expected type against // the tuple struct pattern. Otherwise the substs could get out of range on e.g., // `let P() = U;` where `P != U` with `struct P(T);`. (ty::Adt(_, substs), [field], false) => { diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index a8e5a0ddf26..0a574493573 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -174,7 +174,7 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> { // impl !Send for (A, B) { } // ``` // - // This final impl is legal according to the orpan + // This final impl is legal according to the orphan // rules, but it invalidates the reasoning from // `two_foos` above. debug!( diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 26462e61e5d..fc1ef4f756c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1395,7 +1395,7 @@ fn are_suggestable_generic_args(generic_args: &[hir::GenericArg<'_>]) -> bool { .any(is_suggestable_infer_ty) } -/// Whether `ty` is a type with `_` placeholders that can be infered. Used in diagnostics only to +/// Whether `ty` is a type with `_` placeholders that can be inferred. Used in diagnostics only to /// use inference to provide suggestions for the appropriate type if possible. fn is_suggestable_infer_ty(ty: &hir::Ty<'_>) -> bool { use hir::TyKind::*; diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 289923b45e6..407b50382fa 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -493,7 +493,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { // Writing a projection trait bound of the form // ::Name : ?Sized // is illegal, because ?Sized bounds can only - // be written in the (here, nonexistant) definition + // be written in the (here, nonexistent) definition // of the type. // Therefore, we make sure that we never add a ?Sized // bound for projections diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 0b4bb304fe9..02f1947c99e 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -135,7 +135,7 @@ trait Writer { fn string(&mut self, text: T, klass: Class) -> io::Result<()>; } -// Implement `Writer` for anthing that can be written to, this just implements +// Implement `Writer` for anything that can be written to, this just implements // the default rustdoc behaviour. impl Writer for U { fn string(&mut self, text: T, klass: Class) -> io::Result<()> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 07fe439ace2..c64c4769708 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3601,7 +3601,7 @@ fn render_impl( use_absolute: Option, is_on_foreign_type: bool, show_default_items: bool, - // This argument is used to reference same type with different pathes to avoid duplication + // This argument is used to reference same type with different paths to avoid duplication // in documentation pages for trait with automatic implementations like "Send" and "Sync". aliases: &[String], ) { diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 200b00b1195..edc28033c9b 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -651,7 +651,7 @@ impl Ipv4Addr { /// Returns [`true`] if this address is reserved by IANA for future use. [IETF RFC 1112] /// defines the block of reserved addresses as `240.0.0.0/4`. This range normally includes the - /// broadcast address `255.255.255.255`, but this implementation explicitely excludes it, since + /// broadcast address `255.255.255.255`, but this implementation explicitly excludes it, since /// it is obviously not reserved for future use. /// /// [IETF RFC 1112]: https://tools.ietf.org/html/rfc1112 diff --git a/src/libstd/os/linux/fs.rs b/src/libstd/os/linux/fs.rs index dd71201b50b..d22b44a0666 100644 --- a/src/libstd/os/linux/fs.rs +++ b/src/libstd/os/linux/fs.rs @@ -34,7 +34,7 @@ pub trait MetadataExt { /// } /// ``` #[stable(feature = "metadata_ext", since = "1.1.0")] - #[rustc_deprecated(since = "1.8.0", reason = "other methods of this trait are now prefered")] + #[rustc_deprecated(since = "1.8.0", reason = "other methods of this trait are now preferred")] #[allow(deprecated)] fn as_raw_stat(&self) -> &raw::stat; diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index c51aa7619db..0274268f69f 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -40,7 +40,7 @@ struct Consumer { tail: UnsafeCell<*mut Node>, // where to pop from tail_prev: AtomicPtr>, // where to pop from cache_bound: usize, // maximum cache size - cached_nodes: AtomicUsize, // number of nodes marked as cachable + cached_nodes: AtomicUsize, // number of nodes marked as cacheable addition: Addition, } diff --git a/src/libstd/sys/sgx/abi/usercalls/alloc.rs b/src/libstd/sys/sgx/abi/usercalls/alloc.rs index b54c115a2b6..76a9b427b39 100644 --- a/src/libstd/sys/sgx/abi/usercalls/alloc.rs +++ b/src/libstd/sys/sgx/abi/usercalls/alloc.rs @@ -151,7 +151,7 @@ unsafe impl UserSafe for [T] { /// It is also possible to obtain a mutable reference `&mut UserRef`. Unlike /// regular mutable references, these are not exclusive. Userspace may always /// write to the backing memory at any time, so it can't be assumed that there -/// the pointed-to memory is uniquely borrowed. The two different refence types +/// the pointed-to memory is uniquely borrowed. The two different reference types /// are used solely to indicate intent: a mutable reference is for writing to /// user memory, an immutable reference for reading from user memory. #[unstable(feature = "sgx_platform", issue = "56975")] diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 06876cb0614..fbcb006ecdf 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -156,7 +156,7 @@ where // On Unix-like platforms, libc::abort will unregister signal handlers // including the SIGABRT handler, preventing the abort from being blocked, and -// fclose streams, with the side effect of flushing them so libc bufferred +// fclose streams, with the side effect of flushing them so libc buffered // output will be printed. Additionally the shell will generally print a more // understandable error message like "Abort trap" rather than "Illegal // instruction" that intrinsics::abort would cause, as intrinsics::abort is diff --git a/src/libstd/sys/vxworks/mod.rs b/src/libstd/sys/vxworks/mod.rs index 12bbfa1d4e1..e23191c9431 100644 --- a/src/libstd/sys/vxworks/mod.rs +++ b/src/libstd/sys/vxworks/mod.rs @@ -103,7 +103,7 @@ where // On Unix-like platforms, libc::abort will unregister signal handlers // including the SIGABRT handler, preventing the abort from being blocked, and -// fclose streams, with the side effect of flushing them so libc bufferred +// fclose streams, with the side effect of flushing them so libc buffered // output will be printed. Additionally the shell will generally print a more // understandable error message like "Abort trap" rather than "Illegal // instruction" that intrinsics::abort would cause, as intrinsics::abort is diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs index a800bd17c50..5317063b80d 100644 --- a/src/libtest/cli.rs +++ b/src/libtest/cli.rs @@ -283,7 +283,7 @@ fn is_nightly() -> bool { bootstrap || !disable_unstable_features } -// Gets the CLI options assotiated with `report-time` feature. +// Gets the CLI options associated with `report-time` feature. fn get_time_options( matches: &getopts::Matches, allow_unstable: bool, diff --git a/src/libtest/options.rs b/src/libtest/options.rs index 7db164c269a..8e7bd8de924 100644 --- a/src/libtest/options.rs +++ b/src/libtest/options.rs @@ -41,7 +41,7 @@ pub enum OutputFormat { Json, } -/// Whether ignored test should be runned or not +/// Whether ignored test should be run or not #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum RunIgnored { Yes, diff --git a/src/libtest/test_result.rs b/src/libtest/test_result.rs index 5c975c6272b..465f3f8f994 100644 --- a/src/libtest/test_result.rs +++ b/src/libtest/test_result.rs @@ -27,7 +27,7 @@ pub enum TestResult { unsafe impl Send for TestResult {} /// Creates a `TestResult` depending on the raw result of test execution -/// and assotiated data. +/// and associated data. pub fn calc_result<'a>( desc: &TestDesc, task_result: Result<(), &'a (dyn Any + 'static + Send)>, diff --git a/src/test/incremental/cyclic-trait-hierarchy.rs b/src/test/incremental/cyclic-trait-hierarchy.rs index 27287d06d54..03bb5eea765 100644 --- a/src/test/incremental/cyclic-trait-hierarchy.rs +++ b/src/test/incremental/cyclic-trait-hierarchy.rs @@ -1,4 +1,4 @@ -// Adapated from rust-lang/rust#58813 +// Adapted from rust-lang/rust#58813 // revisions: rpass1 cfail2 diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs index 42168dd273e..9c17c8745f8 100644 --- a/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs +++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_added.rs @@ -4,7 +4,7 @@ // rust-lang/rust#59535: // -// This is analgous to cgu_invalidated_when_import_removed.rs, but it covers +// This is analogous to cgu_invalidated_when_import_removed.rs, but it covers // the other direction: // // We start with a call-graph like `[A] -> [B -> D] [C]` (where the letters are diff --git a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs index 19ce7b3e148..1214e37f982 100644 --- a/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs +++ b/src/test/incremental/thinlto/cgu_invalidated_when_import_removed.rs @@ -41,7 +41,7 @@ mod foo { // In cfail2, ThinLTO decides that foo() does not get inlined into main, and // instead bar() gets inlined into foo(). But faulty logic in our incr. // ThinLTO implementation thought that `main()` is unchanged and thus reused - // the object file still containing a call to the now non-existant bar(). + // the object file still containing a call to the now non-existent bar(). pub fn foo(){ bar() } diff --git a/src/test/ui/consts/const-int-arithmetic-overflow.rs b/src/test/ui/consts/const-int-arithmetic-overflow.rs index 75dac812f1e..99bbeaafda5 100644 --- a/src/test/ui/consts/const-int-arithmetic-overflow.rs +++ b/src/test/ui/consts/const-int-arithmetic-overflow.rs @@ -8,7 +8,7 @@ const fn add(x: i8, y: i8) -> i8 { x+y } const fn sub(x: i8, y: i8) -> i8 { x-y } const fn mul(x: i8, y: i8) -> i8 { x*y } -// div and rem are always checked, so we cannot test their result in case of oveflow. +// div and rem are always checked, so we cannot test their result in case of overflow. const fn neg(x: i8) -> i8 { -x } fn main() { diff --git a/src/test/ui/definition-reachable/nested-fn.rs b/src/test/ui/definition-reachable/nested-fn.rs index b596ba8936a..b665b049f32 100644 --- a/src/test/ui/definition-reachable/nested-fn.rs +++ b/src/test/ui/definition-reachable/nested-fn.rs @@ -1,4 +1,4 @@ -// Check that functions visible to macros through paths with >2 segements are +// Check that functions visible to macros through paths with >2 segments are // considered reachable // aux-build:field-method-macro.rs diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs index 1c3b5ac7613..00f3490991b 100644 --- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs +++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs @@ -12,7 +12,7 @@ impl<'a> LifetimeTrait<'a> for &'a i32 {} fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x } //~^ ERROR cannot infer an appropriate lifetime -// Tests that a closure type contianing 'b cannot be returned from a type where +// Tests that a closure type containing 'b cannot be returned from a type where // only 'a was expected. fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) { //~^ ERROR lifetime mismatch diff --git a/src/test/ui/mir/mir_assign_eval_order.rs b/src/test/ui/mir/mir_assign_eval_order.rs index 1594421b0b1..799bf7f3a12 100644 --- a/src/test/ui/mir/mir_assign_eval_order.rs +++ b/src/test/ui/mir/mir_assign_eval_order.rs @@ -12,7 +12,7 @@ fn evaluate_reborrow_before_assign() { let y = &mut &2; let z = &3; // There's an implicit reborrow of `x` on the right-hand side of the - // assignement. Note that writing an explicit reborrow would not show this + // assignment. Note that writing an explicit reborrow would not show this // bug, as now there would be two reborrows on the right-hand side and at // least one of them would happen before the left-hand side is evaluated. *{ x = z; &mut *y } = x; diff --git a/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs index 0d96767a05d..a111acca66f 100644 --- a/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs +++ b/src/test/ui/nll/issue-54556-used-vs-unused-tails.rs @@ -1,4 +1,4 @@ -// Ths test case is exploring the space of how blocs with tail +// This test case is exploring the space of how blocks with tail // expressions and statements can be composed, trying to keep each // case on one line so that we can compare them via a vertical scan // with the human eye. diff --git a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs index 61d5d51cfd2..d0984bbe65f 100644 --- a/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs +++ b/src/test/ui/sanitize/new-llvm-pass-manager-thin-lto.rs @@ -1,6 +1,6 @@ // Regression test for sanitizer function instrumentation passes not // being run when compiling with new LLVM pass manager and ThinLTO. -// Note: The issue occured only on non-zero opt-level. +// Note: The issue occurred only on non-zero opt-level. // // min-llvm-version 9.0 // needs-sanitizer-support diff --git a/src/test/ui/type-alias-impl-trait/issue-65918.rs b/src/test/ui/type-alias-impl-trait/issue-65918.rs index 4ba778d53ac..af6d5010920 100644 --- a/src/test/ui/type-alias-impl-trait/issue-65918.rs +++ b/src/test/ui/type-alias-impl-trait/issue-65918.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; -/* copied Index and TryFrom for convinience (and simplicity) */ +/* copied Index and TryFrom for convenience (and simplicity) */ trait MyIndex { type O; fn my_index(self) -> Self::O; diff --git a/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs index 2f844b4a05f..7da0b049264 100644 --- a/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs +++ b/src/test/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs @@ -1,6 +1,6 @@ // check-pass // Regression test for issue #67844 -// Ensures that we properly handle nested TAIT occurences +// Ensures that we properly handle nested TAIT occurrences // with generic parameters #![feature(type_alias_impl_trait)] diff --git a/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs index c57e8149574..7bf151514c3 100644 --- a/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs +++ b/src/test/ui/typeck/issue-52082-type-param-shadows-existing-type.rs @@ -1,4 +1,4 @@ -// Fix issue 52082: Confusing error if accidentially defining a type paramter with the same name as +// Fix issue 52082: Confusing error if accidentally defining a type parameter with the same name as // an existing type // // To this end, make sure that when trying to retrieve a field of a (reference to) type parameter, diff --git a/src/test/ui/wf/wf-array-elem-sized.rs b/src/test/ui/wf/wf-array-elem-sized.rs index 41c2d3c43e9..34bf2203426 100644 --- a/src/test/ui/wf/wf-array-elem-sized.rs +++ b/src/test/ui/wf/wf-array-elem-sized.rs @@ -1,4 +1,4 @@ -// Check that array elemen types must be Sized. Issue #25692. +// Check that array element types must be Sized. Issue #25692. #![allow(dead_code)] diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs index c3d699b3e23..8f685fb8559 100644 --- a/src/tools/compiletest/src/errors.rs +++ b/src/tools/compiletest/src/errors.rs @@ -125,7 +125,7 @@ fn parse_expected( let captures = RE.captures(line)?; match (cfg, captures.name("cfgs")) { - // Only error messages that contain our `cfg` betweeen the square brackets apply to us. + // Only error messages that contain our `cfg` between the square brackets apply to us. (Some(cfg), Some(filter)) if !filter.as_str().split(',').any(|s| s == cfg) => return None, (Some(_), Some(_)) => {} diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index ac808b1f14e..424bac88c85 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1487,7 +1487,7 @@ impl<'test> TestCx<'test> { // can turn it back on if needed. if !self.is_rustdoc() // Note that we use the local pass mode here as we don't want - // to set unused to allow if we've overriden the pass mode + // to set unused to allow if we've overridden the pass mode // via command line flags. && local_pm != Some(PassMode::Run) { diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs index f11394bd95f..349829d8725 100644 --- a/src/tools/tidy/src/pal.rs +++ b/src/tools/tidy/src/pal.rs @@ -41,7 +41,7 @@ const EXCEPTION_PATHS: &[&str] = &[ "src/libpanic_unwind", "src/libunwind", // black_box implementation is LLVM-version specific and it uses - // target_os to tell targets with different LLVM-versions appart + // target_os to tell targets with different LLVM-versions apart // (e.g. `wasm32-unknown-emscripten` vs `wasm32-unknown-unknown`): "src/libcore/hint.rs", "src/libstd/sys/", // Platform-specific code for std lives here. From 31183bbd5a0d4e7873f0c789dc537b1eab60dee1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 6 Mar 2020 14:27:09 +0000 Subject: [PATCH 0825/1250] Fix missing ` in doc for File::with_options --- src/libstd/fs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 09be3f13050..e20fcfafa22 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -407,7 +407,7 @@ impl File { /// /// It is equivalent to `OpenOptions::new()` but allows you to write more /// readable code. Instead of `OpenOptions::new().read(true).open("foo.txt")` - /// you can write `File::with_options().read(true).open("foo.txt"). This + /// you can write `File::with_options().read(true).open("foo.txt")`. This /// also avoids the need to import `OpenOptions`. /// /// See the [`OpenOptions::new`] function for more details. From 2d0c5b4337ff24ef12b3ed7242a6bbf9f7567ce1 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 3 Mar 2020 23:22:32 +0300 Subject: [PATCH 0826/1250] rustc_expand: Factor out `Annotatable::into_tokens` to a separate method --- src/librustc_expand/base.rs | 27 ++++++++++++++++++++++++- src/librustc_expand/expand.rs | 37 ++++++----------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 9258b59f79b..f15e626c278 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::tokenstream::{self, TokenStream}; +use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; use rustc_ast::visit::{AssocCtxt, Visitor}; use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; @@ -118,6 +118,31 @@ impl Annotatable { } } + crate fn into_tokens(self) -> TokenStream { + // `Annotatable` can be converted into tokens directly, but we + // are packing it into a nonterminal as a piece of AST to make + // the produced token stream look nicer in pretty-printed form. + let nt = match self { + Annotatable::Item(item) => token::NtItem(item), + Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { + token::NtItem(P(item.and_then(ast::AssocItem::into_item))) + } + Annotatable::ForeignItem(item) => { + token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) + } + Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), + Annotatable::Expr(expr) => token::NtExpr(expr), + Annotatable::Arm(..) + | Annotatable::Field(..) + | Annotatable::FieldPat(..) + | Annotatable::GenericParam(..) + | Annotatable::Param(..) + | Annotatable::StructField(..) + | Annotatable::Variant(..) => panic!("unexpected annotatable"), + }; + TokenTree::token(token::Interpolated(Lrc::new(nt)), DUMMY_SP).into() + } + pub fn expect_item(self) -> P { match self { Annotatable::Item(i) => i, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index b16659725db..effa89e8bfb 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -10,12 +10,11 @@ use rustc_ast::ast::{ItemKind, MacArgs, MacStmtStyle, StmtKind}; use rustc_ast::mut_visit::*; use rustc_ast::ptr::P; use rustc_ast::token; -use rustc_ast::tokenstream::{TokenStream, TokenTree}; +use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::map_in_place::MapInPlace; use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; -use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; @@ -668,38 +667,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); - // `Annotatable` can be converted into tokens directly, but we are packing it - // into a nonterminal as a piece of AST to make the produced token stream - // look nicer in pretty-printed form. This may be no longer necessary. - let item_tok = TokenTree::token( - token::Interpolated(Lrc::new(match item { - Annotatable::Item(item) => token::NtItem(item), - Annotatable::TraitItem(item) | Annotatable::ImplItem(item) => { - token::NtItem(P(item.and_then(ast::AssocItem::into_item))) - } - Annotatable::ForeignItem(item) => { - token::NtItem(P(item.and_then(ast::ForeignItem::into_item))) - } - Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()), - Annotatable::Expr(expr) => token::NtExpr(expr), - Annotatable::Arm(..) - | Annotatable::Field(..) - | Annotatable::FieldPat(..) - | Annotatable::GenericParam(..) - | Annotatable::Param(..) - | Annotatable::StructField(..) - | Annotatable::Variant(..) => panic!("unexpected annotatable"), - })), - DUMMY_SP, - ) - .into(); - let item = attr.unwrap_normal_item(); - if let MacArgs::Eq(..) = item.args { + let tokens = item.into_tokens(); + let attr_item = attr.unwrap_normal_item(); + if let MacArgs::Eq(..) = attr_item.args { self.cx.span_err(span, "key-value macro attributes are not supported"); } let tok_result = - expander.expand(self.cx, span, item.args.inner_tokens(), item_tok); - self.parse_ast_fragment(tok_result, fragment_kind, &item.path, span) + expander.expand(self.cx, span, attr_item.args.inner_tokens(), tokens); + self.parse_ast_fragment(tok_result, fragment_kind, &attr_item.path, span) } SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(self.cx.parse_sess, &attr) { From 18080e60728401c9bd4d102bbb33a0d6d53740f6 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 Mar 2020 03:32:01 +0900 Subject: [PATCH 0827/1250] Remove `NO_DEBUG` const --- src/librustc/middle/codegen_fn_attrs.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustc/middle/codegen_fn_attrs.rs b/src/librustc/middle/codegen_fn_attrs.rs index 82adcfddc28..61b25cc4864 100644 --- a/src/librustc/middle/codegen_fn_attrs.rs +++ b/src/librustc/middle/codegen_fn_attrs.rs @@ -58,9 +58,6 @@ bitflags! { /// "weird symbol" for the standard library in that it has slightly /// different linkage, visibility, and reachability rules. const RUSTC_STD_INTERNAL_SYMBOL = 1 << 6; - /// `#[no_debug]`: an indicator that no debugging information should be - /// generated for this function by LLVM. - const NO_DEBUG = 1 << 7; /// `#[thread_local]`: indicates a static is actually a thread local /// piece of memory const THREAD_LOCAL = 1 << 8; From 4c2b0f1631f40f7dce7292b3b3b4e2a752b82f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 16:02:32 +0100 Subject: [PATCH 0828/1250] bless tests --- src/libcore/tests/num/dec2flt/mod.rs | 2 +- src/librustc_expand/proc_macro.rs | 2 +- src/test/ui/explain.stdout | 2 +- src/test/ui/parser/attr-stmt-expr-attr-bad.stderr | 10 +++++----- src/test/ui/parser/inner-attr-after-doc-comment.stderr | 2 +- src/test/ui/parser/inner-attr.stderr | 2 +- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libcore/tests/num/dec2flt/mod.rs b/src/libcore/tests/num/dec2flt/mod.rs index 509097fdb54..a1fa5556ae5 100644 --- a/src/libcore/tests/num/dec2flt/mod.rs +++ b/src/libcore/tests/num/dec2flt/mod.rs @@ -44,7 +44,7 @@ fn ordinary() { #[test] fn special_code_paths() { test_literal!(36893488147419103229.0); // 2^65 - 3, triggers half-to-even with even significand - test_literal!(101e-33); // Triggers the tricky underflow case in algorithm (for f32) + test_literal!(101e-33); // Triggers the tricky underflow case in AlgorithmM (for f32) test_literal!(1e23); // Triggers AlgorithmR test_literal!(2075e23); // Triggers another path through AlgorithmR test_literal!(8713e-23); // ... and yet another. diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index 5404ee192a6..84a546345bb 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -133,7 +133,7 @@ impl MultiItemModifier for ProcMacroDerive { }; let error_count_before = ecx.parse_sess.span_diagnostic.err_count(); - let msg = "proc-macro derive produced unparsable tokens"; + let msg = "proc-macro derive produced unparseable tokens"; let mut parser = rustc_parse::stream_to_parser(ecx.parse_sess, stream, Some("proc-macro derive")); diff --git a/src/test/ui/explain.stdout b/src/test/ui/explain.stdout index 9ea56271f59..c50c46ee564 100644 --- a/src/test/ui/explain.stdout +++ b/src/test/ui/explain.stdout @@ -46,7 +46,7 @@ This pattern should be rewritten. There are a few possible ways to do this: - change the original fn declaration to match the expected signature, and do the cast in the fn body (the preferred option) -- cast the fn item fo a fn pointer before calling transmute, as shown here: +- cast the fn item of a fn pointer before calling transmute, as shown here: ``` let f: extern "C" fn(*mut i32) = transmute(foo as extern "C" fn(_)); diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index b03db85422d..6159acd5080 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -292,7 +292,7 @@ error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:80:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] let _ = 0; } - | ------- ^^^^^^^^ not permitted following an outer attibute + | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute | @@ -302,7 +302,7 @@ error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:82:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] 0; } - | ------- ^^^^^^^^ not permitted following an outer attibute + | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute | @@ -312,7 +312,7 @@ error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:84:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!(); } - | ------- ^^^^^^^^ not permitted following an outer attibute + | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute | @@ -322,7 +322,7 @@ error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:86:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo![]; } - | ------- ^^^^^^^^ not permitted following an outer attibute + | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute | @@ -332,7 +332,7 @@ error: an inner attribute is not permitted following an outer attribute --> $DIR/attr-stmt-expr-attr-bad.rs:88:32 | LL | #[cfg(FALSE)] fn s() { #[attr] #![attr] foo!{}; } - | ------- ^^^^^^^^ not permitted following an outer attibute + | ------- ^^^^^^^^ not permitted following an outer attribute | | | previous outer attribute | diff --git a/src/test/ui/parser/inner-attr-after-doc-comment.stderr b/src/test/ui/parser/inner-attr-after-doc-comment.stderr index b012abc25e7..c1e9e7a427f 100644 --- a/src/test/ui/parser/inner-attr-after-doc-comment.stderr +++ b/src/test/ui/parser/inner-attr-after-doc-comment.stderr @@ -7,7 +7,7 @@ LL | | */ | |___- previous doc comment LL | LL | #![recursion_limit="100"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. diff --git a/src/test/ui/parser/inner-attr.stderr b/src/test/ui/parser/inner-attr.stderr index 070d9f47d96..e1bf2cca1c9 100644 --- a/src/test/ui/parser/inner-attr.stderr +++ b/src/test/ui/parser/inner-attr.stderr @@ -5,7 +5,7 @@ LL | #[feature(lang_items)] | ---------------------- previous outer attribute LL | LL | #![recursion_limit="100"] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attibute + | ^^^^^^^^^^^^^^^^^^^^^^^^^ not permitted following an outer attribute | = note: inner attributes, like `#![no_std]`, annotate the item enclosing them, and are usually found at the beginning of source files. Outer attributes, like `#[test]`, annotate the item following them. From 83980aca2086e5c4dca5aae9a92a065a9ff4ac56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 19:28:44 +0100 Subject: [PATCH 0829/1250] Don't redundantly repeat field names (clippy::redundant_field_names) --- src/liballoc/collections/linked_list.rs | 2 +- src/liballoc/vec.rs | 2 +- src/libproc_macro/diagnostic.rs | 17 +++++++---------- src/librustc/hir/map/definitions.rs | 2 +- src/librustc/mir/mono.rs | 2 +- src/librustc/traits/structural_impls.rs | 6 +++--- src/librustc/ty/context.rs | 10 +++++----- src/librustc/ty/instance.rs | 2 +- src/librustc/ty/mod.rs | 4 ++-- src/librustc/ty/normalize_erasing_regions.rs | 5 +---- src/librustc/ty/relate.rs | 4 ++-- src/librustc/ty/sty.rs | 2 +- .../deriving/generic/mod.rs | 2 +- src/librustc_codegen_llvm/abi.rs | 2 +- src/librustc_infer/infer/at.rs | 2 +- src/librustc_infer/infer/equate.rs | 2 +- .../error_reporting/nice_region_error/util.rs | 8 ++++---- src/librustc_infer/infer/glb.rs | 2 +- src/librustc_infer/infer/lub.rs | 2 +- .../infer/region_constraints/leak_check.rs | 2 +- .../infer/region_constraints/mod.rs | 2 +- src/librustc_infer/infer/resolve.rs | 2 +- src/librustc_infer/infer/sub.rs | 2 +- src/librustc_infer/traits/mod.rs | 2 +- src/librustc_infer/traits/project.rs | 4 ++-- src/librustc_infer/traits/select.rs | 2 +- src/librustc_infer/traits/util.rs | 2 +- src/librustc_lint/levels.rs | 4 ++-- src/librustc_metadata/rmeta/encoder.rs | 2 +- .../borrow_check/diagnostics/mod.rs | 2 +- .../borrow_check/region_infer/values.rs | 2 +- .../borrow_check/universal_regions.rs | 2 +- src/librustc_mir/dataflow/graphviz.rs | 2 +- src/librustc_mir/dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/interpret/place.rs | 2 +- src/librustc_mir/monomorphize/mod.rs | 2 +- src/librustc_mir/transform/add_retag.rs | 4 ++-- src/librustc_mir/transform/generator.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- src/librustc_mir/util/elaborate_drops.rs | 4 ++-- src/librustc_mir/util/pretty.rs | 2 +- .../build/matches/simplify.rs | 2 +- src/librustc_mir_build/build/matches/test.rs | 5 +---- src/librustc_mir_build/build/mod.rs | 2 +- src/librustc_mir_build/hair/cx/block.rs | 2 +- src/librustc_resolve/late.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 8 ++++---- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/sig.rs | 2 +- src/librustc_session/code_stats.rs | 2 +- src/librustc_span/def_id.rs | 2 +- src/librustc_ty/instance.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/outlives/implicit_infer.rs | 4 ++-- src/librustdoc/doctree.rs | 2 +- src/libstd/collections/hash/map.rs | 2 +- src/libstd/io/cursor.rs | 2 +- src/libstd/io/mod.rs | 4 ++-- src/libstd/sync/mutex.rs | 2 +- src/libstd/sync/rwlock.rs | 7 ++----- 61 files changed, 88 insertions(+), 100 deletions(-) diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs index a9b4e3e4706..8efacf108fc 100644 --- a/src/liballoc/collections/linked_list.rs +++ b/src/liballoc/collections/linked_list.rs @@ -959,7 +959,7 @@ impl LinkedList { let it = self.head; let old_len = self.len; - DrainFilter { list: self, it: it, pred: filter, idx: 0, old_len: old_len } + DrainFilter { list: self, it, pred: filter, idx: 0, old_len } } } diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3fd7be06fd4..7523d9c5ba3 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1659,7 +1659,7 @@ struct SetLenOnDrop<'a> { impl<'a> SetLenOnDrop<'a> { #[inline] fn new(len: &'a mut usize) -> Self { - SetLenOnDrop { local_len: *len, len: len } + SetLenOnDrop { local_len: *len, len } } #[inline] diff --git a/src/libproc_macro/diagnostic.rs b/src/libproc_macro/diagnostic.rs index fdf252e5338..7495468a05b 100644 --- a/src/libproc_macro/diagnostic.rs +++ b/src/libproc_macro/diagnostic.rs @@ -55,13 +55,15 @@ pub struct Diagnostic { } macro_rules! diagnostic_child_methods { - ($spanned:ident, $regular:ident, $level:expr) => ( + ($spanned:ident, $regular:ident, $level:expr) => { /// Adds a new child diagnostic message to `self` with the level /// identified by this method's name with the given `spans` and /// `message`. #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn $spanned(mut self, spans: S, message: T) -> Diagnostic - where S: MultiSpan, T: Into + where + S: MultiSpan, + T: Into, { self.children.push(Diagnostic::spanned(spans, $level, message)); self @@ -74,7 +76,7 @@ macro_rules! diagnostic_child_methods { self.children.push(Diagnostic::new($level, message)); self } - ) + }; } /// Iterator over the children diagnostics of a `Diagnostic`. @@ -96,7 +98,7 @@ impl Diagnostic { /// Creates a new diagnostic with the given `level` and `message`. #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub fn new>(level: Level, message: T) -> Diagnostic { - Diagnostic { level: level, message: message.into(), spans: vec![], children: vec![] } + Diagnostic { level, message: message.into(), spans: vec![], children: vec![] } } /// Creates a new diagnostic with the given `level` and `message` pointing to @@ -107,12 +109,7 @@ impl Diagnostic { S: MultiSpan, T: Into, { - Diagnostic { - level: level, - message: message.into(), - spans: spans.into_spans(), - children: vec![], - } + Diagnostic { level, message: message.into(), spans: spans.into_spans(), children: vec![] } } diagnostic_child_methods!(span_error, error, Level::Error); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 047ce8b8445..e1b5ec041db 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -192,7 +192,7 @@ impl DefPath { } } data.reverse(); - DefPath { data: data, krate: krate } + DefPath { data, krate } } /// Returns a string representation of the `DefPath` without diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 9a3ddfb0e82..4f8efc1607e 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -258,7 +258,7 @@ pub enum Visibility { impl<'tcx> CodegenUnit<'tcx> { pub fn new(name: Symbol) -> CodegenUnit<'tcx> { - CodegenUnit { name: name, items: Default::default(), size_estimate: None } + CodegenUnit { name, items: Default::default(), size_estimate: None } } pub fn name(&self) -> Symbol { diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index 63d7124ee91..a5efea9e5fa 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -532,9 +532,9 @@ impl<'a, 'tcx> Lift<'tcx> for traits::Vtable<'a, ()> { nested, }) => tcx.lift(&substs).map(|substs| { traits::VtableGenerator(traits::VtableGeneratorData { - generator_def_id: generator_def_id, - substs: substs, - nested: nested, + generator_def_id, + substs, + nested, }) }), traits::VtableClosure(traits::VtableClosureData { closure_def_id, substs, nested }) => { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 20736b50831..48ef81c1d5b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2256,22 +2256,22 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_mut_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut }) + self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ref(self, r: Region<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ref(r, TypeAndMut { ty: ty, mutbl: hir::Mutability::Not }) + self.mk_ref(r, TypeAndMut { ty, mutbl: hir::Mutability::Not }) } #[inline] pub fn mk_mut_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Mut }) + self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Mut }) } #[inline] pub fn mk_imm_ptr(self, ty: Ty<'tcx>) -> Ty<'tcx> { - self.mk_ptr(TypeAndMut { ty: ty, mutbl: hir::Mutability::Not }) + self.mk_ptr(TypeAndMut { ty, mutbl: hir::Mutability::Not }) } #[inline] @@ -2393,7 +2393,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn mk_ty_param(self, index: u32, name: Symbol) -> Ty<'tcx> { - self.mk_ty(Param(ParamTy { index, name: name })) + self.mk_ty(Param(ParamTy { index, name })) } #[inline] diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 4014d1d8ae2..445df76cd32 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -241,7 +241,7 @@ impl<'tcx> Instance<'tcx> { def_id, substs ); - Instance { def: InstanceDef::Item(def_id), substs: substs } + Instance { def: InstanceDef::Item(def_id), substs } } pub fn mono(tcx: TyCtxt<'tcx>, def_id: DefId) -> Instance<'tcx> { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index b25fd3c61fd..7bcd63b9655 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -370,7 +370,7 @@ pub trait DefIdTree: Copy { impl<'tcx> DefIdTree for TyCtxt<'tcx> { fn parent(self, id: DefId) -> Option { - self.def_key(id).parent.map(|index| DefId { index: index, ..id }) + self.def_key(id).parent.map(|index| DefId { index, ..id }) } } @@ -2227,7 +2227,7 @@ impl ReprOptions { if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.def_path_str(did))) { flags.insert(ReprFlags::IS_LINEAR); } - ReprOptions { int: size, align: max_align, pack: min_pack, flags: flags } + ReprOptions { int: size, align: max_align, pack: min_pack, flags } } #[inline] diff --git a/src/librustc/ty/normalize_erasing_regions.rs b/src/librustc/ty/normalize_erasing_regions.rs index dc64482907f..cbaabd8e1f1 100644 --- a/src/librustc/ty/normalize_erasing_regions.rs +++ b/src/librustc/ty/normalize_erasing_regions.rs @@ -34,10 +34,7 @@ impl<'tcx> TyCtxt<'tcx> { if !value.has_projections() { value } else { - value.fold_with(&mut NormalizeAfterErasingRegionsFolder { - tcx: self, - param_env: param_env, - }) + value.fold_with(&mut NormalizeAfterErasingRegionsFolder { tcx: self, param_env }) } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 3b9df72266f..10f27bf66f3 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -287,7 +287,7 @@ impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; - Ok(ty::TraitRef { def_id: a.def_id, substs: substs }) + Ok(ty::TraitRef { def_id: a.def_id, substs }) } } } @@ -303,7 +303,7 @@ impl<'tcx> Relate<'tcx> for ty::ExistentialTraitRef<'tcx> { Err(TypeError::Traits(expected_found(relation, &a.def_id, &b.def_id))) } else { let substs = relate_substs(relation, None, a.substs, b.substs)?; - Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs: substs }) + Ok(ty::ExistentialTraitRef { def_id: a.def_id, substs }) } } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index ab2c98c89b4..47bf7822b1f 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1193,7 +1193,7 @@ pub struct ParamTy { impl<'tcx> ParamTy { pub fn new(index: u32, name: Symbol) -> ParamTy { - ParamTy { index, name: name } + ParamTy { index, name } } pub fn for_self() -> ParamTy { diff --git a/src/librustc_builtin_macros/deriving/generic/mod.rs b/src/librustc_builtin_macros/deriving/generic/mod.rs index 311298c0f40..e0c619fcbd3 100644 --- a/src/librustc_builtin_macros/deriving/generic/mod.rs +++ b/src/librustc_builtin_macros/deriving/generic/mod.rs @@ -482,7 +482,7 @@ impl<'a> TraitDef<'a> { }) .cloned(), ); - push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() }))) + push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() }))) } _ => { // Non-Item derive is an error, but it should have been diff --git a/src/librustc_codegen_llvm/abi.rs b/src/librustc_codegen_llvm/abi.rs index c79d9f77e65..470a2bb8e1e 100644 --- a/src/librustc_codegen_llvm/abi.rs +++ b/src/librustc_codegen_llvm/abi.rs @@ -148,7 +148,7 @@ impl LlvmType for CastTarget { .prefix .iter() .flat_map(|option_kind| { - option_kind.map(|kind| Reg { kind: kind, size: self.prefix_chunk }.llvm_type(cx)) + option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx)) }) .chain((0..rest_count).map(|_| rest_ll_unit)) .collect(); diff --git a/src/librustc_infer/infer/at.rs b/src/librustc_infer/infer/at.rs index 156b5a8b0b5..04f5b03c0e1 100644 --- a/src/librustc_infer/infer/at.rs +++ b/src/librustc_infer/infer/at.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> At<'a, 'tcx> { T: ToTrace<'tcx>, { let trace = ToTrace::to_trace(self.cause, a_is_expected, a, b); - Trace { at: self, trace: trace, a_is_expected } + Trace { at: self, trace, a_is_expected } } } diff --git a/src/librustc_infer/infer/equate.rs b/src/librustc_infer/infer/equate.rs index c1eec6832b8..bb0c124a189 100644 --- a/src/librustc_infer/infer/equate.rs +++ b/src/librustc_infer/infer/equate.rs @@ -19,7 +19,7 @@ impl<'combine, 'infcx, 'tcx> Equate<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Equate<'combine, 'infcx, 'tcx> { - Equate { fields: fields, a_is_expected: a_is_expected } + Equate { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index 4dc9096533b..cab632935fd 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -77,11 +77,11 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if found_anon_region { let is_first = index == 0; Some(AnonymousParamInfo { - param: param, + param, param_ty: new_param_ty, - param_ty_span: param_ty_span, - bound_region: bound_region, - is_first: is_first, + param_ty_span, + bound_region, + is_first, }) } else { None diff --git a/src/librustc_infer/infer/glb.rs b/src/librustc_infer/infer/glb.rs index 2634d9cac3e..8b26bcef573 100644 --- a/src/librustc_infer/infer/glb.rs +++ b/src/librustc_infer/infer/glb.rs @@ -18,7 +18,7 @@ impl<'combine, 'infcx, 'tcx> Glb<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Glb<'combine, 'infcx, 'tcx> { - Glb { fields: fields, a_is_expected: a_is_expected } + Glb { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/lub.rs b/src/librustc_infer/infer/lub.rs index b6d20ba1f3f..20ddeec6850 100644 --- a/src/librustc_infer/infer/lub.rs +++ b/src/librustc_infer/infer/lub.rs @@ -18,7 +18,7 @@ impl<'combine, 'infcx, 'tcx> Lub<'combine, 'infcx, 'tcx> { fields: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Lub<'combine, 'infcx, 'tcx> { - Lub { fields: fields, a_is_expected: a_is_expected } + Lub { fields, a_is_expected } } } diff --git a/src/librustc_infer/infer/region_constraints/leak_check.rs b/src/librustc_infer/infer/region_constraints/leak_check.rs index bbd4f3b3550..6ebe3f57597 100644 --- a/src/librustc_infer/infer/region_constraints/leak_check.rs +++ b/src/librustc_infer/infer/region_constraints/leak_check.rs @@ -85,7 +85,7 @@ impl<'tcx> TaintSet<'tcx> { fn new(directions: TaintDirections, initial_region: ty::Region<'tcx>) -> Self { let mut regions = FxHashSet::default(); regions.insert(initial_region); - TaintSet { directions: directions, regions: regions } + TaintSet { directions, regions } } fn fixed_point( diff --git a/src/librustc_infer/infer/region_constraints/mod.rs b/src/librustc_infer/infer/region_constraints/mod.rs index 3f9fa6459b3..868b9504379 100644 --- a/src/librustc_infer/infer/region_constraints/mod.rs +++ b/src/librustc_infer/infer/region_constraints/mod.rs @@ -766,7 +766,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> { b: Region<'tcx>, origin: SubregionOrigin<'tcx>, ) -> Region<'tcx> { - let vars = TwoRegions { a: a, b: b }; + let vars = TwoRegions { a, b }; if let Some(&c) = self.combine_map(t).get(&vars) { return tcx.mk_region(ReVar(c)); } diff --git a/src/librustc_infer/infer/resolve.rs b/src/librustc_infer/infer/resolve.rs index e2207d08ee6..562fbc246f7 100644 --- a/src/librustc_infer/infer/resolve.rs +++ b/src/librustc_infer/infer/resolve.rs @@ -160,7 +160,7 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>, value: &T) -> Fix where T: TypeFoldable<'tcx>, { - let mut full_resolver = FullTypeResolver { infcx: infcx, err: None }; + let mut full_resolver = FullTypeResolver { infcx, err: None }; let result = value.fold_with(&mut full_resolver); match full_resolver.err { None => Ok(result), diff --git a/src/librustc_infer/infer/sub.rs b/src/librustc_infer/infer/sub.rs index 2b770ced42a..f6fc38b5358 100644 --- a/src/librustc_infer/infer/sub.rs +++ b/src/librustc_infer/infer/sub.rs @@ -19,7 +19,7 @@ impl<'combine, 'infcx, 'tcx> Sub<'combine, 'infcx, 'tcx> { f: &'combine mut CombineFields<'infcx, 'tcx>, a_is_expected: bool, ) -> Sub<'combine, 'infcx, 'tcx> { - Sub { fields: f, a_is_expected: a_is_expected } + Sub { fields: f, a_is_expected } } fn with_expected_switched R>(&mut self, f: F) -> R { diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 61702d74f1a..800f8e91a78 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -619,7 +619,7 @@ impl<'tcx> FulfillmentError<'tcx> { obligation: PredicateObligation<'tcx>, code: FulfillmentErrorCode<'tcx>, ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation: obligation, code: code, points_at_arg_span: false } + FulfillmentError { obligation, code, points_at_arg_span: false } } } diff --git a/src/librustc_infer/traits/project.rs b/src/librustc_infer/traits/project.rs index 34889c6984b..78483cf6577 100644 --- a/src/librustc_infer/traits/project.rs +++ b/src/librustc_infer/traits/project.rs @@ -403,7 +403,7 @@ pub type NormalizedTy<'tcx> = Normalized<'tcx, Ty<'tcx>>; impl<'tcx, T> Normalized<'tcx, T> { pub fn with(self, value: U) -> Normalized<'tcx, U> { - Normalized { value: value, obligations: self.obligations } + Normalized { value, obligations: self.obligations } } } @@ -1291,7 +1291,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( substs: trait_ref.substs, item_def_id: obligation.predicate.item_def_id, }, - ty: ty, + ty, } }); diff --git a/src/librustc_infer/traits/select.rs b/src/librustc_infer/traits/select.rs index fd94e3b6994..c0d8f3cfd4f 100644 --- a/src/librustc_infer/traits/select.rs +++ b/src/librustc_infer/traits/select.rs @@ -2923,7 +2923,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Predicate::ClosureKind(closure_def_id, substs, kind), )); - Ok(VtableClosureData { closure_def_id, substs: substs, nested: obligations }) + Ok(VtableClosureData { closure_def_id, substs, nested: obligations }) } /// In the case of closure types and fn pointers, diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 1dca01b3468..cd4595e76cc 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -55,7 +55,7 @@ struct PredicateSet<'tcx> { impl PredicateSet<'tcx> { fn new(tcx: TyCtxt<'tcx>) -> Self { - Self { tcx: tcx, set: Default::default() } + Self { tcx, set: Default::default() } } fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 7da69f3ed26..e0db2ae64ff 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -377,10 +377,10 @@ impl<'s> LintLevelsBuilder<'s> { let prev = self.cur; if !specs.is_empty() { self.cur = self.sets.list.len() as u32; - self.sets.list.push(LintSet::Node { specs: specs, parent: prev }); + self.sets.list.push(LintSet::Node { specs, parent: prev }); } - BuilderPush { prev: prev, changed: prev != self.cur } + BuilderPush { prev, changed: prev != self.cur } } /// Called after `push` when the scope of a set of attributes are exited. diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ea0cc2f0c8b..7624b1d562f 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -493,7 +493,7 @@ impl<'tcx> EncodeContext<'tcx> { edition: tcx.sess.edition(), has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE), has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE), - has_default_lib_allocator: has_default_lib_allocator, + has_default_lib_allocator, plugin_registrar_fn: tcx.plugin_registrar_fn(LOCAL_CRATE).map(|id| id.index), proc_macro_decls_static: if is_proc_macro { let id = tcx.proc_macro_decls_static(LOCAL_CRATE).unwrap(); diff --git a/src/librustc_mir/borrow_check/diagnostics/mod.rs b/src/librustc_mir/borrow_check/diagnostics/mod.rs index cd6834a5a4d..fefef69d63c 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mod.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mod.rs @@ -175,7 +175,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if self.body.local_decls[local].is_ref_for_guard() => { self.append_place_to_string( - PlaceRef { local: local, projection: &[] }, + PlaceRef { local, projection: &[] }, buf, autoderef, &including_downcast, diff --git a/src/librustc_mir/borrow_check/region_infer/values.rs b/src/librustc_mir/borrow_check/region_infer/values.rs index 3126d44014b..675463cb1c1 100644 --- a/src/librustc_mir/borrow_check/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/region_infer/values.rs @@ -140,7 +140,7 @@ impl LivenessValues { /// Each of the regions in num_region_variables will be initialized with an /// empty set of points and no causal information. crate fn new(elements: Rc) -> Self { - Self { points: SparseBitMatrix::new(elements.num_points), elements: elements } + Self { points: SparseBitMatrix::new(elements.num_points), elements } } /// Iterate through each region that has a value in this set. diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index af4ea759f4f..67b00e9ffdd 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -486,7 +486,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { defining_ty, unnormalized_output_ty, unnormalized_input_tys, - yield_ty: yield_ty, + yield_ty, } } diff --git a/src/librustc_mir/dataflow/graphviz.rs b/src/librustc_mir/dataflow/graphviz.rs index 45d2b1a71f0..a9ef7ef6c52 100644 --- a/src/librustc_mir/dataflow/graphviz.rs +++ b/src/librustc_mir/dataflow/graphviz.rs @@ -72,7 +72,7 @@ pub struct Edge { fn outgoing(body: &Body<'_>, bb: BasicBlock) -> Vec { (0..body[bb].terminator().successors().count()) - .map(|index| Edge { source: bb, index: index }) + .map(|index| Edge { source: bb, index }) .collect() } diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 57aa5de7f7a..7e36a3cf2bf 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -474,7 +474,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } fn record_move(&mut self, place: &Place<'tcx>, path: MovePathIndex) { - let move_out = self.builder.data.moves.push(MoveOut { path: path, source: self.loc }); + let move_out = self.builder.data.moves.push(MoveOut { path, source: self.loc }); debug!( "gather_move({:?}, {:?}): adding move {:?} of {:?}", self.loc, place, move_out, path diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 4f96cb69891..4cf179f5fce 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -647,7 +647,7 @@ where } local => PlaceTy { // This works even for dead/uninitialized locals; we check further when writing - place: Place::Local { frame: self.cur_frame(), local: local }, + place: Place::Local { frame: self.cur_frame(), local }, layout: self.layout_of_local(self.frame(), local, None)?, }, }; diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 3dff06967e5..7177bf726d4 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -13,7 +13,7 @@ pub fn custom_coerce_unsize_info<'tcx>( let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); let trait_ref = ty::Binder::bind(ty::TraitRef { - def_id: def_id, + def_id, substs: tcx.mk_substs_trait(source_ty, &[target_ty.into()]), }); diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index a5b467c1e10..45cecc1b125 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -75,8 +75,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag { { let source_info = SourceInfo { scope: OUTERMOST_SOURCE_SCOPE, - span: span, // FIXME: Consider using just the span covering the function - // argument declaration. + span, // FIXME: Consider using just the span covering the function + // argument declaration. }; // Gather all arguments, skip return value. let places = local_decls diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 3107be1b622..d060a0eab3d 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -506,7 +506,7 @@ fn locals_live_across_suspend_points( for (block, data) in body.basic_blocks().iter_enumerated() { if let TerminatorKind::Yield { .. } = data.terminator().kind { - let loc = Location { block: block, statement_index: data.statements.len() }; + let loc = Location { block, statement_index: data.statements.len() }; if !movable { // The `liveness` variable contains the liveness of MIR locals ignoring borrows. diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 2ae7bd4d727..22ac3410a75 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -34,7 +34,7 @@ impl<'tcx> MirPass<'tcx> for SanityCheck { let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); let move_data = MoveData::gather_moves(body, tcx, param_env).unwrap(); - let mdpe = MoveDataParamEnv { move_data: move_data, param_env: param_env }; + let mdpe = MoveDataParamEnv { move_data, param_env }; let flow_inits = MaybeInitializedPlaces::new(tcx, body, &mdpe) .into_engine(tcx, body, def_id) diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index f7239ae55fa..4531b91e537 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -872,7 +872,7 @@ where debug!("drop_flag_reset_block({:?},{:?})", self, mode); let block = self.new_block(unwind, TerminatorKind::Goto { target: succ }); - let block_start = Location { block: block, statement_index: 0 }; + let block_start = Location { block, statement_index: 0 }; self.elaborator.clear_drop_flag(block_start, self.path, mode); block } @@ -921,7 +921,7 @@ where let call = TerminatorKind::Call { func: Operand::function_handle(tcx, free_func, substs, self.source_info.span), - args: args, + args, destination: Some((unit_temp, target)), cleanup: None, from_hir_call: false, diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 6fd8f06fe8f..1fd5f3c4395 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -297,7 +297,7 @@ where writeln!(w, "{}{:?}{}: {{", INDENT, block, cleanup_text)?; // List of statements in the middle. - let mut current_location = Location { block: block, statement_index: 0 }; + let mut current_location = Location { block, statement_index: 0 }; for statement in &data.statements { extra_data(PassWhere::BeforeLocation(current_location), w)?; let indented_body = format!("{0}{0}{1:?};", INDENT, statement); diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs index 56aa150dd37..80fa0c44860 100644 --- a/src/librustc_mir_build/build/matches/simplify.rs +++ b/src/librustc_mir_build/build/matches/simplify.rs @@ -113,7 +113,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // value being matched, taking the variance field into account. candidate.ascriptions.push(Ascription { span: user_ty_span, - user_ty: user_ty, + user_ty, source: match_pair.place, variance, }); diff --git a/src/librustc_mir_build/build/matches/test.rs b/src/librustc_mir_build/build/matches/test.rs index 9f450f8fc7b..d23a2708dc4 100644 --- a/src/librustc_mir_build/build/matches/test.rs +++ b/src/librustc_mir_build/build/matches/test.rs @@ -64,10 +64,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Slice { ref prefix, ref slice, ref suffix } => { let len = prefix.len() + suffix.len(); let op = if slice.is_some() { BinOp::Ge } else { BinOp::Eq }; - Test { - span: match_pair.pattern.span, - kind: TestKind::Len { len: len as u64, op: op }, - } + Test { span: match_pair.pattern.span, kind: TestKind::Len { len: len as u64, op } } } PatKind::Or { .. } => bug!("or-patterns should have already been handled"), diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index 830877f713e..b60a637471e 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -418,7 +418,7 @@ struct GuardFrameLocal { impl GuardFrameLocal { fn new(id: hir::HirId, _binding_mode: BindingMode) -> Self { - GuardFrameLocal { id: id } + GuardFrameLocal { id } } } diff --git a/src/librustc_mir_build/hair/cx/block.rs b/src/librustc_mir_build/hair/cx/block.rs index a883b84f8fe..8d7225c8c7b 100644 --- a/src/librustc_mir_build/hair/cx/block.rs +++ b/src/librustc_mir_build/hair/cx/block.rs @@ -84,7 +84,7 @@ fn mirror_stmts<'a, 'tcx>( result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { - remainder_scope: remainder_scope, + remainder_scope, init_scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node, diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index a3554ea2ee0..6b5e927214f 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2102,7 +2102,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { .is_ok() { let def_id = module.def_id().unwrap(); - found_traits.push(TraitCandidate { def_id: def_id, import_ids: smallvec![] }); + found_traits.push(TraitCandidate { def_id, import_ids: smallvec![] }); } } diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 193b6d75935..7281173e9db 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -1032,13 +1032,13 @@ struct Shadower { } fn original_label(span: Span) -> Original { - Original { kind: ShadowKind::Label, span: span } + Original { kind: ShadowKind::Label, span } } fn shadower_label(span: Span) -> Shadower { - Shadower { kind: ShadowKind::Label, span: span } + Shadower { kind: ShadowKind::Label, span } } fn original_lifetime(span: Span) -> Original { - Original { kind: ShadowKind::Lifetime, span: span } + Original { kind: ShadowKind::Lifetime, span } } fn shadower_lifetime(param: &hir::GenericParam<'_>) -> Shadower { Shadower { kind: ShadowKind::Lifetime, span: param.span } @@ -1347,7 +1347,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let missing_named_lifetime_spots = take(&mut self.missing_named_lifetime_spots); let mut this = LifetimeContext { tcx: *tcx, - map: map, + map, scope: &wrap_scope, trait_ref_hack: self.trait_ref_hack, is_in_fn_syntax: self.is_in_fn_syntax, diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 9da8ee548fd..ec251c224b6 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -334,7 +334,7 @@ impl<'l, 'tcx> SaveContext<'l, 'tcx> { Some(_) => ImplKind::Direct, None => ImplKind::Inherent, }, - span: span, + span, value: String::new(), parent: None, children: items diff --git a/src/librustc_save_analysis/sig.rs b/src/librustc_save_analysis/sig.rs index a295e1637aa..2005366f839 100644 --- a/src/librustc_save_analysis/sig.rs +++ b/src/librustc_save_analysis/sig.rs @@ -793,7 +793,7 @@ impl Sig for ast::ForeignItem { text.push_str(&name); text.push(';'); - Ok(Signature { text: text, defs: defs, refs: vec![] }) + Ok(Signature { text, defs, refs: vec![] }) } ast::ForeignItemKind::Macro(..) => Err("macro"), } diff --git a/src/librustc_session/code_stats.rs b/src/librustc_session/code_stats.rs index 9b89c7ae32a..c263da69c35 100644 --- a/src/librustc_session/code_stats.rs +++ b/src/librustc_session/code_stats.rs @@ -70,7 +70,7 @@ impl CodeStats { type_description: type_desc.to_string(), align: align.bytes(), overall_size: overall_size.bytes(), - packed: packed, + packed, opt_discr_size: opt_discr_size.map(|s| s.bytes()), variants, }; diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 6cdfd0500ca..66cdf46bd4e 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -130,7 +130,7 @@ impl DefId { /// Makes a local `DefId` from the given `DefIndex`. #[inline] pub fn local(index: DefIndex) -> DefId { - DefId { krate: LOCAL_CRATE, index: index } + DefId { krate: LOCAL_CRATE, index } } #[inline] diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index c2b2196e74c..8b1ba57e819 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -47,7 +47,7 @@ pub fn resolve_instance<'tcx>( } } }; - Some(Instance { def: def, substs: substs }) + Some(Instance { def, substs }) }; debug!("resolve(def_id={:?}, substs={:?}) = {:?}", def_id, substs, result); result diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index ff9fec004bb..7570d9d4b28 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -404,7 +404,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let needs = Needs::maybe_mut_place(mutbl); let ty = self.check_expr_with_expectation_and_needs(&oprnd, hint, needs); - let tm = ty::TypeAndMut { ty: ty, mutbl: mutbl }; + let tm = ty::TypeAndMut { ty, mutbl }; match kind { _ if tm.ty.references_error() => self.tcx.types.err, hir::BorrowKind::Raw => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d8b23998e72..d2f9f4e068a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -4234,7 +4234,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let substs = self.fresh_substs_for_item(span, did); let substd_ty = self.instantiate_type_scheme(span, &substs, &ity); - TypeAndSubsts { substs: substs, ty: substd_ty } + TypeAndSubsts { substs, ty: substd_ty } } /// Unifies the output type with the expected type early, for more coercions diff --git a/src/librustc_typeck/outlives/implicit_infer.rs b/src/librustc_typeck/outlives/implicit_infer.rs index fcbeb5b210d..44473fee643 100644 --- a/src/librustc_typeck/outlives/implicit_infer.rs +++ b/src/librustc_typeck/outlives/implicit_infer.rs @@ -31,10 +31,10 @@ pub fn infer_predicates<'tcx>( predicates_added = false; let mut visitor = InferVisitor { - tcx: tcx, + tcx, global_inferred_outlives: &mut global_inferred_outlives, predicates_added: &mut predicates_added, - explicit_map: explicit_map, + explicit_map, }; // Visit all the crates and infer predicates diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index becdeaba50f..41b8e66d265 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -44,7 +44,7 @@ impl Module<'hir> { vis: &'hir hir::Visibility<'hir>, ) -> Module<'hir> { Module { - name: name, + name, id: hir::CRATE_HIR_ID, vis, where_outer: rustc_span::DUMMY_SP, diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index d0e1a01b006..44f8e8bd171 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -2461,7 +2461,7 @@ impl RandomState { KEYS.with(|keys| { let (k0, k1) = keys.get(); keys.set((k0.wrapping_add(1), k1)); - RandomState { k0: k0, k1: k1 } + RandomState { k0, k1 } }) } } diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 9787cbb556b..f36aa1846a1 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -96,7 +96,7 @@ impl Cursor { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn new(inner: T) -> Cursor { - Cursor { pos: 0, inner: inner } + Cursor { pos: 0, inner } } /// Consumes this cursor, returning the underlying value. diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index a50dd9575de..0103e4bd628 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -371,7 +371,7 @@ where F: FnMut(&R) -> usize, { let start_len = buf.len(); - let mut g = Guard { len: buf.len(), buf: buf }; + let mut g = Guard { len: buf.len(), buf }; let ret; loop { if g.len == g.buf.len() { @@ -939,7 +939,7 @@ pub trait Read { where Self: Sized, { - Take { inner: self, limit: limit } + Take { inner: self, limit } } } diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 6eeddc28512..0cb16b19d73 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -416,7 +416,7 @@ impl fmt::Debug for Mutex { impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { unsafe fn new(lock: &'mutex Mutex) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock: lock, poison: guard }) + poison::map_result(lock.poison.borrow(), |guard| MutexGuard { lock, poison: guard }) } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index fdd29af8581..50f54dbf143 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -465,16 +465,13 @@ impl From for RwLock { impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock RwLock) -> LockResult> { - poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock: lock }) + poison::map_result(lock.poison.borrow(), |_| RwLockReadGuard { lock }) } } impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { unsafe fn new(lock: &'rwlock RwLock) -> LockResult> { - poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { - lock: lock, - poison: guard, - }) + poison::map_result(lock.poison.borrow(), |guard| RwLockWriteGuard { lock, poison: guard }) } } From 6fba412499e854d6c4cd8e6b22073d5684d549ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Mar 2020 10:55:21 -0800 Subject: [PATCH 0830/1250] Further tweak spans in ast validation errors --- src/librustc_ast_passes/ast_validation.rs | 59 +++++++++++++++---- src/test/ui/async-await/no-const-async.stderr | 4 +- src/test/ui/auto-trait-validation.stderr | 18 ++++-- src/test/ui/issues/issue-23080-2.rs | 3 +- src/test/ui/issues/issue-23080-2.stderr | 11 ++-- src/test/ui/issues/issue-23080.rs | 3 +- src/test/ui/issues/issue-23080.stderr | 13 ++-- .../ui/parser/fn-header-semantic-fail.stderr | 10 ++-- ...inductive-overflow-supertrait-oibit.stderr | 6 +- .../typeck-auto-trait-no-supertraits-2.stderr | 6 +- .../typeck-auto-trait-no-supertraits.stderr | 6 +- 11 files changed, 91 insertions(+), 48 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index d90e9c4df26..eff58ad4d9a 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -13,7 +13,7 @@ use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor}; use rustc_ast::walk_list; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{error_code, struct_span_err, Applicability}; +use rustc_errors::{error_code, pluralize, struct_span_err, Applicability}; use rustc_parse::validate_attr; use rustc_session::lint::builtin::PATTERNS_IN_FNS_WITHOUT_BODY; use rustc_session::lint::LintBuffer; @@ -887,30 +887,63 @@ impl<'a> Visitor<'a> for AstValidator<'a> { if is_auto == IsAuto::Yes { // Auto traits cannot have generics, super traits nor contain items. if !generics.params.is_empty() { - struct_span_err!( + let spans: Vec<_> = generics.params.iter().map(|i| i.ident.span).collect(); + let last = spans.iter().last().map(|s| *s); + let len = spans.len(); + let mut err = struct_span_err!( self.session, - item.span, + spans, E0567, "auto traits cannot have generic parameters" - ) - .emit(); + ); + if let Some(span) = last { + err.span_label( + span, + &format!( + "cannot have {these} generic parameter{s}", + these = if len == 1 { "this" } else { "these" }, + s = pluralize!(len) + ), + ); + } + err.span_label( + item.ident.span, + "auto trait cannot have generic parameters", + ); + err.emit(); } if !bounds.is_empty() { - struct_span_err!( + let spans: Vec<_> = bounds.iter().map(|b| b.span()).collect(); + let last = spans.iter().last().map(|s| *s); + let len = spans.len(); + let mut err = struct_span_err!( self.session, - item.span, + spans, E0568, "auto traits cannot have super traits" - ) - .emit(); + ); + if let Some(span) = last { + err.span_label( + span, + &format!( + "cannot have {these} super trait{s}", + these = if len == 1 { "this" } else { "these" }, + s = pluralize!(len) + ), + ); + } + err.span_label(item.ident.span, "auto trait cannot have super traits"); + err.emit(); } if !trait_items.is_empty() { + let spans: Vec<_> = trait_items.iter().map(|i| i.ident.span).collect(); struct_span_err!( self.session, - item.span, + spans, E0380, "auto traits cannot have methods or associated items" ) + .span_label(item.ident.span, "auto trait cannot have items") .emit(); } } @@ -1157,9 +1190,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }) = fk.header() { self.err_handler() - .struct_span_err(span, "functions cannot be both `const` and `async`") + .struct_span_err( + vec![*cspan, *aspan], + "functions cannot be both `const` and `async`", + ) .span_label(*cspan, "`const` because of this") .span_label(*aspan, "`async` because of this") + .span_label(span, "") // Point at the fn header. .emit(); } diff --git a/src/test/ui/async-await/no-const-async.stderr b/src/test/ui/async-await/no-const-async.stderr index 07559cd240b..4e59bb50767 100644 --- a/src/test/ui/async-await/no-const-async.stderr +++ b/src/test/ui/async-await/no-const-async.stderr @@ -1,8 +1,8 @@ error: functions cannot be both `const` and `async` - --> $DIR/no-const-async.rs:4:1 + --> $DIR/no-const-async.rs:4:5 | LL | pub const async fn x() {} - | ^^^^-----^-----^^^^^^^^^^ + | ----^^^^^-^^^^^---------- | | | | | `async` because of this | `const` because of this diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr index 51422fab81f..75919a1f991 100644 --- a/src/test/ui/auto-trait-validation.stderr +++ b/src/test/ui/auto-trait-validation.stderr @@ -1,20 +1,26 @@ error[E0567]: auto traits cannot have generic parameters - --> $DIR/auto-trait-validation.rs:3:1 + --> $DIR/auto-trait-validation.rs:3:20 | LL | auto trait Generic {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ------- ^ cannot have this generic parameter + | | + | auto trait cannot have generic parameters error[E0568]: auto traits cannot have super traits - --> $DIR/auto-trait-validation.rs:5:1 + --> $DIR/auto-trait-validation.rs:5:20 | LL | auto trait Bound : Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^ cannot have this super trait + | | + | auto trait cannot have super traits error[E0380]: auto traits cannot have methods or associated items - --> $DIR/auto-trait-validation.rs:7:1 + --> $DIR/auto-trait-validation.rs:7:25 | LL | auto trait MyTrait { fn foo() {} } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ------- ^^^ + | | + | auto trait cannot have items error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-23080-2.rs b/src/test/ui/issues/issue-23080-2.rs index 319aa2a5cce..d20bb4bd907 100644 --- a/src/test/ui/issues/issue-23080-2.rs +++ b/src/test/ui/issues/issue-23080-2.rs @@ -3,8 +3,7 @@ #![feature(optin_builtin_traits)] unsafe auto trait Trait { -//~^ ERROR E0380 - type Output; + type Output; //~ ERROR E0380 } fn call_method(x: T) {} diff --git a/src/test/ui/issues/issue-23080-2.stderr b/src/test/ui/issues/issue-23080-2.stderr index 1103de0d910..fcd1ecfa982 100644 --- a/src/test/ui/issues/issue-23080-2.stderr +++ b/src/test/ui/issues/issue-23080-2.stderr @@ -1,11 +1,10 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080-2.rs:5:1 + --> $DIR/issue-23080-2.rs:6:10 | -LL | / unsafe auto trait Trait { -LL | | -LL | | type Output; -LL | | } - | |_^ +LL | unsafe auto trait Trait { + | ----- auto trait cannot have items +LL | type Output; + | ^^^^^^ error[E0275]: overflow evaluating the requirement `<() as Trait>::Output` | diff --git a/src/test/ui/issues/issue-23080.rs b/src/test/ui/issues/issue-23080.rs index fdfee698144..fa5c35316bc 100644 --- a/src/test/ui/issues/issue-23080.rs +++ b/src/test/ui/issues/issue-23080.rs @@ -1,8 +1,7 @@ #![feature(optin_builtin_traits)] unsafe auto trait Trait { -//~^ ERROR E0380 - fn method(&self) { + fn method(&self) { //~ ERROR E0380 println!("Hello"); } } diff --git a/src/test/ui/issues/issue-23080.stderr b/src/test/ui/issues/issue-23080.stderr index 91c27217324..dbb9861b578 100644 --- a/src/test/ui/issues/issue-23080.stderr +++ b/src/test/ui/issues/issue-23080.stderr @@ -1,13 +1,10 @@ error[E0380]: auto traits cannot have methods or associated items - --> $DIR/issue-23080.rs:3:1 + --> $DIR/issue-23080.rs:4:8 | -LL | / unsafe auto trait Trait { -LL | | -LL | | fn method(&self) { -LL | | println!("Hello"); -LL | | } -LL | | } - | |_^ +LL | unsafe auto trait Trait { + | ----- auto trait cannot have items +LL | fn method(&self) { + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/fn-header-semantic-fail.stderr b/src/test/ui/parser/fn-header-semantic-fail.stderr index 1142cee9851..d6b36fbb714 100644 --- a/src/test/ui/parser/fn-header-semantic-fail.stderr +++ b/src/test/ui/parser/fn-header-semantic-fail.stderr @@ -2,7 +2,7 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:13:5 | LL | const async unsafe extern "C" fn ff5() {} // OK. - | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-^^^^^------------------------------ | | | | | `async` because of this | `const` because of this @@ -45,7 +45,7 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:21:9 | LL | const async unsafe extern "C" fn ft5(); - | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-^^^^^---------------------------- | | | | | `async` because of this | `const` because of this @@ -88,7 +88,7 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:34:9 | LL | const async unsafe extern "C" fn ft5() {} - | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-^^^^^------------------------------ | | | | | `async` because of this | `const` because of this @@ -97,7 +97,7 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:46:9 | LL | const async unsafe extern "C" fn fi5() {} - | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-^^^^^------------------------------ | | | | | `async` because of this | `const` because of this @@ -160,7 +160,7 @@ error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:55:9 | LL | const async unsafe extern "C" fn fe5(); - | -----^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^-^^^^^---------------------------- | | | | | `async` because of this | `const` because of this diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index 63182a6bd95..03d05f4c928 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -1,8 +1,10 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:1 + --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:7:19 | LL | auto trait Magic: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^ cannot have this super trait + | | + | auto trait cannot have super traits error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23 diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr index 8755bcded9d..45c95b191bd 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr @@ -1,8 +1,10 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:1 + --> $DIR/typeck-auto-trait-no-supertraits-2.rs:3:20 | LL | auto trait Magic : Sized where Option : Magic {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^^ cannot have this super trait + | | + | auto trait cannot have super traits error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr index 5a388834909..094f5d7dd24 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -1,8 +1,10 @@ error[E0568]: auto traits cannot have super traits - --> $DIR/typeck-auto-trait-no-supertraits.rs:27:1 + --> $DIR/typeck-auto-trait-no-supertraits.rs:27:19 | LL | auto trait Magic: Copy {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | ----- ^^^^ cannot have this super trait + | | + | auto trait cannot have super traits error: aborting due to previous error From 1631b4de1c951034654cc0684b38dcbd0708c902 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Thu, 5 Mar 2020 15:24:53 +0900 Subject: [PATCH 0831/1250] Avoid using `unwrap()` in suggestions --- src/librustc_typeck/check/method/suggest.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 95faa353e9b..084601fbde1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -547,10 +547,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (&self_ty.kind, parent_pred) { if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind { - let id = self.tcx.hir().as_local_hir_id(def.did).unwrap(); - let node = self.tcx.hir().get(id); + let node = self + .tcx + .hir() + .as_local_hir_id(def.did) + .map(|id| self.tcx.hir().get(id)); match node { - hir::Node::Item(hir::Item { kind, .. }) => { + Some(hir::Node::Item(hir::Item { kind, .. })) => { if let Some(g) = kind.generics() { let key = match &g.where_clause.predicates[..] { [.., pred] => { From 3d676492872d5e464e811a8f8d5afcd7122db089 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Sat, 7 Mar 2020 04:38:50 +0900 Subject: [PATCH 0832/1250] Add a regression test --- src/test/ui/issues/auxiliary/issue-69725.rs | 8 ++++++++ src/test/ui/issues/issue-69725.rs | 11 +++++++++++ src/test/ui/issues/issue-69725.stderr | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 src/test/ui/issues/auxiliary/issue-69725.rs create mode 100644 src/test/ui/issues/issue-69725.rs create mode 100644 src/test/ui/issues/issue-69725.stderr diff --git a/src/test/ui/issues/auxiliary/issue-69725.rs b/src/test/ui/issues/auxiliary/issue-69725.rs new file mode 100644 index 00000000000..13606e498ef --- /dev/null +++ b/src/test/ui/issues/auxiliary/issue-69725.rs @@ -0,0 +1,8 @@ +#[derive(Clone)] +pub struct Struct(A); + +impl Struct { + pub fn new() -> Self { + todo!() + } +} diff --git a/src/test/ui/issues/issue-69725.rs b/src/test/ui/issues/issue-69725.rs new file mode 100644 index 00000000000..b8130b41f21 --- /dev/null +++ b/src/test/ui/issues/issue-69725.rs @@ -0,0 +1,11 @@ +// aux-build:issue-69725.rs + +extern crate issue_69725; +use issue_69725::Struct; + +fn crash() { + let _ = Struct::::new().clone(); + //~^ ERROR: no method named `clone` found +} + +fn main() {} diff --git a/src/test/ui/issues/issue-69725.stderr b/src/test/ui/issues/issue-69725.stderr new file mode 100644 index 00000000000..667383e072a --- /dev/null +++ b/src/test/ui/issues/issue-69725.stderr @@ -0,0 +1,18 @@ +error[E0599]: no method named `clone` found for struct `issue_69725::Struct` in the current scope + --> $DIR/issue-69725.rs:7:32 + | +LL | let _ = Struct::::new().clone(); + | ^^^^^ method not found in `issue_69725::Struct` + | + ::: $DIR/auxiliary/issue-69725.rs:2:1 + | +LL | pub struct Struct(A); + | ------------------------ doesn't satisfy `issue_69725::Struct: std::clone::Clone` + | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `A: std::clone::Clone` + which is required by `issue_69725::Struct: std::clone::Clone` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From 005fc6eaccacd129e96e049a3342d1d539316433 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Mar 2020 11:45:00 -0800 Subject: [PATCH 0833/1250] Suggest removal of auto trait super traits and type params --- src/librustc_ast_passes/ast_validation.rs | 14 +++++++++++++- src/test/ui/auto-trait-validation.stderr | 10 ++++++++++ ...aits-inductive-overflow-supertrait-oibit.stderr | 5 +++++ .../typeck-auto-trait-no-supertraits-2.stderr | 5 +++++ .../typeck/typeck-auto-trait-no-supertraits.stderr | 5 +++++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index eff58ad4d9a..df229e57cf0 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -910,6 +910,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { item.ident.span, "auto trait cannot have generic parameters", ); + err.span_suggestion_verbose( + generics.span, + "remove the parameters for the auto trait to be valid", + String::new(), + Applicability::MachineApplicable, + ); err.emit(); } if !bounds.is_empty() { @@ -922,6 +928,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { E0568, "auto traits cannot have super traits" ); + err.span_label(item.ident.span, "auto trait cannot have super traits"); if let Some(span) = last { err.span_label( span, @@ -931,8 +938,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> { s = pluralize!(len) ), ); + err.span_suggestion_verbose( + generics.span.shrink_to_hi().to(span), + "remove the super traits for the auto trait to be valid", + String::new(), + Applicability::MachineApplicable, + ); } - err.span_label(item.ident.span, "auto trait cannot have super traits"); err.emit(); } if !trait_items.is_empty() { diff --git a/src/test/ui/auto-trait-validation.stderr b/src/test/ui/auto-trait-validation.stderr index 75919a1f991..17d9ca71d14 100644 --- a/src/test/ui/auto-trait-validation.stderr +++ b/src/test/ui/auto-trait-validation.stderr @@ -5,6 +5,11 @@ LL | auto trait Generic {} | ------- ^ cannot have this generic parameter | | | auto trait cannot have generic parameters + | +help: remove the parameters for the auto trait to be valid + | +LL | auto trait Generic {} + | -- error[E0568]: auto traits cannot have super traits --> $DIR/auto-trait-validation.rs:5:20 @@ -13,6 +18,11 @@ LL | auto trait Bound : Copy {} | ----- ^^^^ cannot have this super trait | | | auto trait cannot have super traits + | +help: remove the super traits for the auto trait to be valid + | +LL | auto trait Bound {} + | -- error[E0380]: auto traits cannot have methods or associated items --> $DIR/auto-trait-validation.rs:7:25 diff --git a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr index 03d05f4c928..8714cfbedbb 100644 --- a/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr +++ b/src/test/ui/traits/traits-inductive-overflow-supertrait-oibit.stderr @@ -5,6 +5,11 @@ LL | auto trait Magic: Copy {} | ----- ^^^^ cannot have this super trait | | | auto trait cannot have super traits + | +help: remove the super traits for the auto trait to be valid + | +LL | auto trait Magic {} + | -- error[E0277]: the trait bound `NoClone: std::marker::Copy` is not satisfied --> $DIR/traits-inductive-overflow-supertrait-oibit.rs:15:23 diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr index 45c95b191bd..c652a0c6df0 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits-2.stderr @@ -5,6 +5,11 @@ LL | auto trait Magic : Sized where Option : Magic {} | ----- ^^^^^ cannot have this super trait | | | auto trait cannot have super traits + | +help: remove the super traits for the auto trait to be valid + | +LL | auto trait Magic where Option : Magic {} + | -- error: aborting due to previous error diff --git a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr index 094f5d7dd24..fe6468bc716 100644 --- a/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr +++ b/src/test/ui/typeck/typeck-auto-trait-no-supertraits.stderr @@ -5,6 +5,11 @@ LL | auto trait Magic: Copy {} | ----- ^^^^ cannot have this super trait | | | auto trait cannot have super traits + | +help: remove the super traits for the auto trait to be valid + | +LL | auto trait Magic {} + | -- error: aborting due to previous error From f483032e97ba7c89f803fc6f8078f0acdd9d9b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 6 Mar 2020 11:58:52 -0800 Subject: [PATCH 0834/1250] review comment --- src/librustc_ast_passes/ast_validation.rs | 25 +++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index df229e57cf0..24cf4556dad 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -820,23 +820,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ref self_ty, items: _, } => { - let error = |annotation_span, annotation, note, code| { + let error = |annotation_span, annotation| { let mut err = self.err_handler().struct_span_err( self_ty.span, &format!("inherent impls cannot be {}", annotation), ); err.span_label(annotation_span, &format!("{} because of this", annotation)); err.span_label(self_ty.span, "inherent impl for this type"); - if note { - err.note(&format!( - "only trait implementations may be annotated with {}", - annotation - )); - } - if code { - err.code(error_code!(E0197)); - } - err.emit(); + err }; self.invalid_visibility( @@ -844,16 +835,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { Some("place qualifiers on individual impl items instead"), ); if let Unsafe::Yes(span) = unsafety { - error(span, "unsafe", false, true) + error(span, "unsafe").code(error_code!(E0197)).emit(); } if let ImplPolarity::Negative(span) = polarity { - error(span, "negative", false, false); + error(span, "negative").emit(); } if let Defaultness::Default(def_span) = defaultness { - error(def_span, "`default`", true, false); + error(def_span, "`default`") + .note("only trait implementations may be annotated with `default`") + .emit(); } if let Const::Yes(span) = constness { - error(span, "`const`", true, false); + error(span, "`const`") + .note("only trait implementations may be annotated with `const`") + .emit(); } } ItemKind::Fn(def, ref sig, ref generics, ref body) => { From 33ebc20513c692691216ee1924d5cd29aca6f6aa Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 28 Feb 2020 14:10:33 +0100 Subject: [PATCH 0835/1250] Turn trailing tokens in `assert!()` into hard errors --- src/librustc_builtin_macros/assert.rs | 12 ++++-------- src/test/ui/macros/assert-trailing-junk.rs | 6 +++--- src/test/ui/macros/assert-trailing-junk.stderr | 14 ++++---------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/librustc_builtin_macros/assert.rs b/src/librustc_builtin_macros/assert.rs index 5da4a540940..09ff770e87b 100644 --- a/src/librustc_builtin_macros/assert.rs +++ b/src/librustc_builtin_macros/assert.rs @@ -80,17 +80,15 @@ fn parse_assert<'a>( // my_function(); // ); // - // Warn about semicolon and suggest removing it. Eventually, this should be turned into an - // error. + // Emit an error about semicolon and suggest removing it. if parser.token == token::Semi { - let mut err = cx.struct_span_warn(sp, "macro requires an expression as an argument"); + let mut err = cx.struct_span_err(sp, "macro requires an expression as an argument"); err.span_suggestion( parser.token.span, "try removing semicolon", String::new(), Applicability::MaybeIncorrect, ); - err.note("this is going to be an error in the future"); err.emit(); parser.bump(); @@ -101,11 +99,10 @@ fn parse_assert<'a>( // // assert!(true "error message"); // - // Parse this as an actual message, and suggest inserting a comma. Eventually, this should be - // turned into an error. + // Emit an error and suggest inserting a comma. let custom_message = if let token::Literal(token::Lit { kind: token::Str, .. }) = parser.token.kind { - let mut err = cx.struct_span_warn(parser.token.span, "unexpected string literal"); + let mut err = cx.struct_span_err(parser.token.span, "unexpected string literal"); let comma_span = parser.prev_token.span.shrink_to_hi(); err.span_suggestion_short( comma_span, @@ -113,7 +110,6 @@ fn parse_assert<'a>( ", ".to_string(), Applicability::MaybeIncorrect, ); - err.note("this is going to be an error in the future"); err.emit(); parse_custom_message(&mut parser) diff --git a/src/test/ui/macros/assert-trailing-junk.rs b/src/test/ui/macros/assert-trailing-junk.rs index 676ae05bf0f..cd7faf9bf8b 100644 --- a/src/test/ui/macros/assert-trailing-junk.rs +++ b/src/test/ui/macros/assert-trailing-junk.rs @@ -13,12 +13,12 @@ fn main() { //~^ ERROR no rules expected assert!(true "whatever" blah); - //~^ WARN unexpected string literal + //~^ ERROR unexpected string literal //~^^ ERROR no rules expected assert!(true;); - //~^ WARN macro requires an expression + //~^ ERROR macro requires an expression assert!(false || true "error message"); - //~^ WARN unexpected string literal + //~^ ERROR unexpected string literal } diff --git a/src/test/ui/macros/assert-trailing-junk.stderr b/src/test/ui/macros/assert-trailing-junk.stderr index 4d18a531a80..84a6768b3f4 100644 --- a/src/test/ui/macros/assert-trailing-junk.stderr +++ b/src/test/ui/macros/assert-trailing-junk.stderr @@ -18,15 +18,13 @@ LL | assert!(true, "whatever" blah); | | | help: missing comma here -warning: unexpected string literal +error: unexpected string literal --> $DIR/assert-trailing-junk.rs:15:18 | LL | assert!(true "whatever" blah); | -^^^^^^^^^^ | | | help: try adding a comma - | - = note: this is going to be an error in the future error: no rules expected the token `blah` --> $DIR/assert-trailing-junk.rs:15:29 @@ -36,25 +34,21 @@ LL | assert!(true "whatever" blah); | | | help: missing comma here -warning: macro requires an expression as an argument +error: macro requires an expression as an argument --> $DIR/assert-trailing-junk.rs:19:5 | LL | assert!(true;); | ^^^^^^^^^^^^-^^ | | | help: try removing semicolon - | - = note: this is going to be an error in the future -warning: unexpected string literal +error: unexpected string literal --> $DIR/assert-trailing-junk.rs:22:27 | LL | assert!(false || true "error message"); | -^^^^^^^^^^^^^^^ | | | help: try adding a comma - | - = note: this is going to be an error in the future -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors From 0ed6e795fb3e8e70765576b929e3eb030c4f10d3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 6 Mar 2020 18:22:17 -0300 Subject: [PATCH 0836/1250] mir::Local is Copy we can pass it by value in these cases --- src/librustc/mir/visit.rs | 10 +++++----- src/librustc_codegen_ssa/mir/analyze.rs | 2 +- .../transform/check_consts/validation.rs | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 409c981801b..2aca6f684f4 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -888,7 +888,7 @@ macro_rules! visit_place_fns { () => ( fn visit_projection( &mut self, - local: &Local, + local: Local, projection: &[PlaceElem<'tcx>], context: PlaceContext, location: Location, @@ -898,7 +898,7 @@ macro_rules! visit_place_fns { fn visit_projection_elem( &mut self, - local: &Local, + local: Local, proj_base: &[PlaceElem<'tcx>], elem: &PlaceElem<'tcx>, context: PlaceContext, @@ -925,7 +925,7 @@ macro_rules! visit_place_fns { self.visit_place_base(&place.local, context, location); - self.visit_projection(&place.local, + self.visit_projection(place.local, &place.projection, context, location); @@ -933,7 +933,7 @@ macro_rules! visit_place_fns { fn super_projection( &mut self, - local: &Local, + local: Local, projection: &[PlaceElem<'tcx>], context: PlaceContext, location: Location, @@ -947,7 +947,7 @@ macro_rules! visit_place_fns { fn super_projection_elem( &mut self, - _local: &Local, + _local: Local, _proj_base: &[PlaceElem<'tcx>], elem: &PlaceElem<'tcx>, _context: PlaceContext, diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 7bf222f4701..b8a7d7df487 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -203,7 +203,7 @@ impl> LocalAnalyzer<'mir, 'a, 'tcx, Bx> { } self.visit_place_base(&place_ref.local, context, location); - self.visit_projection(&place_ref.local, place_ref.projection, context, location); + self.visit_projection(place_ref.local, place_ref.projection, context, location); } } } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 1553f826c7e..133772407c5 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -276,7 +276,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } }; self.visit_place_base(&place.local, ctx, location); - self.visit_projection(&place.local, reborrowed_proj, ctx, location); + self.visit_projection(place.local, reborrowed_proj, ctx, location); return; } } @@ -289,7 +289,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { Mutability::Mut => PlaceContext::MutatingUse(MutatingUseContext::AddressOf), }; self.visit_place_base(&place.local, ctx, location); - self.visit_projection(&place.local, reborrowed_proj, ctx, location); + self.visit_projection(place.local, reborrowed_proj, ctx, location); return; } } @@ -408,7 +408,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { } fn visit_projection_elem( &mut self, - place_local: &Local, + place_local: Local, proj_base: &[PlaceElem<'tcx>], elem: &PlaceElem<'tcx>, context: PlaceContext, @@ -428,11 +428,11 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { match elem { ProjectionElem::Deref => { - let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty; if let ty::RawPtr(_) = base_ty.kind { if proj_base.is_empty() { if let (local, []) = (place_local, proj_base) { - let decl = &self.body.local_decls[*local]; + let decl = &self.body.local_decls[local]; if let LocalInfo::StaticRef { def_id, .. } = decl.local_info { let span = decl.source_info.span; self.check_static(def_id, span); @@ -452,7 +452,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { | ProjectionElem::Subslice { .. } | ProjectionElem::Field(..) | ProjectionElem::Index(_) => { - let base_ty = Place::ty_from(*place_local, proj_base, *self.body, self.tcx).ty; + let base_ty = Place::ty_from(place_local, proj_base, *self.body, self.tcx).ty; match base_ty.ty_adt_def() { Some(def) if def.is_union() => { self.check_op(ops::UnionAccess); From 6548be2ba95c29cfd0f3324f4b314a64853b2f57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 11:45:02 +0100 Subject: [PATCH 0837/1250] 'fieldless enums' is not what I meant -- it's empty/uninhabited enums, really --- src/librustc_mir/interpret/validity.rs | 3 +-- src/librustc_target/abi/mod.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 731dcc6a25f..8989da9a91a 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -579,13 +579,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } // Check primitive types. We do this after checking for uninhabited types, - // to exclude fieldless enums (that also appear as fieldless unions here). + // to exclude uninhabited enums (that also appear as fieldless unions here). // Primitives can have varying layout, so we check them separately and before aggregate // handling. // It is CRITICAL that we get this check right, or we might be validating the wrong thing! let primitive = match op.layout.fields { // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - // (Fieldless enums also appear here, but they are uninhabited and thus handled above.) layout::FieldPlacement::Union(0) => true, _ => op.layout.ty.builtin_deref(true).is_some(), }; diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index ffef38cedfc..316e07425c5 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -872,7 +872,7 @@ impl Niche { #[derive(PartialEq, Eq, Hash, Debug, HashStable_Generic)] pub struct LayoutDetails { /// Says where the fields are located within the layout. - /// Primitives and fieldless enums appear as unions without fields. + /// Primitives and uninhabited enums appear as unions without fields. pub fields: FieldPlacement, /// Encodes information about multi-variant layouts. From d47196b2ec23a26c03b1546449f29300d42a4840 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 13:09:13 +0100 Subject: [PATCH 0838/1250] miri value visitor: detect primitives by type, not layout --- src/librustc_mir/interpret/validity.rs | 284 ++++++++++-------- .../ui/consts/const-eval/ub-uninhabit.stderr | 2 +- .../validate_uninhabited_zsts.stderr | 2 +- .../ui/consts/validate_never_arrays.stderr | 6 +- 4 files changed, 163 insertions(+), 131 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 8989da9a91a..defb490199b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -306,23 +306,119 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(()) } - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + /// Check a reference or `Box`. + fn check_safe_pointer(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; + // Handle wide pointers. + // Check metadata early, for better diagnostics + let place = try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + if place.layout.is_unsized() { + self.check_wide_ptr_meta(place.meta, place.layout)?; + } + // Make sure this is dereferenceable and all. + let (size, align) = self + .ecx + .size_and_align_of(place.meta, place.layout)? + // for the purpose of validity, consider foreign types to have + // alignment and size determined by the layout (size will be 0, + // alignment should take attributes into account). + .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); + let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( + place.ptr, + size, + Some(align), + CheckInAllocMsg::InboundsTest, + ) { + Ok(ptr) => ptr, + Err(err) => { + info!( + "{:?} did not pass access check for size {:?}, align {:?}", + place.ptr, size, align + ); + match err.kind { + err_unsup!(InvalidNullPointerUsage) => { + throw_validation_failure!("a NULL reference", self.path) + } + err_unsup!(AlignmentCheckFailed { required, has }) => { + throw_validation_failure!( + format_args!( + "an unaligned reference \ + (required {} byte alignment but found {})", + required.bytes(), + has.bytes() + ), + self.path + ) + } + err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( + "a dangling reference (created from integer)", + self.path + ), + _ => throw_validation_failure!( + "a dangling reference (not entirely in bounds)", + self.path + ), + } + } + }; + // Recursive checking + if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { + if let Some(ptr) = ptr { + // not a ZST + // Skip validation entirely for some external statics + let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); + if let Some(GlobalAlloc::Static(did)) = alloc_kind { + // `extern static` cannot be validated as they have no body. + // FIXME: Statics from other crates are also skipped. + // They might be checked at a different type, but for now we + // want to avoid recursing too deeply. This is not sound! + if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { + return Ok(()); + } + } + } + // Proceed recursively even for ZST, no reason to skip them! + // `!` is a ZST and we want to validate it. + // Normalize before handing `place` to tracking because that will + // check for duplicates. + let place = if size.bytes() > 0 { + self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") + } else { + place + }; + let path = &self.path; + ref_tracking.track(place, || { + // We need to clone the path anyway, make sure it gets created + // with enough space for the additional `Deref`. + let mut new_path = Vec::with_capacity(path.len() + 1); + new_path.clone_from(path); + new_path.push(PathElem::Deref); + new_path + }); + } + Ok(()) + } + + /// Check if this is a value of primitive type, and if yes check the validity of the value + /// at that type. Return `true` if the type is indeed primitive. + fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { ty::Bool => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_bool(), value, self.path, "a boolean"); + Ok(true) } ty::Char => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; try_validation!(value.to_char(), value, self.path, "a valid unicode codepoint"); + Ok(true) } ty::Float(_) | ty::Int(_) | ty::Uint(_) => { + let value = self.ecx.read_scalar(value)?; // NOTE: Keep this in sync with the array optimization for int/float // types below! - let value = value.to_scalar_or_undef(); if self.ref_tracking_for_consts.is_some() { // Integers/floats in CTFE: Must be scalar bits, pointers are dangerous let is_bits = value.not_undef().map_or(false, |v| v.is_bits()); @@ -337,108 +433,32 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // At run-time, for now, we accept *anything* for these types, including // undef. We should fix that, but let's start low. } + Ok(true) } ty::RawPtr(..) => { // We are conservative with undef for integers, but try to // actually enforce our current rules for raw pointers. - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); + let place = try_validation!( + self.ecx.ref_to_mplace(self.ecx.read_immediate(value)?), + "undefined pointer", + self.path + ); if place.layout.is_unsized() { self.check_wide_ptr_meta(place.meta, place.layout)?; } + Ok(true) } - _ if ty.is_box() || ty.is_region_ptr() => { - // Handle wide pointers. - // Check metadata early, for better diagnostics - let place = - try_validation!(self.ecx.ref_to_mplace(value), "undefined pointer", self.path); - if place.layout.is_unsized() { - self.check_wide_ptr_meta(place.meta, place.layout)?; - } - // Make sure this is dereferenceable and all. - let (size, align) = self - .ecx - .size_and_align_of(place.meta, place.layout)? - // for the purpose of validity, consider foreign types to have - // alignment and size determined by the layout (size will be 0, - // alignment should take attributes into account). - .unwrap_or_else(|| (place.layout.size, place.layout.align.abi)); - let ptr: Option<_> = match self.ecx.memory.check_ptr_access_align( - place.ptr, - size, - Some(align), - CheckInAllocMsg::InboundsTest, - ) { - Ok(ptr) => ptr, - Err(err) => { - info!( - "{:?} did not pass access check for size {:?}, align {:?}", - place.ptr, size, align - ); - match err.kind { - err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("a NULL reference", self.path) - } - err_unsup!(AlignmentCheckFailed { required, has }) => { - throw_validation_failure!( - format_args!( - "an unaligned reference \ - (required {} byte alignment but found {})", - required.bytes(), - has.bytes() - ), - self.path - ) - } - err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "a dangling reference (created from integer)", - self.path - ), - _ => throw_validation_failure!( - "a dangling reference (not entirely in bounds)", - self.path - ), - } - } - }; - // Recursive checking - if let Some(ref mut ref_tracking) = self.ref_tracking_for_consts { - if let Some(ptr) = ptr { - // not a ZST - // Skip validation entirely for some external statics - let alloc_kind = self.ecx.tcx.alloc_map.lock().get(ptr.alloc_id); - if let Some(GlobalAlloc::Static(did)) = alloc_kind { - // `extern static` cannot be validated as they have no body. - // FIXME: Statics from other crates are also skipped. - // They might be checked at a different type, but for now we - // want to avoid recursing too deeply. This is not sound! - if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { - return Ok(()); - } - } - } - // Proceed recursively even for ZST, no reason to skip them! - // `!` is a ZST and we want to validate it. - // Normalize before handing `place` to tracking because that will - // check for duplicates. - let place = if size.bytes() > 0 { - self.ecx.force_mplace_ptr(place).expect("we already bounds-checked") - } else { - place - }; - let path = &self.path; - ref_tracking.track(place, || { - // We need to clone the path anyway, make sure it gets created - // with enough space for the additional `Deref`. - let mut new_path = Vec::with_capacity(path.len() + 1); - new_path.clone_from(path); - new_path.push(PathElem::Deref); - new_path - }); - } + ty::Ref(..) => { + self.check_safe_pointer(value)?; + Ok(true) + } + ty::Adt(def, ..) if def.is_box() => { + // FIXME make sure we have a test for `Box`! + self.check_safe_pointer(value)?; + Ok(true) } ty::FnPtr(_sig) => { - let value = value.to_scalar_or_undef(); + let value = self.ecx.read_scalar(value)?; let _fn = try_validation!( value.not_undef().and_then(|ptr| self.ecx.memory.get_fn(ptr)), value, @@ -446,11 +466,35 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M "a function pointer" ); // FIXME: Check if the signature matches + Ok(true) } - // This should be all the (inhabited) primitive types - _ => bug!("Unexpected primitive type {}", value.layout.ty), + ty::Never => throw_validation_failure!("a value of the never type `!`", self.path), + ty::Foreign(..) | ty::FnDef(..) => { + // Nothing to check. + Ok(true) + } + // This should be all the (inhabited) primitive types. The rest is compound, we + // check them by visiting their fields/variants. + // (`Str` UTF-8 check happens in `visit_aggregate`, too.) + ty::Adt(..) + | ty::Tuple(..) + | ty::Array(..) + | ty::Slice(..) + | ty::Str + | ty::Dynamic(..) + | ty::Closure(..) + | ty::Generator(..) + | ty::GeneratorWitness(..) => Ok(false), + // Some types only occur during inference, we should not see them here. + ty::Error + | ty::Infer(..) + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Param(..) + | ty::Opaque(..) + | ty::UnnormalizedProjection(..) + | ty::Projection(..) => bug!("Encountered invalid type {:?}", ty), } - Ok(()) } fn visit_scalar( @@ -558,11 +602,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } #[inline(always)] - fn visit_union(&mut self, _v: Self::V, fields: usize) -> InterpResult<'tcx> { - // Empty unions are not accepted by rustc. That's great, it means we can - // use that as a signal for detecting primitives. Make sure - // we did not miss any primitive. - assert!(fields > 0); + fn visit_union(&mut self, op: OpTy<'tcx, M::PointerTag>, fields: usize) -> InterpResult<'tcx> { + // Empty unions are not accepted by rustc. But uninhabited enums + // claim to be unions, so allow them, too. + assert!(op.layout.abi.is_uninhabited() || fields > 0); Ok(()) } @@ -570,28 +613,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> fn visit_value(&mut self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { trace!("visit_value: {:?}, {:?}", *op, op.layout); - if op.layout.abi.is_uninhabited() { - // Uninhabited types do not have sensible layout, stop right here. - throw_validation_failure!( - format_args!("a value of uninhabited type {:?}", op.layout.ty), - self.path - ) - } - - // Check primitive types. We do this after checking for uninhabited types, - // to exclude uninhabited enums (that also appear as fieldless unions here). - // Primitives can have varying layout, so we check them separately and before aggregate - // handling. - // It is CRITICAL that we get this check right, or we might be validating the wrong thing! - let primitive = match op.layout.fields { - // Primitives appear as Union with 0 fields - except for Boxes and fat pointers. - layout::FieldPlacement::Union(0) => true, - _ => op.layout.ty.builtin_deref(true).is_some(), - }; - if primitive { - // No need to recurse further or check scalar layout, this is a leaf type. - return self.visit_primitive(op); + // Check primitive types -- the leafs of our recursive descend. + if self.visit_primitive(op)? { + return Ok(()); } + // Sanity check: `builtin_deref` does not know any pointers that are not primitive. + assert!(op.layout.ty.builtin_deref(true).is_none()); // Recursively walk the type. Translate some possible errors to something nicer. match self.walk_value(op) { @@ -618,7 +645,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). match op.layout.abi { - layout::Abi::Uninhabited => unreachable!(), // checked above + layout::Abi::Uninhabited => { + throw_validation_failure!( + format_args!("a value of uninhabited type {:?}", op.layout.ty), + self.path + ); + } layout::Abi::Scalar(ref scalar_layout) => { self.visit_scalar(op, scalar_layout)?; } diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 4fef9aa84ea..350d8353fef 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Bar; 1] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr index 2a338e27640..d0e35615dab 100644 --- a/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr +++ b/src/test/ui/consts/const-eval/validate_uninhabited_zsts.stderr @@ -20,7 +20,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_uninhabited_zsts.rs:17:1 | LL | const BAR: [Empty; 3] = [unsafe { std::mem::transmute(()) }; 3]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [Empty; 3] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Empty at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/validate_never_arrays.stderr b/src/test/ui/consts/validate_never_arrays.stderr index 203620a771b..77f0a2ebd40 100644 --- a/src/test/ui/consts/validate_never_arrays.stderr +++ b/src/test/ui/consts/validate_never_arrays.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:3:1 | LL | const _: &[!; 1] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type [!; 1] at . + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:6:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 1]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/validate_never_arrays.rs:7:1 | LL | const _: &[!] = unsafe { &*(1_usize as *const [!; 42]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type ! at .[0] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at .[0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From aa1435b0aef77e0eeb8604fd0eed578772ff7e27 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 20:37:33 +0100 Subject: [PATCH 0839/1250] const validation ub tests: use transmute instead of unions --- src/test/ui/consts/const-eval/ub-enum.rs | 49 +++---- src/test/ui/consts/const-eval/ub-enum.stderr | 52 +++---- src/test/ui/consts/const-eval/ub-nonnull.rs | 6 +- .../ui/consts/const-eval/ub-nonnull.stderr | 4 +- src/test/ui/consts/const-eval/ub-uninhabit.rs | 10 +- .../ui/consts/const-eval/ub-uninhabit.stderr | 8 +- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 129 ++++++------------ .../ui/consts/const-eval/ub-wide-ptr.stderr | 128 +++++++++-------- 8 files changed, 165 insertions(+), 221 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 483285aa4e1..4e7c7be4a76 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,5 +1,7 @@ +#![feature(const_transmute)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; #[repr(transparent)] #[derive(Copy, Clone)] @@ -10,23 +12,16 @@ struct Wrap(T); enum Enum { A = 0, } -#[repr(C)] -union TransmuteEnum { - in1: &'static u8, - in2: usize, - out1: Enum, - out2: Wrap, -} -const GOOD_ENUM: Enum = unsafe { TransmuteEnum { in2: 0 }.out1 }; +const GOOD_ENUM: Enum = unsafe { mem::transmute(0usize) }; -const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; +const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; +const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior -const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; +const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior // (Potentially) invalid enum discriminant @@ -36,39 +31,31 @@ enum Enum2 { A = 2, } -#[repr(C)] -union TransmuteEnum2 { - in1: usize, - in2: &'static u8, - in3: (), - out1: Enum2, - out2: Wrap, // something wrapping the enum so that we test layout first, not enum - out3: Option, -} -const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; +const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; +const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior -const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; +// something wrapping the enum so that we test layout first, not enum +const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior // Undef enum discriminant. -const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; +#[repr(C)] +union MaybeUninit { + uninit: (), + init: T, +} +const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR is undefined behavior // Pointer value in an enum with a niche that is not just 0. -const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; +const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). -#[repr(C)] -union TransmuteChar { - a: u32, - b: char, -} // Need to create something which does not clash with enum layout optimizations. -const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); +const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior fn main() { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8c47d68e968..95d4155be91 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,72 +1,72 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:23:1 + --> $DIR/ub-enum.rs:18:1 | -LL | const BAD_ENUM: Enum = unsafe { TransmuteEnum { in2: 1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant +LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:26:1 + --> $DIR/ub-enum.rs:21:1 | -LL | const BAD_ENUM_PTR: Enum = unsafe { TransmuteEnum { in1: &1 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:24:1 | -LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { TransmuteEnum { in1: &1 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:34:1 | -LL | const BAD_ENUM2: Enum2 = unsafe { TransmuteEnum2 { in1: 0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant +LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:50:1 + --> $DIR/ub-enum.rs:36:1 | -LL | const BAD_ENUM2_PTR: Enum2 = unsafe { TransmuteEnum2 { in2: &0 }.out1 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:52:1 + --> $DIR/ub-enum.rs:39:1 | -LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { TransmuteEnum2 { in2: &0 }.out2 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:56:1 + --> $DIR/ub-enum.rs:48:1 | -LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { TransmuteEnum2 { in3: () }.out1 }; +LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:60:1 + --> $DIR/ub-enum.rs:52:1 | -LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { TransmuteEnum2 { in2: &0 }.out3 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes +LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:71:1 + --> $DIR/ub-enum.rs:58:1 | -LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint +LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-nonnull.rs b/src/test/ui/consts/const-eval/ub-nonnull.rs index 8ce64ced7df..1f46b6c98ad 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.rs +++ b/src/test/ui/consts/const-eval/ub-nonnull.rs @@ -25,11 +25,11 @@ const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value #[repr(C)] -union Transmute { +union MaybeUninit { uninit: (), - out: NonZeroU8, + init: T, } -const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; +const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value // Also test other uses of rustc_layout_scalar_valid_range_start diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index ec056187057..edfc7ac837f 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -43,8 +43,8 @@ LL | const NULL_USIZE: NonZeroUsize = unsafe { mem::transmute(0usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-nonnull.rs:32:1 | -LL | const UNINIT: NonZeroU8 = unsafe { Transmute { uninit: () }.out }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes +LL | const UNINIT: NonZeroU8 = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at .0, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.rs b/src/test/ui/consts/const-eval/ub-uninhabit.rs index d2745d71bdb..e7350ae2716 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.rs +++ b/src/test/ui/consts/const-eval/ub-uninhabit.rs @@ -7,18 +7,18 @@ use std::mem; enum Bar {} #[repr(C)] -union TransmuteUnion { - a: A, - b: B, +union MaybeUninit { + uninit: (), + init: T, } -const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; +const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; //~^ ERROR it is undefined behavior to use this value -const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; +const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; //~^ ERROR it is undefined behavior to use this value fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-uninhabit.stderr b/src/test/ui/consts/const-eval/ub-uninhabit.stderr index 350d8353fef..8ce4279a8b7 100644 --- a/src/test/ui/consts/const-eval/ub-uninhabit.stderr +++ b/src/test/ui/consts/const-eval/ub-uninhabit.stderr @@ -1,8 +1,8 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:15:1 | -LL | const BAD_BAD_BAD: Bar = unsafe { (TransmuteUnion::<(), Bar> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar +LL | const BAD_BAD_BAD: Bar = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -17,8 +17,8 @@ LL | const BAD_BAD_REF: &Bar = unsafe { mem::transmute(1usize) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-uninhabit.rs:21:1 | -LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { (TransmuteUnion::<(), [Bar; 1]> { a: () }).b }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] +LL | const BAD_BAD_ARRAY: [Bar; 1] = unsafe { MaybeUninit { uninit: () }.init }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Bar at [0] | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index a5c2a57c6c8..ada82fc83a8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -1,72 +1,18 @@ // ignore-tidy-linelength +#![feature(const_transmute)] #![allow(unused)] #![allow(const_err)] // make sure we cannot allow away the errors tested here +use std::mem; + // normalize-stderr-test "offset \d+" -> "offset N" // normalize-stderr-test "allocation \d+" -> "allocation N" // normalize-stderr-test "size \d+" -> "size N" #[repr(C)] -union BoolTransmute { - val: u8, - bl: bool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct SliceRepr { - ptr: *const u8, - len: usize, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadSliceRepr { - ptr: *const u8, - len: &'static u8, -} - -#[repr(C)] -union SliceTransmute { - repr: SliceRepr, - bad: BadSliceRepr, - addr: usize, - slice: &'static [u8], - raw_slice: *const [u8], - str: &'static str, - my_str: &'static MyStr, - my_slice: &'static MySliceBool, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr { - ptr: *const u8, - vtable: *const u8, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct DynRepr2 { - ptr: *const u8, - vtable: *const u64, -} - -#[repr(C)] -#[derive(Copy, Clone)] -struct BadDynRepr { - ptr: *const u8, - vtable: usize, -} - -#[repr(C)] -union DynTransmute { - repr: DynRepr, - repr2: DynRepr2, - bad: BadDynRepr, - addr: usize, - rust: &'static dyn Trait, - raw_rust: *const dyn Trait, +union MaybeUninit { + uninit: (), + init: T, } trait Trait {} @@ -81,90 +27,93 @@ type MySliceBool = MySlice<[bool]>; // # str // OK -const STR_VALID: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.str}; +const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) }; // bad str -const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; +const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad str -const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; +const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type -const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; +const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 -const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; +const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // invalid UTF-8 in user-defined str-like -const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; +const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; //~^ ERROR it is undefined behavior to use this value // # slice // OK -const SLICE_VALID: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.slice}; +const SLICE_VALID: &[u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // bad slice: length uninit -const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; +const SLICE_LENGTH_UNINIT: &[u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // bad slice: length too big -const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; +const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value // bad slice: length not an int -const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; +const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice -const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; +const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; //~^ ERROR it is undefined behavior to use this value // good MySliceBool const MYSLICE_GOOD: &MySliceBool = &MySlice(true, [false]); // bad: sized field is not okay -const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); +const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); //~^ ERROR it is undefined behavior to use this value // bad: unsized part is not okay -const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); +const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); //~^ ERROR it is undefined behavior to use this value // # raw slice -const RAW_SLICE_VALID: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 1 } }.raw_slice}; // ok -const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.raw_slice}; // ok because raw -const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: usize::max_value() } }.raw_slice}; // ok because raw -const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; +const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok +const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw +const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { //~^ ERROR it is undefined behavior to use this value + let uninit_len = MaybeUninit:: { uninit: () }; + mem::transmute((42, uninit_len)) +}; // # trait object // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; +const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value // bad trait object -const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; +const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; //~^ ERROR it is undefined behavior to use this value // bad data *inside* the trait object -const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; +const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; //~^ ERROR it is undefined behavior to use this value // # raw trait object -const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; +const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; //~^ ERROR it is undefined behavior to use this value -const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl } as *const _; // ok because raw +const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw // Const eval fails for these, so they need to be statics to error. static mut RAW_TRAIT_OBJ_VTABLE_NULL_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) //~^ ERROR could not evaluate static initializer }; static mut RAW_TRAIT_OBJ_VTABLE_INVALID_THROUGH_REF: *const dyn Trait = unsafe { - DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust + mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) //~^ ERROR could not evaluate static initializer }; -fn main() { - let _ = RAW_TRAIT_OBJ_VTABLE_NULL; - let _ = RAW_TRAIT_OBJ_VTABLE_INVALID; -} +fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 4da9ad6c332..2a3ae7dfe6d 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -1,158 +1,166 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:86:1 + --> $DIR/ub-wide-ptr.rs:32:1 | -LL | const STR_TOO_LONG: &str = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) +LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:89:1 + --> $DIR/ub-wide-ptr.rs:35:1 | -LL | const STR_LENGTH_PTR: &str = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:92:1 + --> $DIR/ub-wide-ptr.rs:38:1 | -LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.my_str}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:96:1 + --> $DIR/ub-wide-ptr.rs:42:1 | -LL | const STR_NO_UTF8: &str = unsafe { SliceTransmute { slice: &[0xFF] }.str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:99:1 + --> $DIR/ub-wide-ptr.rs:45:1 | -LL | const MYSTR_NO_UTF8: &MyStr = unsafe { SliceTransmute { slice: &[0xFF] }.my_str }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:106:1 + --> $DIR/ub-wide-ptr.rs:52:1 | -LL | const SLICE_LENGTH_UNINIT: &[u8] = unsafe { SliceTransmute { addr: 42 }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer +LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:109:1 + --> $DIR/ub-wide-ptr.rs:58:1 | -LL | const SLICE_TOO_LONG: &[u8] = unsafe { SliceTransmute { repr: SliceRepr { ptr: &42, len: 999 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) +LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:112:1 + --> $DIR/ub-wide-ptr.rs:61:1 | -LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { SliceTransmute { bad: BadSliceRepr { ptr: &42, len: &3 } }.slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer +LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:116:1 + --> $DIR/ub-wide-ptr.rs:65:1 | -LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { BoolTransmute { val: 3 }.bl }]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean +LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:122:1 + --> $DIR/ub-wide-ptr.rs:71:1 | -LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { BoolTransmute { val: 3 }.bl }, [false]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean +LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:125:1 + --> $DIR/ub-wide-ptr.rs:74:1 | -LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { BoolTransmute { val: 3 }.bl }]); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean +LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:132:1 + --> $DIR/ub-wide-ptr.rs:81:1 | -LL | const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { SliceTransmute { addr: 42 }.raw_slice}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered undefined pointer +LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { +LL | | +LL | | let uninit_len = MaybeUninit:: { uninit: () }; +LL | | mem::transmute((42, uninit_len)) +LL | | }; + | |__^ type validation failed: encountered undefined pointer | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:137:1 + --> $DIR/ub-wide-ptr.rs:89:1 | -LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { DynTransmute { repr: DynRepr { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:140:1 + --> $DIR/ub-wide-ptr.rs:92:1 | -LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:143:1 + --> $DIR/ub-wide-ptr.rs:95:1 | -LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 3 } }.rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:147:1 + --> $DIR/ub-wide-ptr.rs:99:1 | -LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = &unsafe { BoolTransmute { val: 3 }.bl }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean +LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:151:1 + --> $DIR/ub-wide-ptr.rs:103:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:153:1 + --> $DIR/ub-wide-ptr.rs:105:1 | -LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.raw_rust}; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable +LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:159:5 + --> $DIR/ub-wide-ptr.rs:111:5 | -LL | DynTransmute { bad: BadDynRepr { ptr: &92, vtable: 0 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer +LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:163:5 + --> $DIR/ub-wide-ptr.rs:115:5 | -LL | DynTransmute { repr2: DynRepr2 { ptr: &92, vtable: &3 } }.rust - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N +LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N error: aborting due to 20 previous errors From 4807e939cdeba02b0752ba5748eec9ef4e9f1af8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 20:52:27 +0100 Subject: [PATCH 0840/1250] test that we validate boxes --- src/librustc_mir/interpret/validity.rs | 1 - src/test/ui/consts/const-eval/ub-ref.rs | 13 +++++++ src/test/ui/consts/const-eval/ub-ref.stderr | 40 ++++++++++++++++++--- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index defb490199b..ee4d05c5911 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -453,7 +453,6 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(true) } ty::Adt(def, ..) if def.is_box() => { - // FIXME make sure we have a test for `Box`! self.check_safe_pointer(value)?; Ok(true) } diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 889579ca1ec..14ededafaff 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -8,9 +8,16 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value //~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) +const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; +//~^ ERROR it is undefined behavior to use this value +//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) + const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value +const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; +//~^ ERROR it is undefined behavior to use this value + // It is very important that we reject this: We do promote `&(4 * REF_AS_USIZE)`, // but that would fail to compile; so we ended up breaking user code that would // have worked fine had we not promoted. @@ -20,7 +27,13 @@ const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; //~^ ERROR it is undefined behavior to use this value +const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; +//~^ ERROR it is undefined behavior to use this value + const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; //~^ ERROR it is undefined behavior to use this value +const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; +//~^ ERROR it is undefined behavior to use this value + fn main() {} diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 5cef0a488eb..3cb91ef2752 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -9,13 +9,29 @@ LL | const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | +LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 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 rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:15:1 + | LL | const NULL: &u16 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:17:1 + --> $DIR/ub-ref.rs:18:1 + | +LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:24:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer, but expected initialized plain (non-pointer) bytes @@ -23,7 +39,7 @@ LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:20:1 + --> $DIR/ub-ref.rs:27:1 | LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes @@ -31,13 +47,29 @@ LL | const REF_AS_USIZE_SLICE: &[usize] = &[unsafe { mem::transmute(&0) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-ref.rs:23:1 + --> $DIR/ub-ref.rs:30:1 + | +LL | const REF_AS_USIZE_BOX_SLICE: Box<[usize]> = unsafe { mem::transmute::<&[usize], _>(&[mem::transmute(&0)]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected plain (non-pointer) bytes + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:33:1 | LL | const USIZE_AS_REF: &'static u8 = unsafe { mem::transmute(1337usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 5 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-ref.rs:36:1 + | +LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0080`. From f481547622722c4813f6e60bbbe55802dc688664 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:03:40 +0100 Subject: [PATCH 0841/1250] test some more kinds of enums with uninhabited variants --- src/test/ui/consts/const-eval/ub-enum.rs | 36 +++++++++++++- src/test/ui/consts/const-eval/ub-enum.stderr | 52 ++++++++++++++++---- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 4e7c7be4a76..1e6a670a400 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,4 +1,4 @@ -#![feature(const_transmute)] +#![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here use std::mem; @@ -7,6 +7,11 @@ use std::mem; #[derive(Copy, Clone)] struct Wrap(T); +#[derive(Copy, Clone)] +enum Never {} + +// # simple enum with discriminant 0 + #[repr(usize)] #[derive(Copy, Clone)] enum Enum { @@ -24,6 +29,8 @@ const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; //~^ ERROR is undefined behavior +// # simple enum with discriminant 2 + // (Potentially) invalid enum discriminant #[repr(usize)] #[derive(Copy, Clone)] @@ -52,11 +59,38 @@ const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; //~^ ERROR is undefined behavior +// # valid discriminant for uninhabited variant + +// An enum with 3 variants of which some are uninhabited -- so the uninhabited variants *do* +// have a discriminant. +enum UninhDiscriminant { + A, + B(!), + C, + D(Never), +} + +const GOOD_INHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(0u8) }; // variant A +const GOOD_INHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(2u8) }; // variant C + +const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; +//~^ ERROR is undefined behavior + +// # other + // Invalid enum field content (mostly to test printing of paths for enum tuple // variants and tuples). // Need to create something which does not clash with enum layout optimizations. const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); //~^ ERROR is undefined behavior +// All variants are uninhabited but also have data. +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; +//~^ ERROR is undefined behavior + fn main() { } diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 95d4155be91..d72884933f5 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:18:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:21:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:24:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:34:1 + --> $DIR/ub-enum.rs:41:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = 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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:36:1 + --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:39:1 + --> $DIR/ub-enum.rs:46:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:48:1 + --> $DIR/ub-enum.rs:55:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:52:1 + --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,13 +63,45 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:58:1 + --> $DIR/ub-enum.rs:76:1 + | +LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:78:1 + | +LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:86:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to 9 previous errors +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:90:1 + | +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.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 rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-enum.rs:92:1 + | +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.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 rustc repository if you believe it should not be considered undefined behavior. + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0080`. From 4584e75c9b23b57c4398714406845306e7ba73c2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:17:34 +0100 Subject: [PATCH 0842/1250] better error messages for invalid boxes (and a few more tests) --- src/librustc_mir/interpret/validity.rs | 19 +++++---- src/test/ui/consts/const-eval/ub-ref.rs | 2 +- src/test/ui/consts/const-eval/ub-ref.stderr | 6 +-- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 6 +++ .../ui/consts/const-eval/ub-wide-ptr.stderr | 42 +++++++++++++------ 5 files changed, 51 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index ee4d05c5911..74a22b90a8b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -307,7 +307,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M } /// Check a reference or `Box`. - fn check_safe_pointer(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + fn check_safe_pointer( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + kind: &str, + ) -> InterpResult<'tcx> { let value = self.ecx.read_immediate(value)?; // Handle wide pointers. // Check metadata early, for better diagnostics @@ -337,13 +341,14 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ); match err.kind { err_unsup!(InvalidNullPointerUsage) => { - throw_validation_failure!("a NULL reference", self.path) + throw_validation_failure!(format_args!("a NULL {}", kind), self.path) } err_unsup!(AlignmentCheckFailed { required, has }) => { throw_validation_failure!( format_args!( - "an unaligned reference \ + "an unaligned {} \ (required {} byte alignment but found {})", + kind, required.bytes(), has.bytes() ), @@ -351,11 +356,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M ) } err_unsup!(ReadBytesAsPointer) => throw_validation_failure!( - "a dangling reference (created from integer)", + format_args!("a dangling {} (created from integer)", kind), self.path ), _ => throw_validation_failure!( - "a dangling reference (not entirely in bounds)", + format_args!("a dangling {} (not entirely in bounds)", kind), self.path ), } @@ -449,11 +454,11 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M Ok(true) } ty::Ref(..) => { - self.check_safe_pointer(value)?; + self.check_safe_pointer(value, "reference")?; Ok(true) } ty::Adt(def, ..) if def.is_box() => { - self.check_safe_pointer(value)?; + self.check_safe_pointer(value, "box")?; Ok(true) } ty::FnPtr(_sig) => { diff --git a/src/test/ui/consts/const-eval/ub-ref.rs b/src/test/ui/consts/const-eval/ub-ref.rs index 14ededafaff..562ec99111b 100644 --- a/src/test/ui/consts/const-eval/ub-ref.rs +++ b/src/test/ui/consts/const-eval/ub-ref.rs @@ -10,7 +10,7 @@ const UNALIGNED: &u16 = unsafe { mem::transmute(&[0u8; 4]) }; const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; //~^ ERROR it is undefined behavior to use this value -//~^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) +//~^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 1) const NULL: &u16 = unsafe { mem::transmute(0usize) }; //~^ ERROR it is undefined behavior to use this value diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 3cb91ef2752..fb3df8ace4e 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:11:1 | LL | const UNALIGNED_BOX: Box = unsafe { mem::transmute(&[0u8; 4]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned reference (required 2 byte alignment but found 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered an unaligned box (required 2 byte alignment but found 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 rustc repository if you believe it should not be considered undefined behavior. @@ -26,7 +26,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:18:1 | LL | const NULL_BOX: Box = unsafe { mem::transmute(0usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL reference + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a NULL box | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -66,7 +66,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:36:1 | LL | const USIZE_AS_BOX: Box = unsafe { mem::transmute(1337usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (created from integer) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (created from integer) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index ada82fc83a8..26d37884746 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -60,6 +60,12 @@ const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // bad slice: length not an int const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value +// bad slice box: length too big +const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; +//~^ ERROR it is undefined behavior to use this value +// bad slice box: length not an int +const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; +//~^ ERROR it is undefined behavior to use this value // bad data *inside* the slice const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 2a3ae7dfe6d..22adf0e55ee 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -67,7 +67,23 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:65:1 + --> $DIR/ub-wide-ptr.rs:64:1 + | +LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:67:1 + | +LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:71:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean @@ -75,7 +91,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:71:1 + --> $DIR/ub-wide-ptr.rs:77:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean @@ -83,7 +99,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:74:1 + --> $DIR/ub-wide-ptr.rs:80:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean @@ -91,7 +107,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:81:1 + --> $DIR/ub-wide-ptr.rs:87:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -103,7 +119,7 @@ LL | | }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:89:1 + --> $DIR/ub-wide-ptr.rs:95:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -111,7 +127,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:92:1 + --> $DIR/ub-wide-ptr.rs:98:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -119,7 +135,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:95:1 + --> $DIR/ub-wide-ptr.rs:101:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -127,7 +143,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4u = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:99:1 + --> $DIR/ub-wide-ptr.rs:105:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean @@ -135,7 +151,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:103:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -143,7 +159,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:105:1 + --> $DIR/ub-wide-ptr.rs:111:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -151,17 +167,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:111:5 + --> $DIR/ub-wide-ptr.rs:117:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:115:5 + --> $DIR/ub-wide-ptr.rs:121:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors For more information about this error, try `rustc --explain E0080`. From f0586f9aea1948fe208751f8183d58f9af1116b6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 21:53:58 +0100 Subject: [PATCH 0843/1250] please tidy --- src/test/ui/consts/const-eval/ub-enum.rs | 1 + src/test/ui/consts/const-eval/ub-enum.stderr | 26 ++++++++++---------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 1e6a670a400..499be5107f9 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,3 +1,4 @@ +// ignore-tidy-linelength #![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index d72884933f5..e0cf2cd610f 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:23:1 + --> $DIR/ub-enum.rs:24:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:26:1 + --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:29:1 + --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:41:1 + --> $DIR/ub-enum.rs:42:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = 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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:43:1 + --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:46:1 + --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:55:1 + --> $DIR/ub-enum.rs:56:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:59:1 + --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,7 +63,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:76:1 + --> $DIR/ub-enum.rs:77:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 @@ -71,7 +71,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:78:1 + --> $DIR/ub-enum.rs:79:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 @@ -79,7 +79,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:86:1 + --> $DIR/ub-enum.rs:87:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint @@ -87,7 +87,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:90:1 + --> $DIR/ub-enum.rs:91:1 | LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 @@ -95,7 +95,7 @@ LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:92:1 + --> $DIR/ub-enum.rs:93:1 | LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 From 58f8cc21352613639fdc58f4f8a59f5c579b5372 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 22:24:23 +0100 Subject: [PATCH 0844/1250] rename visit_primitive -> try_visit_primitive, and comments --- src/librustc_mir/interpret/validity.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 74a22b90a8b..29d18e87c4f 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -406,7 +406,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. - fn visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { + fn try_visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { @@ -477,7 +477,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M // Nothing to check. Ok(true) } - // This should be all the (inhabited) primitive types. The rest is compound, we + // The above should be all the (inhabited) primitive types. The rest is compound, we // check them by visiting their fields/variants. // (`Str` UTF-8 check happens in `visit_aggregate`, too.) ty::Adt(..) @@ -489,7 +489,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => Ok(false), - // Some types only occur during inference, we should not see them here. + // Some types only occur during typechecking, they have no layout. + // We should not see them here and we could not check them anyway. ty::Error | ty::Infer(..) | ty::Placeholder(..) @@ -618,7 +619,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> trace!("visit_value: {:?}, {:?}", *op, op.layout); // Check primitive types -- the leafs of our recursive descend. - if self.visit_primitive(op)? { + if self.try_visit_primitive(op)? { return Ok(()); } // Sanity check: `builtin_deref` does not know any pointers that are not primitive. From 295c2d69bd425e8258f197252d2f100e08f478d8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Mar 2020 22:47:28 +0100 Subject: [PATCH 0845/1250] bug on ty::GeneratorWitness --- src/librustc_mir/interpret/validity.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 29d18e87c4f..0fba8a5c15c 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -406,7 +406,10 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M /// Check if this is a value of primitive type, and if yes check the validity of the value /// at that type. Return `true` if the type is indeed primitive. - fn try_visit_primitive(&mut self, value: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx, bool> { + fn try_visit_primitive( + &mut self, + value: OpTy<'tcx, M::PointerTag>, + ) -> InterpResult<'tcx, bool> { // Go over all the primitive types let ty = value.layout.ty; match ty.kind { @@ -487,8 +490,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Str | ty::Dynamic(..) | ty::Closure(..) - | ty::Generator(..) - | ty::GeneratorWitness(..) => Ok(false), + | ty::Generator(..) => Ok(false), // Some types only occur during typechecking, they have no layout. // We should not see them here and we could not check them anyway. ty::Error @@ -498,7 +500,8 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M | ty::Param(..) | ty::Opaque(..) | ty::UnnormalizedProjection(..) - | ty::Projection(..) => bug!("Encountered invalid type {:?}", ty), + | ty::Projection(..) + | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), } } From 125159f30a7a97b0b4d4bc36b11846a3f6dd4a7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Dec 2019 15:46:31 -0800 Subject: [PATCH 0846/1250] When encountering an Item in a pat context, point at the item def --- src/librustc_typeck/check/pat.rs | 103 ++++++++++++++---- .../ui/blind/blind-item-block-middle.stderr | 9 +- src/test/ui/issues/issue-33504.stderr | 9 +- src/test/ui/issues/issue-4968.stderr | 9 +- src/test/ui/issues/issue-5100.stderr | 3 + src/test/ui/issues/issue-7867.stderr | 3 + src/test/ui/match/match-tag-nullary.stderr | 3 + .../const.stderr | 9 +- .../ui/suggestions/const-in-struct-pat.rs | 11 ++ .../ui/suggestions/const-in-struct-pat.stderr | 16 +++ 10 files changed, 147 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/suggestions/const-in-struct-pat.rs create mode 100644 src/test/ui/suggestions/const-in-struct-pat.stderr diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index b7aac707a98..dd4b407ac52 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -63,6 +63,22 @@ struct TopInfo<'tcx> { /// found type `std::result::Result<_, _>` /// ``` span: Option, + /// This refers to the parent pattern. Used to provide extra diagnostic information on errors. + /// ```text + /// error[E0308]: mismatched types + /// --> $DIR/const-in-struct-pat.rs:8:17 + /// | + /// L | struct f; + /// | --------- unit struct defined here + /// ... + /// L | let Thing { f } = t; + /// | ^ + /// | | + /// | expected struct `std::string::String`, found struct `f` + /// | `f` is interpreted as a unit struct, not a new binding + /// | help: bind the struct field to a different name instead: `f: other_f` + /// ``` + parent_pat: Option<&'tcx Pat<'tcx>>, } impl<'tcx> FnCtxt<'_, 'tcx> { @@ -120,7 +136,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Option, origin_expr: bool, ) { - self.check_pat(pat, expected, INITIAL_BM, TopInfo { expected, origin_expr, span }); + let info = TopInfo { expected, origin_expr, span, parent_pat: None }; + self.check_pat(pat, expected, INITIAL_BM, info); } /// Type check the given `pat` against the `expected` type @@ -161,8 +178,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.check_pat_struct(pat, qpath, fields, etc, expected, def_bm, ti) } PatKind::Or(pats) => { + let parent_pat = Some(pat); for pat in pats { - self.check_pat(pat, expected, def_bm, ti); + self.check_pat(pat, expected, def_bm, TopInfo { parent_pat, ..ti }); } expected } @@ -501,7 +519,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ident( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, ba: hir::BindingAnnotation, var_id: HirId, sub: Option<&'tcx Pat<'tcx>>, @@ -546,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if let Some(p) = sub { - self.check_pat(&p, expected, def_bm, ti); + self.check_pat(&p, expected, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); } local_ty @@ -647,6 +665,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { variant_ty } else { for field in fields { + let ti = TopInfo { parent_pat: Some(&pat), ..ti }; self.check_pat(&field.pat, self.tcx.types.err, def_bm, ti); } return self.tcx.types.err; @@ -656,9 +675,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.demand_eqtype_pat(pat.span, expected, pat_ty, ti); // Type-check subpatterns. - if self - .check_struct_pat_fields(pat_ty, pat.hir_id, pat.span, variant, fields, etc, def_bm, ti) - { + if self.check_struct_pat_fields(pat_ty, &pat, variant, fields, etc, def_bm, ti) { pat_ty } else { self.tcx.types.err @@ -696,18 +713,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Type-check the path. - let pat_ty = self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id).0; - if let Some(mut err) = + let (pat_ty, pat_res) = + self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.hir_id); + if let Some(err) = self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty) { - err.emit(); + self.emit_bad_pat_path(err, pat.span, res, pat_res, segments, ti.parent_pat); } pat_ty } + fn emit_bad_pat_path( + &self, + mut e: DiagnosticBuilder<'_>, + pat_span: Span, + res: Res, + pat_res: Res, + segments: &'b [hir::PathSegment<'b>], + parent_pat: Option<&Pat<'_>>, + ) { + if let Some(span) = self.tcx.hir().res_span(pat_res) { + e.span_label(span, &format!("{} defined here", res.descr())); + if let [hir::PathSegment { ident, .. }] = &*segments { + e.span_label( + pat_span, + &format!( + "`{}` is interpreted as {} {}, not a new binding", + ident, + res.article(), + res.descr(), + ), + ); + let (msg, sugg) = match parent_pat { + Some(Pat { kind: hir::PatKind::Struct(..), .. }) => ( + "bind the struct field to a different name instead", + format!("{}: other_{}", ident, ident.as_str().to_lowercase()), + ), + _ => ( + "introduce a new binding instead", + format!("other_{}", ident.as_str().to_lowercase()), + ), + }; + e.span_suggestion(ident.span, msg, sugg, Applicability::HasPlaceholders); + } + } + e.emit(); + } + fn check_pat_tuple_struct( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, qpath: &hir::QPath<'_>, subpats: &'tcx [&'tcx Pat<'tcx>], ddpos: Option, @@ -717,8 +772,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Ty<'tcx> { let tcx = self.tcx; let on_error = || { + let parent_pat = Some(pat); for pat in subpats { - self.check_pat(&pat, tcx.types.err, def_bm, ti); + self.check_pat(&pat, tcx.types.err, def_bm, TopInfo { parent_pat, ..ti }); } }; let report_unexpected_res = |res: Res| { @@ -793,7 +849,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; for (i, subpat) in subpats.iter().enumerate_and_adjust(variant.fields.len(), ddpos) { let field_ty = self.field_ty(subpat.span, &variant.fields[i], substs); - self.check_pat(&subpat, field_ty, def_bm, ti); + self.check_pat(&subpat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); self.tcx.check_stability(variant.fields[i].did, Some(pat.hir_id), subpat.span); } @@ -938,8 +994,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_struct_pat_fields( &self, adt_ty: Ty<'tcx>, - pat_id: HirId, - span: Span, + pat: &'tcx Pat<'tcx>, variant: &'tcx ty::VariantDef, fields: &'tcx [hir::FieldPat<'tcx>], etc: bool, @@ -950,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (substs, adt) = match adt_ty.kind { ty::Adt(adt, substs) => (substs, adt), - _ => span_bug!(span, "struct pattern is not an ADT"), + _ => span_bug!(pat.span, "struct pattern is not an ADT"), }; let kind_name = adt.variant_descr(); @@ -983,7 +1038,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .get(&ident) .map(|(i, f)| { self.write_field_index(field.hir_id, *i); - self.tcx.check_stability(f.did, Some(pat_id), span); + self.tcx.check_stability(f.did, Some(pat.hir_id), span); self.field_ty(span, f, substs) }) .unwrap_or_else(|| { @@ -994,7 +1049,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - self.check_pat(&field.pat, field_ty, def_bm, ti); + self.check_pat(&field.pat, field_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); } let mut unmentioned_fields = variant @@ -1017,7 +1072,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if variant.is_field_list_non_exhaustive() && !adt.did.is_local() && !etc { struct_span_err!( tcx.sess, - span, + pat.span, E0638, "`..` required with {} marked as non-exhaustive", kind_name @@ -1029,14 +1084,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if kind_name == "union" { if fields.len() != 1 { tcx.sess - .struct_span_err(span, "union patterns should have exactly one field") + .struct_span_err(pat.span, "union patterns should have exactly one field") .emit(); } if etc { - tcx.sess.struct_span_err(span, "`..` cannot be used in union patterns").emit(); + tcx.sess.struct_span_err(pat.span, "`..` cannot be used in union patterns").emit(); } } else if !etc && !unmentioned_fields.is_empty() { - self.error_unmentioned_fields(span, &unmentioned_fields, variant); + self.error_unmentioned_fields(pat.span, &unmentioned_fields, variant); } no_field_errors } @@ -1196,7 +1251,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_pat_ref( &self, - pat: &Pat<'_>, + pat: &'tcx Pat<'tcx>, inner: &'tcx Pat<'tcx>, mutbl: hir::Mutability, expected: Ty<'tcx>, @@ -1236,7 +1291,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (tcx.types.err, tcx.types.err) }; - self.check_pat(&inner, inner_ty, def_bm, ti); + self.check_pat(&inner, inner_ty, def_bm, TopInfo { parent_pat: Some(&pat), ..ti }); rptr_ty } diff --git a/src/test/ui/blind/blind-item-block-middle.stderr b/src/test/ui/blind/blind-item-block-middle.stderr index 264e7fc8e73..d8d15615d7c 100644 --- a/src/test/ui/blind/blind-item-block-middle.stderr +++ b/src/test/ui/blind/blind-item-block-middle.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/blind-item-block-middle.rs:6:9 | +LL | mod foo { pub struct bar; } + | --------------- unit struct defined here +... LL | let bar = 5; - | ^^^ expected integer, found struct `foo::bar` + | ^^^ + | | + | expected integer, found struct `foo::bar` + | `bar` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_bar` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-33504.stderr b/src/test/ui/issues/issue-33504.stderr index 522df6a07c2..1e61178f42e 100644 --- a/src/test/ui/issues/issue-33504.stderr +++ b/src/test/ui/issues/issue-33504.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/issue-33504.rs:7:13 | +LL | struct Test; + | ------------ unit struct defined here +... LL | let Test = 1; - | ^^^^ expected integer, found struct `Test` + | ^^^^ + | | + | expected integer, found struct `Test` + | `Test` is interpreted as a unit struct, not a new binding + | help: introduce a new binding instead: `other_test` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-4968.stderr b/src/test/ui/issues/issue-4968.stderr index 35435d0e618..5451cf42355 100644 --- a/src/test/ui/issues/issue-4968.stderr +++ b/src/test/ui/issues/issue-4968.stderr @@ -1,8 +1,15 @@ error[E0308]: mismatched types --> $DIR/issue-4968.rs:5:16 | +LL | const A: (isize,isize) = (4,2); + | ------------------------------- constant defined here +LL | fn main() { LL | match 42 { A => () } - | ^ expected integer, found tuple + | ^ + | | + | expected integer, found tuple + | `A` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_a` | = note: expected type `{integer}` found tuple `(isize, isize)` diff --git a/src/test/ui/issues/issue-5100.stderr b/src/test/ui/issues/issue-5100.stderr index c81d6dcaf02..a89980964ca 100644 --- a/src/test/ui/issues/issue-5100.stderr +++ b/src/test/ui/issues/issue-5100.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-5100.rs:8:9 | +LL | enum A { B, C } + | - unit variant defined here +... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` LL | A::B => (), diff --git a/src/test/ui/issues/issue-7867.stderr b/src/test/ui/issues/issue-7867.stderr index 4a29464aebd..0d3121d6045 100644 --- a/src/test/ui/issues/issue-7867.stderr +++ b/src/test/ui/issues/issue-7867.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/issue-7867.rs:7:9 | +LL | enum A { B, C } + | - unit variant defined here +... LL | match (true, false) { | ------------- this expression has type `(bool, bool)` LL | A::B => (), diff --git a/src/test/ui/match/match-tag-nullary.stderr b/src/test/ui/match/match-tag-nullary.stderr index 3703a59edb8..723c7fa92b1 100644 --- a/src/test/ui/match/match-tag-nullary.stderr +++ b/src/test/ui/match/match-tag-nullary.stderr @@ -1,6 +1,9 @@ error[E0308]: mismatched types --> $DIR/match-tag-nullary.rs:4:40 | +LL | enum B { B } + | - unit variant defined here +LL | LL | fn main() { let x: A = A::A; match x { B::B => { } } } | - ^^^^ expected enum `A`, found enum `B` | | diff --git a/src/test/ui/rfc-2005-default-binding-mode/const.stderr b/src/test/ui/rfc-2005-default-binding-mode/const.stderr index 27efd450b94..10d30ec1a1b 100644 --- a/src/test/ui/rfc-2005-default-binding-mode/const.stderr +++ b/src/test/ui/rfc-2005-default-binding-mode/const.stderr @@ -1,10 +1,17 @@ error[E0308]: mismatched types --> $DIR/const.rs:14:9 | +LL | const FOO: Foo = Foo{bar: 5}; + | ----------------------------- constant defined here +... LL | match &f { | -- this expression has type `&Foo` LL | FOO => {}, - | ^^^ expected `&Foo`, found struct `Foo` + | ^^^ + | | + | expected `&Foo`, found struct `Foo` + | `FOO` is interpreted as a constant, not a new binding + | help: introduce a new binding instead: `other_foo` error: aborting due to previous error diff --git a/src/test/ui/suggestions/const-in-struct-pat.rs b/src/test/ui/suggestions/const-in-struct-pat.rs new file mode 100644 index 00000000000..1cbba935402 --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.rs @@ -0,0 +1,11 @@ +#[allow(non_camel_case_types)] +struct foo; +struct Thing { + foo: String, +} + +fn example(t: Thing) { + let Thing { foo } = t; //~ ERROR mismatched types +} + +fn main() {} diff --git a/src/test/ui/suggestions/const-in-struct-pat.stderr b/src/test/ui/suggestions/const-in-struct-pat.stderr new file mode 100644 index 00000000000..0a010dcab4c --- /dev/null +++ b/src/test/ui/suggestions/const-in-struct-pat.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/const-in-struct-pat.rs:8:17 + | +LL | struct foo; + | ----------- unit struct defined here +... +LL | let Thing { foo } = t; + | ^^^ - this expression has type `Thing` + | | + | expected struct `std::string::String`, found struct `foo` + | `foo` is interpreted as a unit struct, not a new binding + | help: bind the struct field to a different name instead: `foo: other_foo` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From b900de0f778c4b66921a71824ed7745724405f45 Mon Sep 17 00:00:00 2001 From: Lena Wildervanck Date: Fri, 6 Mar 2020 10:29:11 +0100 Subject: [PATCH 0847/1250] Implement Error for TryReserveError --- src/liballoc/collections/mod.rs | 17 +++++++++++++++++ src/libstd/error.rs | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/src/liballoc/collections/mod.rs b/src/liballoc/collections/mod.rs index 0bb62373fab..9e7e66e657a 100644 --- a/src/liballoc/collections/mod.rs +++ b/src/liballoc/collections/mod.rs @@ -42,6 +42,7 @@ pub use linked_list::LinkedList; pub use vec_deque::VecDeque; use crate::alloc::{Layout, LayoutErr}; +use core::fmt::Display; /// The error type for `try_reserve` methods. #[derive(Clone, PartialEq, Eq, Debug)] @@ -77,6 +78,22 @@ impl From for TryReserveError { } } +#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +impl Display for TryReserveError { + fn fmt( + &self, + fmt: &mut core::fmt::Formatter<'_>, + ) -> core::result::Result<(), core::fmt::Error> { + fmt.write_str("memory allocation failed")?; + fmt.write_str(match &self { + TryReserveError::CapacityOverflow => { + " because the computed capacity exceeded the collection's maximum" + } + TryReserveError::AllocError { .. } => " because the memory allocator returned a error", + }) + } +} + /// An intermediate trait for specialization of `Extend`. #[doc(hidden)] trait SpecExtend { diff --git a/src/libstd/error.rs b/src/libstd/error.rs index b480581e21b..61944edf142 100644 --- a/src/libstd/error.rs +++ b/src/libstd/error.rs @@ -552,6 +552,13 @@ impl Error for char::ParseCharError { } } +#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")] +impl Error for alloc::collections::TryReserveError { + fn description(&self) -> &str { + "memory allocation failed" + } +} + // Copied from `any.rs`. impl dyn Error + 'static { /// Returns `true` if the boxed type is the same as `T` From 05f6482f435c498b19f3af56d1017c84323683f5 Mon Sep 17 00:00:00 2001 From: JOE1994 Date: Thu, 20 Feb 2020 14:29:40 -0500 Subject: [PATCH 0848/1250] mir-interpret: add method Memory::read wide_string --- src/librustc/mir/interpret/value.rs | 10 ++++++++++ src/librustc_mir/interpret/memory.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/librustc/mir/interpret/value.rs b/src/librustc/mir/interpret/value.rs index 2be36ad418a..8a02f47accb 100644 --- a/src/librustc/mir/interpret/value.rs +++ b/src/librustc/mir/interpret/value.rs @@ -590,6 +590,11 @@ impl<'tcx, Tag> ScalarMaybeUndef { self.not_undef()?.to_u8() } + #[inline(always)] + pub fn to_u16(self) -> InterpResult<'tcx, u16> { + self.not_undef()?.to_u16() + } + #[inline(always)] pub fn to_u32(self) -> InterpResult<'tcx, u32> { self.not_undef()?.to_u32() @@ -610,6 +615,11 @@ impl<'tcx, Tag> ScalarMaybeUndef { self.not_undef()?.to_i8() } + #[inline(always)] + pub fn to_i16(self) -> InterpResult<'tcx, i16> { + self.not_undef()?.to_i16() + } + #[inline(always)] pub fn to_i32(self) -> InterpResult<'tcx, i32> { self.not_undef()?.to_i32() diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 0bcdf9ae3c1..4b668500e7c 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -791,6 +791,33 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { self.get_raw(ptr.alloc_id)?.read_c_str(self, ptr) } + /// Reads a 0x0000-terminated u16-sequence from memory. Returns them as a Vec. + /// Terminator 0x0000 is not included in the returned Vec. + /// + /// Performs appropriate bounds checks. + pub fn read_wide_str(&self, ptr: Scalar) -> InterpResult<'tcx, Vec> { + let size_2bytes = Size::from_bytes(2); + let align_2bytes = Align::from_bytes(2).unwrap(); + // We need to read at least 2 bytes, so we *need* a ptr. + let mut ptr = self.force_ptr(ptr)?; + let allocation = self.get_raw(ptr.alloc_id)?; + let mut u16_seq = Vec::new(); + + loop { + ptr = self + .check_ptr_access(ptr.into(), size_2bytes, align_2bytes)? + .expect("cannot be a ZST"); + let single_u16 = allocation.read_scalar(self, ptr, size_2bytes)?.to_u16()?; + if single_u16 != 0x0000 { + u16_seq.push(single_u16); + ptr = ptr.offset(size_2bytes, self)?; + } else { + break; + } + } + Ok(u16_seq) + } + /// Writes the given stream of bytes into memory. /// /// Performs appropriate bounds checks. From 545ef9d83ab383bdc99376a2fe4164e46f4a3f6e Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Sat, 7 Mar 2020 02:40:54 +0100 Subject: [PATCH 0849/1250] Add `Layout::dangling()` to return a well-aligned `NonNull` --- src/libcore/alloc.rs | 12 ++++++++++++ src/libcore/tests/alloc.rs | 3 +++ src/libcore/tests/lib.rs | 1 + 3 files changed, 16 insertions(+) diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index f3a2b73f2b8..4f401c75104 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -140,6 +140,18 @@ impl Layout { unsafe { Layout::from_size_align_unchecked(size, align) } } + /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. + /// + /// Note that the pointer value may potentially represent a valid pointer to + /// a `T`, which means this must not be used as a "not yet initialized" + /// sentinel value. Types that lazily allocate must track initialization by + /// some other means. + #[unstable(feature = "alloc_layout_extra", issue = "55724")] + pub const fn dangling(&self) -> NonNull { + // align is non-zero and a power of two + unsafe { NonNull::new_unchecked(self.align() as *mut u8) } + } + /// Creates a layout describing the record that can hold a value /// of the same layout as `self`, but that also is aligned to /// alignment `align` (measured in bytes). diff --git a/src/libcore/tests/alloc.rs b/src/libcore/tests/alloc.rs index 63537ba23d8..c8592e40a69 100644 --- a/src/libcore/tests/alloc.rs +++ b/src/libcore/tests/alloc.rs @@ -1,10 +1,13 @@ use core::alloc::Layout; +use core::ptr::NonNull; #[test] fn const_unchecked_layout() { const SIZE: usize = 0x2000; const ALIGN: usize = 0x1000; const LAYOUT: Layout = unsafe { Layout::from_size_align_unchecked(SIZE, ALIGN) }; + const DANGLING: NonNull = LAYOUT.dangling(); assert_eq!(LAYOUT.size(), SIZE); assert_eq!(LAYOUT.align(), ALIGN); + assert_eq!(Some(DANGLING), NonNull::new(ALIGN as *mut u8)); } diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 991458db5b7..71a061af289 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -1,3 +1,4 @@ +#![feature(alloc_layout_extra)] #![feature(bool_to_option)] #![feature(bound_cloned)] #![feature(box_syntax)] From 09d3ba13afb8fdf449928b160431787e2d259db1 Mon Sep 17 00:00:00 2001 From: Tim Diekmann <21277928+TimDiekmann@users.noreply.github.com> Date: Sat, 7 Mar 2020 02:45:55 +0100 Subject: [PATCH 0850/1250] Update alloc.rs --- src/libcore/alloc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 4f401c75104..0a7a8ab266a 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -142,8 +142,8 @@ impl Layout { /// Creates a `NonNull` that is dangling, but well-aligned for this Layout. /// - /// Note that the pointer value may potentially represent a valid pointer to - /// a `T`, which means this must not be used as a "not yet initialized" + /// Note that the pointer value may potentially represent a valid pointer, + /// which means this must not be used as a "not yet initialized" /// sentinel value. Types that lazily allocate must track initialization by /// some other means. #[unstable(feature = "alloc_layout_extra", issue = "55724")] From dbd1514353a5aa38d08fbb08e05aa478ae926de0 Mon Sep 17 00:00:00 2001 From: O01eg Date: Sat, 7 Mar 2020 07:29:23 +0300 Subject: [PATCH 0851/1250] Add new option to the documentation. --- src/doc/rustc/src/command-line-arguments.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 659f8f65e65..7a7838d965b 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -146,6 +146,7 @@ The valid types of print values are: - `crate-name` — The name of the crate. - `file-names` — The names of the files created by the `link` emit kind. - `sysroot` — Path to the sysroot. +- `target-libdir` - Path to the target libdir. - `cfg` — List of cfg values. See [conditional compilation] for more information about cfg values. - `target-list` — List of known targets. The target may be selected with the From dffd18fafc5ffe41b958bf9cacc0c3a6ef257348 Mon Sep 17 00:00:00 2001 From: Jonathan Giddy Date: Sat, 7 Mar 2020 08:21:27 +0000 Subject: [PATCH 0852/1250] Correct version that relaxed orphan rules --- src/libcore/convert/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/convert/mod.rs b/src/libcore/convert/mod.rs index 959fd63df51..47ab8715cfa 100644 --- a/src/libcore/convert/mod.rs +++ b/src/libcore/convert/mod.rs @@ -229,7 +229,7 @@ pub trait AsMut { /// /// # Implementing [`Into`] for conversions to external types in old versions of Rust /// -/// Prior to Rust 1.40, if the destination type was not part of the current crate +/// Prior to Rust 1.41, if the destination type was not part of the current crate /// then you couldn't implement [`From`] directly. /// For example, take this code: /// From 8de1ec9ce0a53b8ad9987e923e833c82fda05603 Mon Sep 17 00:00:00 2001 From: Kornel Date: Thu, 27 Feb 2020 16:28:27 +0000 Subject: [PATCH 0853/1250] Make error message clearer about creating new module --- src/librustc_parse/parser/diagnostics.rs | 26 +++++-------------- src/librustc_parse/parser/module.rs | 9 +++---- src/test/ui/error-codes/E0583.stderr | 2 +- .../invalid-module-declaration.stderr | 2 +- .../missing_non_modrs_mod.stderr | 2 +- .../missing_non_modrs_mod_inline.stderr | 2 +- src/test/ui/parser/mod_file_not_exist.rs | 2 +- src/test/ui/parser/mod_file_not_exist.stderr | 2 +- .../ui/parser/mod_file_not_exist_windows.rs | 2 +- .../parser/mod_file_not_exist_windows.stderr | 2 +- 10 files changed, 18 insertions(+), 33 deletions(-) diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 8b43b424f55..0618587bac1 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -18,6 +18,7 @@ use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use log::{debug, trace}; use std::mem; +use std::path::PathBuf; const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; @@ -40,29 +41,15 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { } pub enum Error { - FileNotFoundForModule { - mod_name: String, - default_path: String, - secondary_path: String, - dir_path: String, - }, - DuplicatePaths { - mod_name: String, - default_path: String, - secondary_path: String, - }, + FileNotFoundForModule { mod_name: String, default_path: PathBuf }, + DuplicatePaths { mod_name: String, default_path: String, secondary_path: String }, UselessDocComment, } impl Error { fn span_err(self, sp: impl Into, handler: &Handler) -> DiagnosticBuilder<'_> { match self { - Error::FileNotFoundForModule { - ref mod_name, - ref default_path, - ref secondary_path, - ref dir_path, - } => { + Error::FileNotFoundForModule { ref mod_name, ref default_path } => { let mut err = struct_span_err!( handler, sp, @@ -71,8 +58,9 @@ impl Error { mod_name, ); err.help(&format!( - "name the file either {} or {} inside the directory \"{}\"", - default_path, secondary_path, dir_path, + "to create the module `{}`, create file \"{}\"", + mod_name, + default_path.display(), )); err } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index b436f1969bb..7b46601cc7d 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -234,12 +234,9 @@ impl<'a> Parser<'a> { path: secondary_path, directory_ownership: DirectoryOwnership::Owned { relative: None }, }), - (false, false) => Err(Error::FileNotFoundForModule { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - dir_path: dir_path.display().to_string(), - }), + (false, false) => { + Err(Error::FileNotFoundForModule { mod_name: mod_name.clone(), default_path }) + } (true, true) => Err(Error::DuplicatePaths { mod_name: mod_name.clone(), default_path: default_path_str, diff --git a/src/test/ui/error-codes/E0583.stderr b/src/test/ui/error-codes/E0583.stderr index ef7a48bc8a4..5d47b633e78 100644 --- a/src/test/ui/error-codes/E0583.stderr +++ b/src/test/ui/error-codes/E0583.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `module_that_doesnt_exist` LL | mod module_that_doesnt_exist; | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: name the file either module_that_doesnt_exist.rs or module_that_doesnt_exist/mod.rs inside the directory "$DIR" + = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs" error: aborting due to previous error diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index c95df5b4534..5d2cdaef1a7 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `baz` LL | pub mod baz; | ^^^ | - = help: name the file either bar/baz.rs or bar/baz/mod.rs inside the directory "$DIR/auxiliary/foo" + = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs" error: aborting due to previous error diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index 98b74e5f5cb..e8d997e6de0 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `missing` LL | mod missing; | ^^^^^^^ | - = help: name the file either foo/missing.rs or foo/missing/mod.rs inside the directory "$DIR" + = help: to create the module `missing`, create file "$DIR/foo/missing.rs" error: aborting due to previous error diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr index 457e8fcccbf..b2b0f8b466a 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `missing` LL | mod missing; | ^^^^^^^ | - = help: name the file either missing.rs or missing/mod.rs inside the directory "$DIR/foo_inline/inline" + = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs" error: aborting due to previous error diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs index e662c707a38..71fbc7aea45 100644 --- a/src/test/ui/parser/mod_file_not_exist.rs +++ b/src/test/ui/parser/mod_file_not_exist.rs @@ -1,7 +1,7 @@ // ignore-windows mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` -//~^ HELP name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory +//~^ HELP to create the module `not_a_real_file`, create file " fn main() { assert_eq!(mod_file_aux::bar(), 10); diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index dadf4b29dcf..db3ea04ac76 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `not_a_real_file` LL | mod not_a_real_file; | ^^^^^^^^^^^^^^^ | - = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" error: aborting due to previous error diff --git a/src/test/ui/parser/mod_file_not_exist_windows.rs b/src/test/ui/parser/mod_file_not_exist_windows.rs index 0cd9e9c799f..97cadab675f 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.rs +++ b/src/test/ui/parser/mod_file_not_exist_windows.rs @@ -1,7 +1,7 @@ // only-windows mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` -//~^ HELP name the file either not_a_real_file.rs or not_a_real_file\mod.rs inside the directory +//~^ HELP to create the module `not_a_real_file`, create file fn main() { assert_eq!(mod_file_aux::bar(), 10); diff --git a/src/test/ui/parser/mod_file_not_exist_windows.stderr b/src/test/ui/parser/mod_file_not_exist_windows.stderr index 60ae00abab1..a58db80f73d 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.stderr +++ b/src/test/ui/parser/mod_file_not_exist_windows.stderr @@ -4,7 +4,7 @@ error[E0583]: file not found for module `not_a_real_file` LL | mod not_a_real_file; | ^^^^^^^^^^^^^^^ | - = help: name the file either not_a_real_file.rs or not_a_real_file/mod.rs inside the directory "$DIR" + = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" error: aborting due to previous error From adc422f3d5f2f63445567cbbb37c7828368b1cbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 7 Mar 2020 00:00:00 +0000 Subject: [PATCH 0854/1250] Compile address sanitizer test with debuginfo This makes error-pattern to match regardless of current configuration of `rust.debuginfo-level-tests` in `config.toml`. --- src/test/ui/sanitize/address.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/test/ui/sanitize/address.rs b/src/test/ui/sanitize/address.rs index d27a30a2dc5..f8650cd86d5 100644 --- a/src/test/ui/sanitize/address.rs +++ b/src/test/ui/sanitize/address.rs @@ -1,16 +1,15 @@ // needs-sanitizer-support // only-x86_64 // -// compile-flags: -Z sanitizer=address -O +// compile-flags: -Z sanitizer=address -O -g // // run-fail // error-pattern: AddressSanitizer: stack-buffer-overflow -// error-pattern: 'xs' <== Memory access at offset +// error-pattern: 'xs' (line 15) <== Memory access at offset #![feature(test)] use std::hint::black_box; -use std::mem; fn main() { let xs = [0, 1, 2, 3]; From 1915bf122e488ce540cdb7782550e907f269b9e3 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 18:49:13 +0300 Subject: [PATCH 0855/1250] resolve: `ImportDirective` -> `Import` `ImportDirectiveSubclass` -> `ImportKind` `ImportKind::SingleImport` -> `ImportKind::Single` `ImportKind::GlobImport` -> `ImportKind::Glob` --- src/librustc_resolve/build_reduced_graph.rs | 38 +++--- src/librustc_resolve/check_unused.rs | 10 +- src/librustc_resolve/diagnostics.rs | 10 +- src/librustc_resolve/imports.rs | 132 +++++++++----------- src/librustc_resolve/lib.rs | 40 +++--- 5 files changed, 105 insertions(+), 125 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 43cfe05ac23..32cf1af60ec 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -6,8 +6,7 @@ //! Imports are also considered items and placed into modules here, but not resolved yet. use crate::def_collector::collect_definitions; -use crate::imports::ImportDirective; -use crate::imports::ImportDirectiveSubclass::{self, GlobImport, SingleImport}; +use crate::imports::{Import, ImportKind}; use crate::macros::{LegacyBinding, LegacyScope}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; @@ -312,7 +311,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn add_import_directive( &mut self, module_path: Vec, - subclass: ImportDirectiveSubclass<'a>, + kind: ImportKind<'a>, span: Span, id: NodeId, item: &ast::Item, @@ -321,11 +320,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let directive = self.r.arenas.alloc_import_directive(ImportDirective { + let directive = self.r.arenas.alloc_import_directive(Import { + kind, parent_scope: self.parent_scope, module_path, imported_module: Cell::new(None), - subclass, span, id, use_span: item.span, @@ -340,10 +339,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { debug!("add_import_directive({:?})", directive); self.r.indeterminate_imports.push(directive); - match directive.subclass { + match directive.kind { // Don't add unresolved underscore imports to modules - SingleImport { target: Ident { name: kw::Underscore, .. }, .. } => {} - SingleImport { target, type_ns_only, .. } => { + ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {} + ImportKind::Single { target, type_ns_only, .. } => { self.r.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { let key = this.new_key(target, ns); @@ -354,8 +353,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. - GlobImport { is_prelude: true, .. } => {} - GlobImport { .. } => current_module.globs.borrow_mut().push(directive), + ImportKind::Glob { is_prelude: true, .. } => {} + ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(directive), _ => unreachable!(), } } @@ -480,7 +479,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ); } - let subclass = SingleImport { + let kind = ImportKind::Single { source: source.ident, target: ident, source_bindings: PerNS { @@ -498,7 +497,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }; self.add_import_directive( module_path, - subclass, + kind, use_tree.span, id, item, @@ -508,13 +507,13 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ); } ast::UseTreeKind::Glob => { - let subclass = GlobImport { + let kind = ImportKind::Glob { is_prelude: attr::contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; self.add_import_directive( prefix, - subclass, + kind, use_tree.span, id, item, @@ -637,15 +636,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { 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 { + let directive = self.r.arenas.alloc_import_directive(Import { + kind: ImportKind::ExternCrate { source: orig_name, target: ident }, root_id: item.id, id: item.id, parent_scope: self.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - subclass: ImportDirectiveSubclass::ExternCrate { - source: orig_name, - target: ident, - }, has_attributes: !item.attrs.is_empty(), use_span_with_attributes: item.span_with_attributes(), use_span: item.span, @@ -993,12 +989,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } let macro_use_directive = |this: &Self, span| { - this.r.arenas.alloc_import_directive(ImportDirective { + this.r.arenas.alloc_import_directive(Import { + kind: ImportKind::MacroUse, root_id: item.id, id: item.id, parent_scope: this.parent_scope, imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))), - subclass: ImportDirectiveSubclass::MacroUse, use_span_with_attributes: item.span_with_attributes(), has_attributes: !item.attrs.is_empty(), use_span: item.span, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 659a54b169b..5d45fcb3934 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -23,7 +23,7 @@ // - `check_crate` finally emits the diagnostics based on the data generated // in the last step -use crate::imports::ImportDirectiveSubclass; +use crate::imports::ImportKind; use crate::Resolver; use rustc::{lint, ty}; @@ -224,12 +224,12 @@ fn calc_unused_spans( impl Resolver<'_> { crate fn check_unused(&mut self, krate: &ast::Crate) { for directive in self.potentially_unused_imports.iter() { - match directive.subclass { + match directive.kind { _ if directive.used.get() || directive.vis.get() == ty::Visibility::Public || directive.span.is_dummy() => { - if let ImportDirectiveSubclass::MacroUse = directive.subclass { + if let ImportKind::MacroUse = directive.kind { if !directive.span.is_dummy() { self.lint_buffer.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, @@ -243,10 +243,10 @@ impl Resolver<'_> { } } } - ImportDirectiveSubclass::ExternCrate { .. } => { + ImportKind::ExternCrate { .. } => { self.maybe_unused_extern_crates.push((directive.id, directive.span)); } - ImportDirectiveSubclass::MacroUse => { + ImportKind::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg); diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 18192a18cef..52d50b95000 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -18,7 +18,7 @@ use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, MultiSpan, Span}; -use crate::imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver}; +use crate::imports::{Import, ImportKind, ImportResolver}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; @@ -1126,7 +1126,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - directive: &'b ImportDirective<'b>, + directive: &'b Import<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, ) -> Option<(Option, Vec)> { @@ -1151,10 +1151,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { let module_name = crate_module.kind.name().unwrap(); - let import = match directive.subclass { - ImportDirectiveSubclass::SingleImport { source, target, .. } - if source != target => - { + let import = match directive.kind { + ImportKind::Single { source, target, .. } if source != target => { format!("{} as {}", source, target) } _ => format!("{}", ident), diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 3b018005a88..a43ef4ffee4 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -1,7 +1,5 @@ //! A bunch of methods and structures more or less related to resolving imports. -use ImportDirectiveSubclass::*; - use crate::diagnostics::Suggestion; use crate::Determinacy::{self, *}; use crate::Namespace::{self, MacroNS, TypeNS}; @@ -38,8 +36,8 @@ type Res = def::Res; /// Contains data for specific types of import directives. #[derive(Clone, Debug)] -pub enum ImportDirectiveSubclass<'a> { - SingleImport { +pub enum ImportKind<'a> { + Single { /// `source` in `use prefix::source as target`. source: Ident, /// `target` in `use prefix::source as target`. @@ -53,7 +51,7 @@ pub enum ImportDirectiveSubclass<'a> { /// Did this import result from a nested import? ie. `use foo::{bar, baz};` nested: bool, }, - GlobImport { + Glob { is_prelude: bool, max_vis: Cell, // The visibility of the greatest re-export. // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors. @@ -67,10 +65,12 @@ pub enum ImportDirectiveSubclass<'a> { /// One import directive. #[derive(Debug, Clone)] -crate struct ImportDirective<'a> { - /// The ID of the `extern crate`, `UseTree` etc that imported this `ImportDirective`. +crate struct Import<'a> { + pub kind: ImportKind<'a>, + + /// The ID of the `extern crate`, `UseTree` etc that imported this `Import`. /// - /// In the case where the `ImportDirective` was expanded from a "nested" use tree, + /// In the case where the `Import` was expanded from a "nested" use tree, /// this id is the ID of the leaf tree. For example: /// /// ```ignore (pacify the mercilous tidy) @@ -107,22 +107,21 @@ crate struct ImportDirective<'a> { pub module_path: Vec, /// The resolution of `module_path`. pub imported_module: Cell>>, - pub subclass: ImportDirectiveSubclass<'a>, pub vis: Cell, pub used: Cell, } -impl<'a> ImportDirective<'a> { +impl<'a> Import<'a> { pub fn is_glob(&self) -> bool { - match self.subclass { - ImportDirectiveSubclass::GlobImport { .. } => true, + match self.kind { + ImportKind::Glob { .. } => true, _ => false, } } pub fn is_nested(&self) -> bool { - match self.subclass { - ImportDirectiveSubclass::SingleImport { nested, .. } => nested, + match self.kind { + ImportKind::Single { nested, .. } => nested, _ => false, } } @@ -137,7 +136,7 @@ impl<'a> ImportDirective<'a> { pub struct NameResolution<'a> { /// Single imports that may define the name in the namespace. /// Import directives are arena-allocated, so it's ok to use pointers as keys. - single_imports: FxHashSet>>, + single_imports: FxHashSet>>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option<&'a NameBinding<'a>>, shadowed_glob: Option<&'a NameBinding<'a>>, @@ -155,7 +154,7 @@ impl<'a> NameResolution<'a> { }) } - crate fn add_single_import(&mut self, directive: &'a ImportDirective<'a>) { + crate fn add_single_import(&mut self, directive: &'a Import<'a>) { self.single_imports.insert(PtrKey(directive)); } } @@ -348,8 +347,8 @@ impl<'a> Resolver<'a> { single_import.imported_module.get(), return Err((Undetermined, Weak::No)) ); - let ident = match single_import.subclass { - SingleImport { source, .. } => source, + let ident = match single_import.kind { + ImportKind::Single { source, .. } => source, _ => unreachable!(), }; match self.resolve_ident_in_module( @@ -456,7 +455,7 @@ impl<'a> Resolver<'a> { crate fn import( &self, binding: &'a NameBinding<'a>, - directive: &'a ImportDirective<'a>, + directive: &'a Import<'a>, ) -> &'a NameBinding<'a> { let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` @@ -467,7 +466,7 @@ impl<'a> Resolver<'a> { binding.pseudo_vis() }; - if let GlobImport { ref max_vis, .. } = directive.subclass { + if let ImportKind::Glob { ref max_vis, .. } = directive.kind { if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) { max_vis.set(vis) } @@ -596,8 +595,8 @@ impl<'a> Resolver<'a> { // Define a "dummy" resolution containing a Res::Err as a placeholder for a // failed resolution - fn import_dummy_binding(&mut self, directive: &'a ImportDirective<'a>) { - if let SingleImport { target, .. } = directive.subclass { + fn import_dummy_binding(&mut self, directive: &'a Import<'a>) { + if let ImportKind::Single { target, .. } = directive.kind { let dummy_binding = self.dummy_binding; let dummy_binding = self.import(dummy_binding, directive); self.per_ns(|this, ns| { @@ -671,7 +670,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .chain(indeterminate_imports.into_iter().map(|i| (true, i))) { if let Some(err) = self.finalize_import(import) { - if let SingleImport { source, ref source_bindings, .. } = import.subclass { + if let ImportKind::Single { source, ref source_bindings, .. } = import.kind { if source.name == kw::SelfLower { // Silence `unresolved import` error if E0429 is already emitted if let Err(Determined) = source_bindings.value_ns.get() { @@ -695,7 +694,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if seen_spans.insert(err.span) { let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), - &import.subclass, + &import.kind, err.span, ); errors.push((path, err)); @@ -706,7 +705,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { self.r.used_imports.insert((import.id, TypeNS)); let path = import_path_to_string( &import.module_path.iter().map(|seg| seg.ident).collect::>(), - &import.subclass, + &import.kind, import.span, ); let err = UnresolvedImportError { @@ -767,7 +766,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// Attempts to resolve the given import, returning true if its resolution is determined. /// If successful, the resolved bindings are written into the module. - fn resolve_import(&mut self, directive: &'b ImportDirective<'b>) -> bool { + fn resolve_import(&mut self, directive: &'b Import<'b>) -> bool { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", Segment::names_to_string(&directive.module_path), @@ -798,22 +797,22 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; directive.imported_module.set(Some(module)); - let (source, target, source_bindings, target_bindings, type_ns_only) = - match directive.subclass { - SingleImport { - source, - target, - ref source_bindings, - ref target_bindings, - type_ns_only, - .. - } => (source, target, source_bindings, target_bindings, type_ns_only), - GlobImport { .. } => { - self.resolve_glob_import(directive); - return true; - } - _ => unreachable!(), - }; + let (source, target, source_bindings, target_bindings, type_ns_only) = match directive.kind + { + ImportKind::Single { + source, + target, + ref source_bindings, + ref target_bindings, + type_ns_only, + .. + } => (source, target, source_bindings, target_bindings, type_ns_only), + ImportKind::Glob { .. } => { + self.resolve_glob_import(directive); + return true; + } + _ => unreachable!(), + }; let mut indeterminate = false; self.r.per_ns(|this, ns| { @@ -873,10 +872,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import( - &mut self, - directive: &'b ImportDirective<'b>, - ) -> Option { + fn finalize_import(&mut self, directive: &'b Import<'b>) -> Option { let orig_vis = directive.vis.replace(ty::Visibility::Invisible); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let path_res = self.r.resolve_path( @@ -957,10 +953,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), }; - let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive - .subclass - { - SingleImport { + let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive.kind { + ImportKind::Single { source, target, ref source_bindings, @@ -968,7 +962,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { type_ns_only, .. } => (source, target, source_bindings, target_bindings, type_ns_only), - GlobImport { is_prelude, ref max_vis } => { + ImportKind::Glob { is_prelude, ref max_vis } => { if directive.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. @@ -1272,7 +1266,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { fn check_for_redundant_imports( &mut self, ident: Ident, - directive: &'b ImportDirective<'b>, + directive: &'b Import<'b>, source_bindings: &PerNS, Determinacy>>>, target_bindings: &PerNS>>>, target: Ident, @@ -1337,7 +1331,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } - fn resolve_glob_import(&mut self, directive: &'b ImportDirective<'b>) { + fn resolve_glob_import(&mut self, directive: &'b Import<'b>) { let module = match directive.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, _ => { @@ -1351,7 +1345,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { return; } else if module.def_id() == directive.parent_scope.module.def_id() { return; - } else if let GlobImport { is_prelude: true, .. } = directive.subclass { + } else if let ImportKind::Glob { is_prelude: true, .. } = directive.kind { self.r.prelude = Some(module); return; } @@ -1412,11 +1406,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { && orig_binding.is_variant() && !orig_binding.vis.is_at_least(binding.vis, &*this) { - let msg = match directive.subclass { - ImportDirectiveSubclass::SingleImport { .. } => { + let msg = match directive.kind { + ImportKind::Single { .. } => { format!("variant `{}` is private and cannot be re-exported", ident) } - ImportDirectiveSubclass::GlobImport { .. } => { + ImportKind::Glob { .. } => { let msg = "enum is private and its variants \ cannot be re-exported" .to_owned(); @@ -1432,7 +1426,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } msg } - ref s => bug!("unexpected import subclass {:?}", s), + ref s => bug!("unexpected import kind {:?}", s), }; let mut err = this.session.struct_span_err(binding.span, &msg); @@ -1481,11 +1475,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } -fn import_path_to_string( - names: &[Ident], - subclass: &ImportDirectiveSubclass<'_>, - span: Span, -) -> String { +fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Span) -> String { let pos = names.iter().position(|p| span == p.span && p.name != kw::PathRoot); let global = !names.is_empty() && names[0].name == kw::PathRoot; if let Some(pos) = pos { @@ -1494,22 +1484,22 @@ fn import_path_to_string( } else { let names = if global { &names[1..] } else { names }; if names.is_empty() { - import_directive_subclass_to_string(subclass) + import_directive_subclass_to_string(import_kind) } else { format!( "{}::{}", names_to_string(&names.iter().map(|ident| ident.name).collect::>()), - import_directive_subclass_to_string(subclass), + import_directive_subclass_to_string(import_kind), ) } } } -fn import_directive_subclass_to_string(subclass: &ImportDirectiveSubclass<'_>) -> String { - match *subclass { - SingleImport { source, .. } => source.to_string(), - GlobImport { .. } => "*".to_string(), - ExternCrate { .. } => "".to_string(), - MacroUse => "#[macro_use]".to_string(), +fn import_directive_subclass_to_string(import_kind: &ImportKind<'_>) -> String { + match import_kind { + ImportKind::Single { source, .. } => source.to_string(), + ImportKind::Glob { .. } => "*".to_string(), + ImportKind::ExternCrate { .. } => "".to_string(), + ImportKind::MacroUse => "#[macro_use]".to_string(), } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 44eba0d533d..2ffcf340b9a 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -56,7 +56,7 @@ use std::{cmp, fmt, iter, ptr}; use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_next_binding}; use diagnostics::{ImportSuggestion, Suggestion}; -use imports::{ImportDirective, ImportDirectiveSubclass, ImportResolver, NameResolution}; +use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, Rib, RibKind::*}; use macros::{LegacyBinding, LegacyScope}; @@ -456,8 +456,8 @@ pub struct ModuleData<'a> { no_implicit_prelude: bool, - glob_importers: RefCell>>, - globs: RefCell>>, + glob_importers: RefCell>>, + globs: RefCell>>, // Used to memoize the traits in this module for faster searches through all traits in scope. traits: RefCell)]>>>, @@ -584,7 +584,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res, /* is_macro_export */ bool), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, directive: &'a ImportDirective<'a>, used: Cell }, + Import { binding: &'a NameBinding<'a>, directive: &'a Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -713,8 +713,7 @@ impl<'a> NameBinding<'a> { fn is_extern_crate(&self) -> bool { match self.kind { NameBindingKind::Import { - directive: - &ImportDirective { subclass: ImportDirectiveSubclass::ExternCrate { .. }, .. }, + directive: &Import { kind: ImportKind::ExternCrate { .. }, .. }, .. } => true, NameBindingKind::Module(&ModuleData { @@ -839,10 +838,10 @@ pub struct Resolver<'a> { field_names: FxHashMap>>, /// All imports known to succeed or fail. - determined_imports: Vec<&'a ImportDirective<'a>>, + determined_imports: Vec<&'a Import<'a>>, /// All non-determined imports. - indeterminate_imports: Vec<&'a ImportDirective<'a>>, + indeterminate_imports: Vec<&'a Import<'a>>, /// FIXME: Refactor things so that these fields are passed through arguments and not resolver. /// We are resolving a last import segment during import validation. @@ -947,7 +946,7 @@ pub struct Resolver<'a> { /// Avoid duplicated errors for "name already defined". name_already_seen: FxHashMap, - potentially_unused_imports: Vec<&'a ImportDirective<'a>>, + potentially_unused_imports: Vec<&'a Import<'a>>, /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. @@ -971,7 +970,7 @@ pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, - import_directives: arena::TypedArena>, + import_directives: arena::TypedArena>, name_resolutions: arena::TypedArena>>, legacy_bindings: arena::TypedArena>, ast_paths: arena::TypedArena, @@ -991,10 +990,7 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { self.name_bindings.alloc(name_binding) } - fn alloc_import_directive( - &'a self, - import_directive: ImportDirective<'a>, - ) -> &'a ImportDirective<'_> { + fn alloc_import_directive(&'a self, import_directive: Import<'a>) -> &'a Import<'_> { self.import_directives.alloc(import_directive) } fn alloc_name_resolution(&'a self) -> &'a RefCell> { @@ -1431,7 +1427,7 @@ impl<'a> Resolver<'a> { } #[inline] - fn add_to_glob_map(&mut self, directive: &ImportDirective<'_>, ident: Ident) { + fn add_to_glob_map(&mut self, directive: &Import<'_>, ident: Ident) { if directive.is_glob() { self.glob_map.entry(directive.id).or_default().insert(ident.name); } @@ -2261,7 +2257,7 @@ impl<'a> Resolver<'a> { if let NameBindingKind::Import { directive: d, .. } = binding.kind { // Careful: we still want to rewrite paths from // renamed extern crates. - if let ImportDirectiveSubclass::ExternCrate { source: None, .. } = d.subclass { + if let ImportKind::ExternCrate { source: None, .. } = d.kind { return; } } @@ -2639,7 +2635,7 @@ impl<'a> Resolver<'a> { &self, err: &mut DiagnosticBuilder<'_>, name: Name, - directive: &ImportDirective<'_>, + directive: &Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -2649,11 +2645,11 @@ impl<'a> Resolver<'a> { }; let mut suggestion = None; - match directive.subclass { - ImportDirectiveSubclass::SingleImport { type_ns_only: true, .. } => { + match directive.kind { + ImportKind::Single { type_ns_only: true, .. } => { suggestion = Some(format!("self as {}", suggested_name)) } - ImportDirectiveSubclass::SingleImport { source, .. } => { + ImportKind::Single { source, .. } => { if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0).map(|pos| pos as usize) { @@ -2669,7 +2665,7 @@ impl<'a> Resolver<'a> { } } } - ImportDirectiveSubclass::ExternCrate { source, target, .. } => { + ImportKind::ExternCrate { source, target, .. } => { suggestion = Some(format!( "extern crate {} as {};", source.unwrap_or(target.name), @@ -2717,7 +2713,7 @@ impl<'a> Resolver<'a> { fn add_suggestion_for_duplicate_nested_use( &self, err: &mut DiagnosticBuilder<'_>, - directive: &ImportDirective<'_>, + directive: &Import<'_>, binding_span: Span, ) { assert!(directive.is_nested()); From 66d7a88c41ebcc25e499babd103177a9d8df6cdb Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 19:02:32 +0300 Subject: [PATCH 0856/1250] resolve: `directive` -> `import` --- src/librustc_resolve/build_reduced_graph.rs | 51 ++-- src/librustc_resolve/check_unused.rs | 30 +- src/librustc_resolve/diagnostics.rs | 18 +- src/librustc_resolve/imports.rs | 264 +++++++++--------- src/librustc_resolve/late.rs | 8 +- src/librustc_resolve/lib.rs | 77 +++-- .../ui/rust-2018/macro-use-warned-against.rs | 2 +- .../rust-2018/macro-use-warned-against.stderr | 2 +- 8 files changed, 215 insertions(+), 237 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 32cf1af60ec..ec5a8c4a0b8 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -307,8 +307,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { }) } - // Add an import directive to the current module. - fn add_import_directive( + // Add an import to the current module. + fn add_import( &mut self, module_path: Vec, kind: ImportKind<'a>, @@ -320,7 +320,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { vis: ty::Visibility, ) { let current_module = self.parent_scope.module; - let directive = self.r.arenas.alloc_import_directive(Import { + let import = self.r.arenas.alloc_import(Import { kind, parent_scope: self.parent_scope, module_path, @@ -336,10 +336,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { used: Cell::new(false), }); - debug!("add_import_directive({:?})", directive); + debug!("add_import({:?})", import); - self.r.indeterminate_imports.push(directive); - match directive.kind { + self.r.indeterminate_imports.push(import); + match import.kind { // Don't add unresolved underscore imports to modules ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {} ImportKind::Single { target, type_ns_only, .. } => { @@ -347,14 +347,14 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if !type_ns_only || ns == TypeNS { let key = this.new_key(target, ns); let mut resolution = this.resolution(current_module, key).borrow_mut(); - resolution.add_single_import(directive); + resolution.add_single_import(import); } }); } // We don't add prelude imports to the globs since they only affect lexical scopes, // which are not relevant to import resolution. ImportKind::Glob { is_prelude: true, .. } => {} - ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(directive), + ImportKind::Glob { .. } => current_module.globs.borrow_mut().push(import), _ => unreachable!(), } } @@ -495,7 +495,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { type_ns_only, nested, }; - self.add_import_directive( + self.add_import( module_path, kind, use_tree.span, @@ -511,16 +511,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { is_prelude: attr::contains_name(&item.attrs, sym::prelude_import), max_vis: Cell::new(ty::Visibility::Invisible), }; - self.add_import_directive( - prefix, - kind, - use_tree.span, - id, - item, - root_span, - item.id, - vis, - ); + self.add_import(prefix, kind, use_tree.span, id, item, root_span, item.id, vis); } ast::UseTreeKind::Nested(ref items) => { // Ensure there is at most one `self` in the list @@ -636,7 +627,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { 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(Import { + let import = self.r.arenas.alloc_import(Import { kind: ImportKind::ExternCrate { source: orig_name, target: ident }, root_id: item.id, id: item.id, @@ -651,8 +642,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { vis: Cell::new(vis), used: Cell::new(used), }); - self.r.potentially_unused_imports.push(directive); - let imported_binding = self.r.import(binding, directive); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); if ptr::eq(parent, self.r.graph_root) { if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) { if expansion != ExpnId::root() @@ -988,8 +979,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - let macro_use_directive = |this: &Self, span| { - this.r.arenas.alloc_import_directive(Import { + let macro_use_import = |this: &Self, span| { + this.r.arenas.alloc_import(Import { kind: ImportKind::MacroUse, root_id: item.id, id: item.id, @@ -1008,11 +999,11 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let allow_shadowing = self.parent_scope.expansion == ExpnId::root(); if let Some(span) = import_all { - let directive = macro_use_directive(self, span); - self.r.potentially_unused_imports.push(directive); + let import = macro_use_import(self, span); + self.r.potentially_unused_imports.push(import); module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { - let imported_binding = this.r.import(binding, directive); + let imported_binding = this.r.import(binding, import); this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); } }); @@ -1027,9 +1018,9 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { ident.span, ); if let Ok(binding) = result { - let directive = macro_use_directive(self, ident.span); - self.r.potentially_unused_imports.push(directive); - let imported_binding = self.r.import(binding, directive); + let import = macro_use_import(self, ident.span); + self.r.potentially_unused_imports.push(import); + let imported_binding = self.r.import(binding, import); self.legacy_import_macro( ident.name, imported_binding, diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 5d45fcb3934..722f843ab6e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -3,7 +3,7 @@ // // Although this is mostly a lint pass, it lives in here because it depends on // resolve data structures and because it finalises the privacy information for -// `use` directives. +// `use` items. // // Unused trait imports can't be checked until the method resolution. We save // candidates here, and do the actual check in librustc_typeck/check_unused.rs. @@ -58,7 +58,7 @@ struct UnusedImportCheckVisitor<'a, 'b> { } impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { - // We have information about whether `use` (import) directives are actually + // We have information about whether `use` (import) items are actually // used now. If an import is not used at all, we signal a lint error. fn check_import(&mut self, id: ast::NodeId) { let mut used = false; @@ -223,33 +223,33 @@ fn calc_unused_spans( impl Resolver<'_> { crate fn check_unused(&mut self, krate: &ast::Crate) { - for directive in self.potentially_unused_imports.iter() { - match directive.kind { - _ if directive.used.get() - || directive.vis.get() == ty::Visibility::Public - || directive.span.is_dummy() => + for import in self.potentially_unused_imports.iter() { + match import.kind { + _ if import.used.get() + || import.vis.get() == ty::Visibility::Public + || import.span.is_dummy() => { - if let ImportKind::MacroUse = directive.kind { - if !directive.span.is_dummy() { + if let ImportKind::MacroUse = import.kind { + if !import.span.is_dummy() { self.lint_buffer.buffer_lint( lint::builtin::MACRO_USE_EXTERN_CRATE, - directive.id, - directive.span, - "deprecated `#[macro_use]` directive used to \ + import.id, + import.span, + "deprecated `#[macro_use]` attribute used to \ import macros should be replaced at use sites \ - with a `use` statement to import the macro \ + with a `use` item to import the macro \ instead", ); } } } ImportKind::ExternCrate { .. } => { - self.maybe_unused_extern_crates.push((directive.id, directive.span)); + self.maybe_unused_extern_crates.push((import.id, import.span)); } ImportKind::MacroUse => { let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(lint, directive.id, directive.span, msg); + self.lint_buffer.buffer_lint(lint, import.id, import.span, msg); } _ => {} } diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 52d50b95000..38efc907ff0 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -1126,7 +1126,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// ``` pub(crate) fn check_for_module_export_macro( &mut self, - directive: &'b Import<'b>, + import: &'b Import<'b>, module: ModuleOrUniformRoot<'b>, ident: Ident, ) -> Option<(Option, Vec)> { @@ -1151,7 +1151,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let binding = resolution.borrow().binding()?; if let Res::Def(DefKind::Macro(MacroKind::Bang), _) = binding.res() { let module_name = crate_module.kind.name().unwrap(); - let import = match directive.kind { + let import_snippet = match import.kind { ImportKind::Single { source, target, .. } if source != target => { format!("{} as {}", source, target) } @@ -1159,18 +1159,18 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; let mut corrections: Vec<(Span, String)> = Vec::new(); - if !directive.is_nested() { + if !import.is_nested() { // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove // intermediate segments. - corrections.push((directive.span, format!("{}::{}", module_name, import))); + corrections.push((import.span, format!("{}::{}", module_name, import_snippet))); } else { // Find the binding span (and any trailing commas and spaces). // ie. `use a::b::{c, d, e};` // ^^^ let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding( self.r.session, - directive.span, - directive.use_span, + import.span, + import.use_span, ); debug!( "check_for_module_export_macro: found_closing_brace={:?} binding_span={:?}", @@ -1207,7 +1207,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let (has_nested, after_crate_name) = find_span_immediately_after_crate_name( self.r.session, module_name, - directive.use_span, + import.use_span, ); debug!( "check_for_module_export_macro: has_nested={:?} after_crate_name={:?}", @@ -1223,11 +1223,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { start_point, if has_nested { // In this case, `start_snippet` must equal '{'. - format!("{}{}, ", start_snippet, import) + format!("{}{}, ", start_snippet, import_snippet) } else { // In this case, add a `{`, then the moved import, then whatever // was there before. - format!("{{{}, {}", import, start_snippet) + format!("{{{}, {}", import_snippet, start_snippet) }, )); } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index a43ef4ffee4..81c1e496c9d 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -34,7 +34,7 @@ use std::{mem, ptr}; type Res = def::Res; -/// Contains data for specific types of import directives. +/// Contains data for specific kinds of imports. #[derive(Clone, Debug)] pub enum ImportKind<'a> { Single { @@ -63,7 +63,7 @@ pub enum ImportKind<'a> { MacroUse, } -/// One import directive. +/// One import. #[derive(Debug, Clone)] crate struct Import<'a> { pub kind: ImportKind<'a>, @@ -77,7 +77,7 @@ crate struct Import<'a> { /// use foo::bar::{a, b} /// ``` /// - /// If this is the import directive for `foo::bar::a`, we would have the ID of the `UseTree` + /// If this is the import for `foo::bar::a`, we would have the ID of the `UseTree` /// for `a` in this field. pub id: NodeId, @@ -135,7 +135,7 @@ impl<'a> Import<'a> { /// Records information about the resolution of a name in a namespace of a module. pub struct NameResolution<'a> { /// Single imports that may define the name in the namespace. - /// Import directives are arena-allocated, so it's ok to use pointers as keys. + /// Imports are arena-allocated, so it's ok to use pointers as keys. single_imports: FxHashSet>>, /// The least shadowable known binding for this name, or None if there are no known bindings. pub binding: Option<&'a NameBinding<'a>>, @@ -154,8 +154,8 @@ impl<'a> NameResolution<'a> { }) } - crate fn add_single_import(&mut self, directive: &'a Import<'a>) { - self.single_imports.insert(PtrKey(directive)); + crate fn add_single_import(&mut self, import: &'a Import<'a>) { + self.single_imports.insert(PtrKey(import)); } } @@ -450,34 +450,34 @@ impl<'a> Resolver<'a> { Err((Determined, Weak::No)) } - // Given a binding and an import directive that resolves to it, - // return the corresponding binding defined by the import directive. + // Given a binding and an import that resolves to it, + // return the corresponding binding defined by the import. crate fn import( &self, binding: &'a NameBinding<'a>, - directive: &'a Import<'a>, + import: &'a Import<'a>, ) -> &'a NameBinding<'a> { - let vis = if binding.pseudo_vis().is_at_least(directive.vis.get(), self) || + let vis = if binding.pseudo_vis().is_at_least(import.vis.get(), self) || // cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE` - !directive.is_glob() && binding.is_extern_crate() + !import.is_glob() && binding.is_extern_crate() { - directive.vis.get() + import.vis.get() } else { binding.pseudo_vis() }; - if let ImportKind::Glob { ref max_vis, .. } = directive.kind { - if vis == directive.vis.get() || vis.is_at_least(max_vis.get(), self) { + if let ImportKind::Glob { ref max_vis, .. } = import.kind { + if vis == import.vis.get() || vis.is_at_least(max_vis.get(), self) { max_vis.set(vis) } } self.arenas.alloc_name_binding(NameBinding { - kind: NameBindingKind::Import { binding, directive, used: Cell::new(false) }, + kind: NameBindingKind::Import { binding, import, used: Cell::new(false) }, ambiguity: None, - span: directive.span, + span: import.span, vis, - expansion: directive.parent_scope.expansion, + expansion: import.parent_scope.expansion, }) } @@ -576,17 +576,17 @@ impl<'a> Resolver<'a> { }; // Define `binding` in `module`s glob importers. - for directive in module.glob_importers.borrow_mut().iter() { + for import in module.glob_importers.borrow_mut().iter() { let mut ident = key.ident; - let scope = match ident.span.reverse_glob_adjust(module.expansion, directive.span) { + let scope = match ident.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.macro_def_scope(def), - Some(None) => directive.parent_scope.module, + Some(None) => import.parent_scope.module, None => continue, }; if self.is_accessible_from(binding.vis, scope) { - let imported_binding = self.import(binding, directive); + let imported_binding = self.import(binding, import); let key = BindingKey { ident, ..key }; - let _ = self.try_define(directive.parent_scope.module, key, imported_binding); + let _ = self.try_define(import.parent_scope.module, key, imported_binding); } } @@ -595,13 +595,13 @@ impl<'a> Resolver<'a> { // Define a "dummy" resolution containing a Res::Err as a placeholder for a // failed resolution - fn import_dummy_binding(&mut self, directive: &'a Import<'a>) { - if let ImportKind::Single { target, .. } = directive.kind { + fn import_dummy_binding(&mut self, import: &'a Import<'a>) { + if let ImportKind::Single { target, .. } = import.kind { let dummy_binding = self.dummy_binding; - let dummy_binding = self.import(dummy_binding, directive); + let dummy_binding = self.import(dummy_binding, import); self.per_ns(|this, ns| { let key = this.new_key(target, ns); - let _ = this.try_define(directive.parent_scope.module, key, dummy_binding); + let _ = this.try_define(import.parent_scope.module, key, dummy_binding); // Consider erroneous imports used to avoid duplicate diagnostics. this.record_use(target, ns, dummy_binding, false); }); @@ -766,28 +766,28 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// Attempts to resolve the given import, returning true if its resolution is determined. /// If successful, the resolved bindings are written into the module. - fn resolve_import(&mut self, directive: &'b Import<'b>) -> bool { + fn resolve_import(&mut self, import: &'b Import<'b>) -> bool { debug!( "(resolving import for module) resolving import `{}::...` in `{}`", - Segment::names_to_string(&directive.module_path), - module_to_string(directive.parent_scope.module).unwrap_or_else(|| "???".to_string()), + Segment::names_to_string(&import.module_path), + module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()), ); - let module = if let Some(module) = directive.imported_module.get() { + let module = if let Some(module) = import.imported_module.get() { module } else { // For better failure detection, pretend that the import will // not define any names while resolving its module path. - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let path_res = self.r.resolve_path( - &directive.module_path, + &import.module_path, None, - &directive.parent_scope, + &import.parent_scope, false, - directive.span, - directive.crate_lint(), + import.span, + import.crate_lint(), ); - directive.vis.set(orig_vis); + import.vis.set(orig_vis); match path_res { PathResult::Module(module) => module, @@ -796,9 +796,8 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } }; - directive.imported_module.set(Some(module)); - let (source, target, source_bindings, target_bindings, type_ns_only) = match directive.kind - { + import.imported_module.set(Some(module)); + let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind { ImportKind::Single { source, target, @@ -808,7 +807,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .. } => (source, target, source_bindings, target_bindings, type_ns_only), ImportKind::Glob { .. } => { - self.resolve_glob_import(directive); + self.resolve_glob_import(import); return true; } _ => unreachable!(), @@ -820,23 +819,23 @@ impl<'a, 'b> ImportResolver<'a, 'b> { if let Err(Undetermined) = source_bindings[ns].get() { // For better failure detection, pretend that the import will // not define any names while resolving its module path. - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let binding = this.resolve_ident_in_module( module, source, ns, - &directive.parent_scope, + &import.parent_scope, false, - directive.span, + import.span, ); - directive.vis.set(orig_vis); + import.vis.set(orig_vis); source_bindings[ns].set(binding); } else { return; }; - let parent = directive.parent_scope.module; + let parent = import.parent_scope.module; match source_bindings[ns].get() { Err(Undetermined) => indeterminate = true, // Don't update the resolution, because it was never added. @@ -844,20 +843,20 @@ impl<'a, 'b> ImportResolver<'a, 'b> { Err(Determined) => { let key = this.new_key(target, ns); this.update_resolution(parent, key, |_, resolution| { - resolution.single_imports.remove(&PtrKey(directive)); + resolution.single_imports.remove(&PtrKey(import)); }); } Ok(binding) if !binding.is_importable() => { let msg = format!("`{}` is not directly importable", target); - struct_span_err!(this.session, directive.span, E0253, "{}", &msg) - .span_label(directive.span, "cannot be imported directly") + struct_span_err!(this.session, import.span, E0253, "{}", &msg) + .span_label(import.span, "cannot be imported directly") .emit(); // Do not import this illegal binding. Import a dummy binding and pretend // everything is fine - this.import_dummy_binding(directive); + this.import_dummy_binding(import); } Ok(binding) => { - let imported_binding = this.import(binding, directive); + let imported_binding = this.import(binding, import); target_bindings[ns].set(Some(imported_binding)); this.define(parent, target, ns, imported_binding); } @@ -872,35 +871,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> { /// /// Optionally returns an unresolved import error. This error is buffered and used to /// consolidate multiple unresolved import errors into a single diagnostic. - fn finalize_import(&mut self, directive: &'b Import<'b>) -> Option { - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + fn finalize_import(&mut self, import: &'b Import<'b>) -> Option { + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let prev_ambiguity_errors_len = self.r.ambiguity_errors.len(); let path_res = self.r.resolve_path( - &directive.module_path, + &import.module_path, None, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, - directive.crate_lint(), + import.span, + import.crate_lint(), ); let no_ambiguity = self.r.ambiguity_errors.len() == prev_ambiguity_errors_len; - directive.vis.set(orig_vis); + import.vis.set(orig_vis); if let PathResult::Failed { .. } | PathResult::NonModule(..) = path_res { // Consider erroneous imports used to avoid duplicate diagnostics. - self.r.used_imports.insert((directive.id, TypeNS)); + self.r.used_imports.insert((import.id, TypeNS)); } let module = match path_res { PathResult::Module(module) => { // Consistency checks, analogous to `finalize_macro_resolutions`. - if let Some(initial_module) = directive.imported_module.get() { + if let Some(initial_module) = import.imported_module.get() { if !ModuleOrUniformRoot::same_def(module, initial_module) && no_ambiguity { - span_bug!(directive.span, "inconsistent resolution for an import"); + span_bug!(import.span, "inconsistent resolution for an import"); } } else { if self.r.privacy_errors.is_empty() { let msg = "cannot determine resolution for the import"; let msg_note = "import resolution is stuck, try simplifying other imports"; - self.r.session.struct_span_err(directive.span, msg).note(msg_note).emit(); + self.r.session.struct_span_err(import.span, msg).note(msg_note).emit(); } } @@ -908,7 +907,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::Failed { is_error_from_last_segment: false, span, label, suggestion } => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); self.r .report_error(span, ResolutionError::FailedToResolve { label, suggestion }); } @@ -916,11 +915,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::Failed { is_error_from_last_segment: true, span, label, suggestion } => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); let err = match self.make_path_suggestion( span, - directive.module_path.clone(), - &directive.parent_scope, + import.module_path.clone(), + &import.parent_scope, ) { Some((suggestion, note)) => UnresolvedImportError { span, @@ -945,7 +944,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } PathResult::NonModule(path_res) if path_res.base_res() == Res::Err => { if no_ambiguity { - assert!(directive.imported_module.get().is_none()); + assert!(import.imported_module.get().is_none()); } // The error was already reported earlier. return None; @@ -953,7 +952,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(), }; - let (ident, target, source_bindings, target_bindings, type_ns_only) = match directive.kind { + let (ident, target, source_bindings, target_bindings, type_ns_only) = match import.kind { ImportKind::Single { source, target, @@ -963,24 +962,24 @@ impl<'a, 'b> ImportResolver<'a, 'b> { .. } => (source, target, source_bindings, target_bindings, type_ns_only), ImportKind::Glob { is_prelude, ref max_vis } => { - if directive.module_path.len() <= 1 { + if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. - let mut full_path = directive.module_path.clone(); + let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(Ident::invalid())); self.r.lint_if_path_starts_with_module( - directive.crate_lint(), + import.crate_lint(), &full_path, - directive.span, + import.span, None, ); } if let ModuleOrUniformRoot::Module(module) = module { - if module.def_id() == directive.parent_scope.module.def_id() { + if module.def_id() == import.parent_scope.module.def_id() { // Importing a module into itself is not allowed. return Some(UnresolvedImportError { - span: directive.span, + span: import.span, label: Some(String::from("cannot glob-import a module into itself")), note: Vec::new(), suggestion: None, @@ -989,15 +988,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } if !is_prelude && max_vis.get() != ty::Visibility::Invisible && // Allow empty globs. - !max_vis.get().is_at_least(directive.vis.get(), &*self) + !max_vis.get().is_at_least(import.vis.get(), &*self) { let msg = "glob import doesn't reexport anything because no candidate is public enough"; - self.r.lint_buffer.buffer_lint( - UNUSED_IMPORTS, - directive.id, - directive.span, - msg, - ); + self.r.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg); } return None; } @@ -1007,7 +1001,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut all_ns_err = true; self.r.per_ns(|this, ns| { if !type_ns_only || ns == TypeNS { - let orig_vis = directive.vis.replace(ty::Visibility::Invisible); + let orig_vis = import.vis.replace(ty::Visibility::Invisible); let orig_blacklisted_binding = mem::replace(&mut this.blacklisted_binding, target_bindings[ns].get()); let orig_last_import_segment = mem::replace(&mut this.last_import_segment, true); @@ -1015,13 +1009,13 @@ impl<'a, 'b> ImportResolver<'a, 'b> { module, ident, ns, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, + import.span, ); this.last_import_segment = orig_last_import_segment; this.blacklisted_binding = orig_blacklisted_binding; - directive.vis.set(orig_vis); + import.vis.set(orig_vis); match binding { Ok(binding) => { @@ -1038,7 +1032,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ident, ns, target_binding, - directive.module_path.is_empty(), + import.module_path.is_empty(), ); } } @@ -1047,7 +1041,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let res = binding.res(); if let Ok(initial_res) = initial_res { if res != initial_res && this.ambiguity_errors.is_empty() { - span_bug!(directive.span, "inconsistent resolution for an import"); + span_bug!(import.span, "inconsistent resolution for an import"); } } else { if res != Res::Err @@ -1058,7 +1052,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let msg_note = "import resolution is stuck, try simplifying other imports"; this.session - .struct_span_err(directive.span, msg) + .struct_span_err(import.span, msg) .note(msg_note) .emit(); } @@ -1084,9 +1078,9 @@ impl<'a, 'b> ImportResolver<'a, 'b> { module, ident, ns, - &directive.parent_scope, + &import.parent_scope, true, - directive.span, + import.span, ); if binding.is_ok() { all_ns_failed = false; @@ -1137,7 +1131,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }); let (suggestion, note) = - match self.check_for_module_export_macro(directive, module, ident) { + match self.check_for_module_export_macro(import, module, ident) { Some((suggestion, note)) => (suggestion.or(lev_suggestion), note), _ => (lev_suggestion, Vec::new()), }; @@ -1163,14 +1157,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; Some(UnresolvedImportError { - span: directive.span, + span: import.span, label: Some(label), note, suggestion, }) } else { // `resolve_ident_in_module` reported a privacy error. - self.r.import_dummy_binding(directive); + self.r.import_dummy_binding(import); None }; } @@ -1179,7 +1173,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> { let mut any_successful_reexport = false; self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { - let vis = directive.vis.get(); + let vis = import.vis.get(); if !binding.pseudo_vis().is_at_least(vis, &*this) { reexport_error = Some((ns, binding)); } else { @@ -1200,42 +1194,42 @@ impl<'a, 'b> ImportResolver<'a, 'b> { ); self.r.lint_buffer.buffer_lint( PUB_USE_OF_PRIVATE_EXTERN_CRATE, - directive.id, - directive.span, + import.id, + import.span, &msg, ); } else if ns == TypeNS { struct_span_err!( self.r.session, - directive.span, + import.span, E0365, "`{}` is private, and cannot be re-exported", ident ) - .span_label(directive.span, format!("re-export of private `{}`", ident)) + .span_label(import.span, format!("re-export of private `{}`", ident)) .note(&format!("consider declaring type or module `{}` with `pub`", ident)) .emit(); } else { let msg = format!("`{}` is private, and cannot be re-exported", ident); let note_msg = format!("consider marking `{}` as `pub` in the imported module", ident,); - struct_span_err!(self.r.session, directive.span, E0364, "{}", &msg) - .span_note(directive.span, ¬e_msg) + struct_span_err!(self.r.session, import.span, E0364, "{}", &msg) + .span_note(import.span, ¬e_msg) .emit(); } } - if directive.module_path.len() <= 1 { + if import.module_path.len() <= 1 { // HACK(eddyb) `lint_if_path_starts_with_module` needs at least // 2 segments, so the `resolve_path` above won't trigger it. - let mut full_path = directive.module_path.clone(); + let mut full_path = import.module_path.clone(); full_path.push(Segment::from_ident(ident)); self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { this.lint_if_path_starts_with_module( - directive.crate_lint(), + import.crate_lint(), &full_path, - directive.span, + import.span, Some(binding), ); } @@ -1247,17 +1241,11 @@ impl<'a, 'b> ImportResolver<'a, 'b> { // purposes it's good enough to just favor one over the other. self.r.per_ns(|this, ns| { if let Ok(binding) = source_bindings[ns].get() { - this.import_res_map.entry(directive.id).or_default()[ns] = Some(binding.res()); + this.import_res_map.entry(import.id).or_default()[ns] = Some(binding.res()); } }); - self.check_for_redundant_imports( - ident, - directive, - source_bindings, - target_bindings, - target, - ); + self.check_for_redundant_imports(ident, import, source_bindings, target_bindings, target); debug!("(resolving single import) successfully resolved import"); None @@ -1266,19 +1254,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> { fn check_for_redundant_imports( &mut self, ident: Ident, - directive: &'b Import<'b>, + import: &'b Import<'b>, source_bindings: &PerNS, Determinacy>>>, target_bindings: &PerNS>>>, target: Ident, ) { // Skip if the import was produced by a macro. - if directive.parent_scope.expansion != ExpnId::root() { + if import.parent_scope.expansion != ExpnId::root() { return; } // Skip if we are inside a named module (in contrast to an anonymous // module defined by a block). - if let ModuleKind::Def(..) = directive.parent_scope.module.kind { + if let ModuleKind::Def(..) = import.parent_scope.module.kind { return; } @@ -1298,10 +1286,10 @@ impl<'a, 'b> ImportResolver<'a, 'b> { match this.early_resolve_ident_in_lexical_scope( target, ScopeSet::All(ns, false), - &directive.parent_scope, + &import.parent_scope, false, false, - directive.span, + import.span, ) { Ok(other_binding) => { is_redundant[ns] = Some( @@ -1323,35 +1311,35 @@ impl<'a, 'b> ImportResolver<'a, 'b> { redundant_spans.dedup(); self.r.lint_buffer.buffer_lint_with_diagnostic( UNUSED_IMPORTS, - directive.id, - directive.span, + import.id, + import.span, &format!("the item `{}` is imported redundantly", ident), BuiltinLintDiagnostics::RedundantImport(redundant_spans, ident), ); } } - fn resolve_glob_import(&mut self, directive: &'b Import<'b>) { - let module = match directive.imported_module.get().unwrap() { + fn resolve_glob_import(&mut self, import: &'b Import<'b>) { + let module = match import.imported_module.get().unwrap() { ModuleOrUniformRoot::Module(module) => module, _ => { - self.r.session.span_err(directive.span, "cannot glob-import all possible crates"); + self.r.session.span_err(import.span, "cannot glob-import all possible crates"); return; } }; if module.is_trait() { - self.r.session.span_err(directive.span, "items in traits are not importable."); + self.r.session.span_err(import.span, "items in traits are not importable."); return; - } else if module.def_id() == directive.parent_scope.module.def_id() { + } else if module.def_id() == import.parent_scope.module.def_id() { return; - } else if let ImportKind::Glob { is_prelude: true, .. } = directive.kind { + } else if let ImportKind::Glob { is_prelude: true, .. } = import.kind { self.r.prelude = Some(module); return; } // Add to module's glob_importers - module.glob_importers.borrow_mut().push(directive); + module.glob_importers.borrow_mut().push(import); // Ensure that `resolutions` isn't borrowed during `try_define`, // since it might get updated via a glob cycle. @@ -1365,19 +1353,19 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }) .collect::>(); for (mut key, binding) in bindings { - let scope = match key.ident.span.reverse_glob_adjust(module.expansion, directive.span) { + let scope = match key.ident.span.reverse_glob_adjust(module.expansion, import.span) { Some(Some(def)) => self.r.macro_def_scope(def), - Some(None) => directive.parent_scope.module, + Some(None) => import.parent_scope.module, None => continue, }; if self.r.is_accessible_from(binding.pseudo_vis(), scope) { - let imported_binding = self.r.import(binding, directive); - let _ = self.r.try_define(directive.parent_scope.module, key, imported_binding); + let imported_binding = self.r.import(binding, import); + let _ = self.r.try_define(import.parent_scope.module, key, imported_binding); } } // Record the destination of this import - self.r.record_partial_res(directive.id, PartialRes::new(module.res().unwrap())); + self.r.record_partial_res(import.id, PartialRes::new(module.res().unwrap())); } // Miscellaneous post-processing, including recording re-exports, @@ -1401,12 +1389,12 @@ impl<'a, 'b> ImportResolver<'a, 'b> { } } - if let NameBindingKind::Import { binding: orig_binding, directive, .. } = binding.kind { + if let NameBindingKind::Import { binding: orig_binding, import, .. } = binding.kind { if ns == TypeNS && orig_binding.is_variant() && !orig_binding.vis.is_at_least(binding.vis, &*this) { - let msg = match directive.kind { + let msg = match import.kind { ImportKind::Single { .. } => { format!("variant `{}` is private and cannot be re-exported", ident) } @@ -1430,14 +1418,14 @@ impl<'a, 'b> ImportResolver<'a, 'b> { }; let mut err = this.session.struct_span_err(binding.span, &msg); - let imported_module = match directive.imported_module.get() { + let imported_module = match import.imported_module.get() { Some(ModuleOrUniformRoot::Module(module)) => module, _ => bug!("module should exist"), }; let parent_module = imported_module.parent.expect("parent should exist"); let resolutions = this.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; + let enum_path_segment_index = import.module_path.len() - 1; + let enum_ident = import.module_path[enum_path_segment_index].ident; let key = this.new_key(enum_ident, TypeNS); let enum_resolution = resolutions.get(&key).expect("resolution should exist"); @@ -1484,18 +1472,18 @@ fn import_path_to_string(names: &[Ident], import_kind: &ImportKind<'_>, span: Sp } else { let names = if global { &names[1..] } else { names }; if names.is_empty() { - import_directive_subclass_to_string(import_kind) + import_kind_to_string(import_kind) } else { format!( "{}::{}", names_to_string(&names.iter().map(|ident| ident.name).collect::>()), - import_directive_subclass_to_string(import_kind), + import_kind_to_string(import_kind), ) } } } -fn import_directive_subclass_to_string(import_kind: &ImportKind<'_>) -> String { +fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String { match import_kind { ImportKind::Single { source, .. } => source.to_string(), ImportKind::Glob { .. } => "*".to_string(), diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 6b5e927214f..98bb98a3a8d 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -2189,10 +2189,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { trait_name: Ident, ) -> SmallVec<[NodeId; 1]> { let mut import_ids = smallvec![]; - while let NameBindingKind::Import { directive, binding, .. } = kind { - self.r.maybe_unused_trait_imports.insert(directive.id); - self.r.add_to_glob_map(&directive, trait_name); - import_ids.push(directive.id); + while let NameBindingKind::Import { import, binding, .. } = kind { + self.r.maybe_unused_trait_imports.insert(import.id); + self.r.add_to_glob_map(&import, trait_name); + import_ids.push(import.id); kind = &binding.kind; } import_ids diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2ffcf340b9a..492ac6ed839 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -584,7 +584,7 @@ impl<'a> ToNameBinding<'a> for &'a NameBinding<'a> { enum NameBindingKind<'a> { Res(Res, /* is_macro_export */ bool), Module(Module<'a>), - Import { binding: &'a NameBinding<'a>, directive: &'a Import<'a>, used: Cell }, + Import { binding: &'a NameBinding<'a>, import: &'a Import<'a>, used: Cell }, } impl<'a> NameBindingKind<'a> { @@ -713,7 +713,7 @@ impl<'a> NameBinding<'a> { fn is_extern_crate(&self) -> bool { match self.kind { NameBindingKind::Import { - directive: &Import { kind: ImportKind::ExternCrate { .. }, .. }, + import: &Import { kind: ImportKind::ExternCrate { .. }, .. }, .. } => true, NameBindingKind::Module(&ModuleData { @@ -733,7 +733,7 @@ impl<'a> NameBinding<'a> { fn is_glob_import(&self) -> bool { match self.kind { - NameBindingKind::Import { directive, .. } => directive.is_glob(), + NameBindingKind::Import { import, .. } => import.is_glob(), _ => false, } } @@ -970,7 +970,7 @@ pub struct ResolverArenas<'a> { modules: arena::TypedArena>, local_modules: RefCell>>, name_bindings: arena::TypedArena>, - import_directives: arena::TypedArena>, + imports: arena::TypedArena>, name_resolutions: arena::TypedArena>>, legacy_bindings: arena::TypedArena>, ast_paths: arena::TypedArena, @@ -990,8 +990,8 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_binding(&'a self, name_binding: NameBinding<'a>) -> &'a NameBinding<'a> { self.name_bindings.alloc(name_binding) } - fn alloc_import_directive(&'a self, import_directive: Import<'a>) -> &'a Import<'_> { - self.import_directives.alloc(import_directive) + fn alloc_import(&'a self, import: Import<'a>) -> &'a Import<'_> { + self.imports.alloc(import) } fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) @@ -1406,7 +1406,7 @@ impl<'a> Resolver<'a> { misc2: AmbiguityErrorMisc::None, }); } - if let NameBindingKind::Import { directive, binding, ref used } = used_binding.kind { + if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind { // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { @@ -1419,17 +1419,17 @@ impl<'a> Resolver<'a> { } } used.set(true); - directive.used.set(true); - self.used_imports.insert((directive.id, ns)); - self.add_to_glob_map(&directive, ident); + import.used.set(true); + self.used_imports.insert((import.id, ns)); + self.add_to_glob_map(&import, ident); self.record_use(ident, ns, binding, false); } } #[inline] - fn add_to_glob_map(&mut self, directive: &Import<'_>, ident: Ident) { - if directive.is_glob() { - self.glob_map.entry(directive.id).or_default().insert(ident.name); + fn add_to_glob_map(&mut self, import: &Import<'_>, ident: Ident) { + if import.is_glob() { + self.glob_map.entry(import.id).or_default().insert(ident.name); } } @@ -2254,10 +2254,9 @@ impl<'a> Resolver<'a> { // `ExternCrate` (also used for `crate::...`) then no need to issue a // warning, this looks all good! if let Some(binding) = second_binding { - if let NameBindingKind::Import { directive: d, .. } = binding.kind { - // Careful: we still want to rewrite paths from - // renamed extern crates. - if let ImportKind::ExternCrate { source: None, .. } = d.kind { + if let NameBindingKind::Import { import, .. } = binding.kind { + // Careful: we still want to rewrite paths from renamed extern crates. + if let ImportKind::ExternCrate { source: None, .. } = import.kind { return; } } @@ -2560,10 +2559,10 @@ impl<'a> Resolver<'a> { // See https://github.com/rust-lang/rust/issues/32354 use NameBindingKind::Import; - let directive = match (&new_binding.kind, &old_binding.kind) { + let import = match (&new_binding.kind, &old_binding.kind) { // If there are two imports where one or both have attributes then prefer removing the // import without attributes. - (Import { directive: new, .. }, Import { directive: old, .. }) + (Import { import: new, .. }, Import { import: old, .. }) if { !new_binding.span.is_dummy() && !old_binding.span.is_dummy() @@ -2577,11 +2576,11 @@ impl<'a> Resolver<'a> { } } // Otherwise prioritize the new binding. - (Import { directive, .. }, other) if !new_binding.span.is_dummy() => { - Some((directive, new_binding.span, other.is_import())) + (Import { import, .. }, other) if !new_binding.span.is_dummy() => { + Some((import, new_binding.span, other.is_import())) } - (other, Import { directive, .. }) if !old_binding.span.is_dummy() => { - Some((directive, old_binding.span, other.is_import())) + (other, Import { import, .. }) if !old_binding.span.is_dummy() => { + Some((import, old_binding.span, other.is_import())) } _ => None, }; @@ -2598,22 +2597,22 @@ impl<'a> Resolver<'a> { && !has_dummy_span && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item); - match directive { - Some((directive, span, true)) if should_remove_import && directive.is_nested() => { - self.add_suggestion_for_duplicate_nested_use(&mut err, directive, span) + match import { + Some((import, span, true)) if should_remove_import && import.is_nested() => { + self.add_suggestion_for_duplicate_nested_use(&mut err, import, span) } - Some((directive, _, true)) if should_remove_import && !directive.is_glob() => { + Some((import, _, true)) if should_remove_import && !import.is_glob() => { // Simple case - remove the entire import. Due to the above match arm, this can // only be a single use so just remove it entirely. err.tool_only_span_suggestion( - directive.use_span_with_attributes, + import.use_span_with_attributes, "remove unnecessary import", String::new(), Applicability::MaybeIncorrect, ); } - Some((directive, span, _)) => { - self.add_suggestion_for_rename_of_use(&mut err, name, directive, span) + Some((import, span, _)) => { + self.add_suggestion_for_rename_of_use(&mut err, name, import, span) } _ => {} } @@ -2635,7 +2634,7 @@ impl<'a> Resolver<'a> { &self, err: &mut DiagnosticBuilder<'_>, name: Name, - directive: &Import<'_>, + import: &Import<'_>, binding_span: Span, ) { let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() { @@ -2645,7 +2644,7 @@ impl<'a> Resolver<'a> { }; let mut suggestion = None; - match directive.kind { + match import.kind { ImportKind::Single { type_ns_only: true, .. } => { suggestion = Some(format!("self as {}", suggested_name)) } @@ -2707,27 +2706,27 @@ impl<'a> Resolver<'a> { /// If the nested use contains only one import then the suggestion will remove the entire /// line. /// - /// It is expected that the directive provided is a nested import - this isn't checked by the + /// It is expected that the provided import is nested - this isn't checked by the /// function. If this invariant is not upheld, this function's behaviour will be unexpected /// as characters expected by span manipulations won't be present. fn add_suggestion_for_duplicate_nested_use( &self, err: &mut DiagnosticBuilder<'_>, - directive: &Import<'_>, + import: &Import<'_>, binding_span: Span, ) { - assert!(directive.is_nested()); + assert!(import.is_nested()); let message = "remove unnecessary import"; // Two examples will be used to illustrate the span manipulations we're doing: // // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is - // `a` and `directive.use_span` is `issue_52891::{d, a, e};`. + // `a` and `import.use_span` is `issue_52891::{d, a, e};`. // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is - // `a` and `directive.use_span` is `issue_52891::{d, e, a};`. + // `a` and `import.use_span` is `issue_52891::{d, e, a};`. let (found_closing_brace, span) = - find_span_of_binding_until_next_binding(self.session, binding_span, directive.use_span); + find_span_of_binding_until_next_binding(self.session, binding_span, import.use_span); // If there was a closing brace then identify the span to remove any trailing commas from // previous imports. @@ -2743,7 +2742,7 @@ impl<'a> Resolver<'a> { // Remove the entire line if we cannot extend the span back, this indicates a // `issue_52891::{self}` case. err.span_suggestion( - directive.use_span_with_attributes, + import.use_span_with_attributes, message, String::new(), Applicability::MaybeIncorrect, diff --git a/src/test/ui/rust-2018/macro-use-warned-against.rs b/src/test/ui/rust-2018/macro-use-warned-against.rs index 6cd54aa68ae..65400163ddd 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.rs +++ b/src/test/ui/rust-2018/macro-use-warned-against.rs @@ -4,7 +4,7 @@ #![warn(macro_use_extern_crate, unused)] -#[macro_use] //~ WARN should be replaced at use sites with a `use` statement +#[macro_use] //~ WARN should be replaced at use sites with a `use` item extern crate macro_use_warned_against; #[macro_use] //~ WARN unused `#[macro_use]` extern crate macro_use_warned_against2; diff --git a/src/test/ui/rust-2018/macro-use-warned-against.stderr b/src/test/ui/rust-2018/macro-use-warned-against.stderr index 611b9d5dac9..ef00b865815 100644 --- a/src/test/ui/rust-2018/macro-use-warned-against.stderr +++ b/src/test/ui/rust-2018/macro-use-warned-against.stderr @@ -1,4 +1,4 @@ -warning: deprecated `#[macro_use]` directive used to import macros should be replaced at use sites with a `use` statement to import the macro instead +warning: deprecated `#[macro_use]` attribute used to import macros should be replaced at use sites with a `use` item to import the macro instead --> $DIR/macro-use-warned-against.rs:7:1 | LL | #[macro_use] From 9f3679fe4485aa4be4a0de9abc8aca938c60db36 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 7 Mar 2020 16:31:30 +0000 Subject: [PATCH 0857/1250] Apply review feedback --- src/libpanic_unwind/seh.rs | 2 +- src/librustc_codegen_llvm/intrinsic.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index c1656023b60..c294fe26327 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -237,7 +237,7 @@ static mut TYPE_DESCRIPTOR: _TypeDescriptor = _TypeDescriptor { macro_rules! define_cleanup { ($abi:tt) => { unsafe extern $abi fn exception_cleanup(e: *mut Exception) { - if let Some(b) = e.read().data { + if let Exception { data: Some(b) } = e.read() { drop(b); super::__rust_drop_panic(); } diff --git a/src/librustc_codegen_llvm/intrinsic.rs b/src/librustc_codegen_llvm/intrinsic.rs index d34540638f1..5ce18a9007a 100644 --- a/src/librustc_codegen_llvm/intrinsic.rs +++ b/src/librustc_codegen_llvm/intrinsic.rs @@ -1024,7 +1024,7 @@ fn codegen_gnu_try( // Codegens the shims described above: // // bx: - // invoke %func(%data) normal %normal unwind %catch + // invoke %try_func(%data) normal %normal unwind %catch // // normal: // ret 0 From 2e88bec61916cdb5d24ee9c79af3f70f2d52cb5c Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Sat, 7 Mar 2020 14:17:03 -0600 Subject: [PATCH 0858/1250] test(bindings_after_at): add dynamic drop tests for bindings_after_at --- src/test/ui/drop/dynamic-drop.rs | 48 ++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/test/ui/drop/dynamic-drop.rs b/src/test/ui/drop/dynamic-drop.rs index 451686d9ae2..d31736f142c 100644 --- a/src/test/ui/drop/dynamic-drop.rs +++ b/src/test/ui/drop/dynamic-drop.rs @@ -3,6 +3,7 @@ #![feature(generators, generator_trait, untagged_unions)] #![feature(move_ref_pattern)] +#![feature(bindings_after_at)] #![allow(unused_assignments)] #![allow(unused_variables)] @@ -291,6 +292,44 @@ fn subslice_mixed_min_lengths(a: &Allocator, c: i32) { } } +fn bindings_after_at_dynamic_init_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_) = foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_init_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + let _x; + + if let bar @ Some(_baz) = &foo { + _x = bar; + } +} + +fn bindings_after_at_dynamic_drop_move(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_) = foo { + bar + } else { + None + }; +} + +fn bindings_after_at_dynamic_drop_ref(a: &Allocator, c: bool) { + let foo = if c { Some(a.alloc()) } else { None }; + + if let bar @ Some(_baz) = &foo { + bar + } else { + &None + }; +} + fn move_ref_pattern(a: &Allocator) { let mut tup = (a.alloc(), a.alloc(), a.alloc(), a.alloc()); let (ref _a, ref mut _b, _c, mut _d) = tup; @@ -471,5 +510,14 @@ fn main() { run_test(|a| panic_after_init_temp(a)); run_test(|a| panic_after_init_by_loop(a)); + run_test(|a| bindings_after_at_dynamic_init_move(a, true)); + run_test(|a| bindings_after_at_dynamic_init_move(a, false)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_init_ref(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_move(a, false)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, true)); + run_test(|a| bindings_after_at_dynamic_drop_ref(a, false)); + run_test_nopanic(|a| union1(a)); } From 425e7e5596c0ab6555fa75292d38863280d4a3d7 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 7 Mar 2020 21:29:09 +0100 Subject: [PATCH 0859/1250] Don't insert panic when generator can not return --- src/librustc_mir/transform/generator.rs | 31 +++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d060a0eab3d..cc8d2807b47 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -991,12 +991,30 @@ fn insert_panic_block<'tcx>( assert_block } +fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { + // Returning from a function with an uninhabited return type is undefined behavior. + if body.return_ty().conservative_is_privately_uninhabited(tcx) { + return false; + } + + // If there's no return terminator the function also won't return. + for block in body.basic_blocks() { + if let TerminatorKind::Return = block.terminator().kind { + return true; + } + } + + // Otherwise we assume that the function may return. + false +} + fn create_generator_resume_function<'tcx>( tcx: TyCtxt<'tcx>, transform: TransformVisitor<'tcx>, def_id: DefId, source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>, + can_return: bool, ) { // Poison the generator when it unwinds for block in body.basic_blocks_mut() { @@ -1015,7 +1033,14 @@ fn create_generator_resume_function<'tcx>( // Panic when resumed on the returned or poisoned state let generator_kind = body.generator_kind.unwrap(); - cases.insert(1, (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind)))); + + if can_return { + cases.insert( + 1, + (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))), + ); + } + cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind)))); insert_switch(body, cases, &transform, TerminatorKind::Unreachable); @@ -1200,6 +1225,8 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let (remap, layout, storage_liveness) = compute_layout(tcx, source, &upvars, interior, movable, body); + let can_return = can_return(tcx, body); + // Run the transformation which converts Places from Local to generator struct // accesses for locals in `remap`. // It also rewrites `return x` and `yield y` as writing a new generator state and returning @@ -1243,6 +1270,6 @@ impl<'tcx> MirPass<'tcx> for StateTransform { body.generator_drop = Some(box drop_shim); // Create the Generator::resume function - create_generator_resume_function(tcx, transform, def_id, source, body); + create_generator_resume_function(tcx, transform, def_id, source, body, can_return); } } From 9fa79813f9a9b63b298bdb5469f085072481830b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 21:56:42 +0100 Subject: [PATCH 0860/1250] rustdoc: don't call into_iter() on iterator. (clippy::identity_conversion) --- src/librustdoc/html/markdown.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 42529a6682e..2479363f945 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -870,7 +870,7 @@ pub fn plain_summary_line(md: &str) -> String { } let mut s = String::with_capacity(md.len() * 3 / 2); let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true }; - p.into_iter().filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); + p.filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); s } From 6bfff8a30356e3dd7eaa1c6b9d08e1e7d978d5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 22:01:12 +0100 Subject: [PATCH 0861/1250] rustdoc: Use .any(p) instead of find(p).is_some(). (clippy::search_is_some) --- src/librustdoc/html/render.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 07fe439ace2..c851bc3cdd8 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3401,10 +3401,8 @@ fn render_assoc_items( let deref_impl = traits.iter().find(|t| t.inner_impl().trait_.def_id() == c.deref_trait_did); if let Some(impl_) = deref_impl { - let has_deref_mut = traits - .iter() - .find(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did) - .is_some(); + let has_deref_mut = + traits.iter().any(|t| t.inner_impl().trait_.def_id() == c.deref_mut_trait_did); render_deref_methods(w, cx, impl_, containing_item, has_deref_mut); } @@ -3816,7 +3814,7 @@ fn render_impl( ) { for trait_item in &t.items { let n = trait_item.name.clone(); - if i.items.iter().find(|m| m.name == n).is_some() { + if i.items.iter().any(|m| m.name == n) { continue; } let did = i.trait_.as_ref().unwrap().def_id().unwrap(); From 7aad89a9001cc5e1a10aa1730483749a1ed04f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Thu, 5 Mar 2020 21:50:44 +0100 Subject: [PATCH 0862/1250] Use ?-operator in more places (clippy::question_mark, had some false negatives fixed recently) --- src/libcore/str/pattern.rs | 13 +++++-------- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/util.rs | 7 +------ src/librustc_driver/lib.rs | 7 +------ src/librustc_infer/traits/specialize/mod.rs | 7 +------ src/librustc_resolve/lib.rs | 6 +----- src/librustc_span/lib.rs | 6 +----- src/librustdoc/clean/inline.rs | 6 +----- src/librustdoc/html/markdown.rs | 6 +----- 9 files changed, 13 insertions(+), 47 deletions(-) diff --git a/src/libcore/str/pattern.rs b/src/libcore/str/pattern.rs index 6c826e5dcde..ffa418cba6c 100644 --- a/src/libcore/str/pattern.rs +++ b/src/libcore/str/pattern.rs @@ -365,11 +365,7 @@ unsafe impl<'a> ReverseSearcher<'a> for CharSearcher<'a> { let haystack = self.haystack.as_bytes(); loop { // get the haystack up to but not including the last character searched - let bytes = if let Some(slice) = haystack.get(self.finger..self.finger_back) { - slice - } else { - return None; - }; + let bytes = haystack.get(self.finger..self.finger_back)?; // the last byte of the utf8 encoded needle // SAFETY: we have an invariant that `utf8_size < 5` let last_byte = unsafe { *self.utf8_encoded.get_unchecked(self.utf8_size - 1) }; @@ -575,11 +571,12 @@ macro_rules! pattern_methods { #[inline] fn is_suffix_of(self, haystack: &'a str) -> bool - where $t: ReverseSearcher<'a> + where + $t: ReverseSearcher<'a>, { ($pmap)(self).is_suffix_of(haystack) } - } + }; } macro_rules! searcher_methods { @@ -614,7 +611,7 @@ macro_rules! searcher_methods { fn next_reject_back(&mut self) -> Option<(usize, usize)> { self.0.next_reject_back() } - } + }; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index bd26e02efb7..f69b3325ba5 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -298,7 +298,7 @@ impl<'hir> Map<'hir> { } pub fn def_kind(&self, hir_id: HirId) -> Option { - let node = if let Some(node) = self.find(hir_id) { node } else { return None }; + let node = self.find(hir_id)?; Some(match node { Node::Item(item) => match item.kind { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index fcebedb2601..69daa2da1fd 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -346,12 +346,7 @@ impl<'tcx> TyCtxt<'tcx> { adt_did: DefId, validate: &mut dyn FnMut(Self, DefId) -> Result<(), ErrorReported>, ) -> Option { - let drop_trait = if let Some(def_id) = self.lang_items().drop_trait() { - def_id - } else { - return None; - }; - + let drop_trait = self.lang_items().drop_trait()?; self.ensure().coherent_trait(drop_trait); let mut dtor_did = None; diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 789507fb48b..f7d2fe6e3f8 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1120,12 +1120,7 @@ fn extra_compiler_flags() -> Option<(Vec, bool)> { return None; } - let matches = if let Some(matches) = handle_options(&args) { - matches - } else { - return None; - }; - + let matches = handle_options(&args)?; let mut result = Vec::new(); let mut excluded_cargo_defaults = false; for flag in ICE_REPORT_COMPILER_FLAGS { diff --git a/src/librustc_infer/traits/specialize/mod.rs b/src/librustc_infer/traits/specialize/mod.rs index ee1c737c208..de7fe3d9a2e 100644 --- a/src/librustc_infer/traits/specialize/mod.rs +++ b/src/librustc_infer/traits/specialize/mod.rs @@ -413,12 +413,7 @@ pub(super) fn specialization_graph_provider( fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option { use std::fmt::Write; - let trait_ref = if let Some(tr) = tcx.impl_trait_ref(impl_def_id) { - tr - } else { - return None; - }; - + let trait_ref = tcx.impl_trait_ref(impl_def_id)?; let mut w = "impl".to_owned(); let substs = InternalSubsts::identity_for_item(tcx, impl_def_id); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 44eba0d533d..4009f4047ea 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2778,12 +2778,8 @@ impl<'a> Resolver<'a> { } else { let crate_id = if !speculative { self.crate_loader.process_path_extern(ident.name, ident.span) - } else if let Some(crate_id) = - self.crate_loader.maybe_process_path_extern(ident.name, ident.span) - { - crate_id } else { - return None; + self.crate_loader.maybe_process_path_extern(ident.name, ident.span)? }; let crate_root = self.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }); Some( diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 502ea64aab9..66fb4cd251a 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -1167,11 +1167,7 @@ impl SourceFile { } let begin = { - let line = if let Some(line) = self.lines.get(line_number) { - line - } else { - return None; - }; + let line = self.lines.get(line_number)?; let begin: BytePos = *line - self.start_pos; begin.to_usize() }; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 618dfa0d33a..ae597acf1dc 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -42,11 +42,7 @@ pub fn try_inline( attrs: Option>, visited: &mut FxHashSet, ) -> Option> { - let did = if let Some(did) = res.opt_def_id() { - did - } else { - return None; - }; + let did = res.opt_def_id()?; if did.is_local() { return None; } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 2479363f945..e13bf270440 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -844,11 +844,7 @@ pub fn plain_summary_line(md: &str) -> String { type Item = String; fn next(&mut self) -> Option { - let next_event = self.inner.next(); - if next_event.is_none() { - return None; - } - let next_event = next_event.unwrap(); + let next_event = self.inner.next()?; let (ret, is_in) = match next_event { Event::Start(Tag::Paragraph) => (None, 1), Event::Start(Tag::Heading(_)) => (None, 1), From 45108b195f5a98304e34503bd0655f3871179816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 23:31:14 +0100 Subject: [PATCH 0863/1250] rustdoc: simplify boolean condition (clippy::nonminimal_bool) --- src/librustdoc/clean/inline.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index ae597acf1dc..341313a6e5f 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -577,7 +577,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean: name: ref _name, }, ref bounds, - } => !(*s == "Self" && did == trait_did) && !bounds.is_empty(), + } => !(bounds.is_empty() || *s == "Self" && did == trait_did), _ => true, }); g From 1351db31fb646085e6c6f4bc5917d9392eb2a720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 23:50:23 +0100 Subject: [PATCH 0864/1250] iterate over a maps values directly. (clippy::for_kv_map) --- src/librustdoc/html/render.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c851bc3cdd8..6fcf22743b1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1542,7 +1542,7 @@ impl Context { } if self.shared.sort_modules_alphabetically { - for (_, items) in &mut map { + for items in map.values_mut() { items.sort(); } } From 254ceae30aa9504c59046b603d63bf43697f79b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 23:55:20 +0100 Subject: [PATCH 0865/1250] call .as_deref() instead of .as_ref().map(Deref::deref) (clippy::option_as_ref_deref) --- src/librustc_resolve/late/diagnostics.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index fd62c802934..4d451691f44 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -1107,11 +1107,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> { } }; - match ( - lifetime_names.len(), - lifetime_names.iter().next(), - snippet.as_ref().map(|s| s.as_str()), - ) { + match (lifetime_names.len(), lifetime_names.iter().next(), snippet.as_deref()) { (1, Some(name), Some("&")) => { suggest_existing(err, format!("&{} ", name)); } From 0d7faaf6bd3bae11ac8098f2c0d931994b791875 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 6 Mar 2020 23:59:22 +0100 Subject: [PATCH 0866/1250] rustdoc: remove redundant static lifetimes (clippy::redundant_static_lifetimes) --- src/librustdoc/html/static_files.rs | 56 ++++++++++++++--------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/src/librustdoc/html/static_files.rs b/src/librustdoc/html/static_files.rs index 9fc1d76185f..6790f3bd5d0 100644 --- a/src/librustdoc/html/static_files.rs +++ b/src/librustdoc/html/static_files.rs @@ -8,106 +8,106 @@ //! directly written to a `Write` handle. /// The file contents of the main `rustdoc.css` file, responsible for the core layout of the page. -pub static RUSTDOC_CSS: &'static str = include_str!("static/rustdoc.css"); +pub static RUSTDOC_CSS: &str = include_str!("static/rustdoc.css"); /// The file contents of `settings.css`, responsible for the items on the settings page. -pub static SETTINGS_CSS: &'static str = include_str!("static/settings.css"); +pub static SETTINGS_CSS: &str = include_str!("static/settings.css"); /// The file contents of the `noscript.css` file, used in case JS isn't supported or is disabled. -pub static NOSCRIPT_CSS: &'static str = include_str!("static/noscript.css"); +pub static NOSCRIPT_CSS: &str = include_str!("static/noscript.css"); /// The file contents of `normalize.css`, included to even out standard elements between browser /// implementations. -pub static NORMALIZE_CSS: &'static str = include_str!("static/normalize.css"); +pub static NORMALIZE_CSS: &str = include_str!("static/normalize.css"); /// The file contents of `main.js`, which contains the core JavaScript used on documentation pages, /// including search behavior and docblock folding, among others. -pub static MAIN_JS: &'static str = include_str!("static/main.js"); +pub static MAIN_JS: &str = include_str!("static/main.js"); /// The file contents of `settings.js`, which contains the JavaScript used to handle the settings /// page. -pub static SETTINGS_JS: &'static str = include_str!("static/settings.js"); +pub static SETTINGS_JS: &str = include_str!("static/settings.js"); /// The file contents of `storage.js`, which contains functionality related to browser Local /// Storage, used to store documentation settings. -pub static STORAGE_JS: &'static str = include_str!("static/storage.js"); +pub static STORAGE_JS: &str = include_str!("static/storage.js"); /// The file contents of `brush.svg`, the icon used for the theme-switch button. -pub static BRUSH_SVG: &'static [u8] = include_bytes!("static/brush.svg"); +pub static BRUSH_SVG: &[u8] = include_bytes!("static/brush.svg"); /// The file contents of `wheel.svg`, the icon used for the settings button. -pub static WHEEL_SVG: &'static [u8] = include_bytes!("static/wheel.svg"); +pub static WHEEL_SVG: &[u8] = include_bytes!("static/wheel.svg"); /// The file contents of `down-arrow.svg`, the icon used for the crate choice combobox. -pub static DOWN_ARROW_SVG: &'static [u8] = include_bytes!("static/down-arrow.svg"); +pub static DOWN_ARROW_SVG: &[u8] = include_bytes!("static/down-arrow.svg"); /// The contents of `COPYRIGHT.txt`, the license listing for files distributed with documentation /// output. -pub static COPYRIGHT: &'static [u8] = include_bytes!("static/COPYRIGHT.txt"); +pub static COPYRIGHT: &[u8] = include_bytes!("static/COPYRIGHT.txt"); /// The contents of `LICENSE-APACHE.txt`, the text of the Apache License, version 2.0. -pub static LICENSE_APACHE: &'static [u8] = include_bytes!("static/LICENSE-APACHE.txt"); +pub static LICENSE_APACHE: &[u8] = include_bytes!("static/LICENSE-APACHE.txt"); /// The contents of `LICENSE-MIT.txt`, the text of the MIT License. -pub static LICENSE_MIT: &'static [u8] = include_bytes!("static/LICENSE-MIT.txt"); +pub static LICENSE_MIT: &[u8] = include_bytes!("static/LICENSE-MIT.txt"); /// The contents of `rust-logo.png`, the default icon of the documentation. -pub static RUST_LOGO: &'static [u8] = include_bytes!("static/rust-logo.png"); +pub static RUST_LOGO: &[u8] = include_bytes!("static/rust-logo.png"); /// The contents of `favicon.ico`, the default favicon of the documentation. -pub static RUST_FAVICON: &'static [u8] = include_bytes!("static/favicon.ico"); +pub static RUST_FAVICON: &[u8] = include_bytes!("static/favicon.ico"); /// The built-in themes given to every documentation site. pub mod themes { /// The "light" theme, selected by default when no setting is available. Used as the basis for /// the `--check-theme` functionality. - pub static LIGHT: &'static str = include_str!("static/themes/light.css"); + pub static LIGHT: &str = include_str!("static/themes/light.css"); /// The "dark" theme. - pub static DARK: &'static str = include_str!("static/themes/dark.css"); + pub static DARK: &str = include_str!("static/themes/dark.css"); } /// Files related to the Fira Sans font. pub mod fira_sans { /// The file `FiraSans-Regular.woff`, the Regular variant of the Fira Sans font. - pub static REGULAR: &'static [u8] = include_bytes!("static/FiraSans-Regular.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/FiraSans-Regular.woff"); /// The file `FiraSans-Medium.woff`, the Medium variant of the Fira Sans font. - pub static MEDIUM: &'static [u8] = include_bytes!("static/FiraSans-Medium.woff"); + pub static MEDIUM: &[u8] = include_bytes!("static/FiraSans-Medium.woff"); /// The file `FiraSans-LICENSE.txt`, the license text for the Fira Sans font. - pub static LICENSE: &'static [u8] = include_bytes!("static/FiraSans-LICENSE.txt"); + pub static LICENSE: &[u8] = include_bytes!("static/FiraSans-LICENSE.txt"); } /// Files related to the Source Serif Pro font. pub mod source_serif_pro { /// The file `SourceSerifPro-Regular.ttf.woff`, the Regular variant of the Source Serif Pro /// font. - pub static REGULAR: &'static [u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/SourceSerifPro-Regular.ttf.woff"); /// The file `SourceSerifPro-Bold.ttf.woff`, the Bold variant of the Source Serif Pro font. - pub static BOLD: &'static [u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff"); + pub static BOLD: &[u8] = include_bytes!("static/SourceSerifPro-Bold.ttf.woff"); /// The file `SourceSerifPro-It.ttf.woff`, the Italic variant of the Source Serif Pro font. - pub static ITALIC: &'static [u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff"); + pub static ITALIC: &[u8] = include_bytes!("static/SourceSerifPro-It.ttf.woff"); /// The file `SourceSerifPro-LICENSE.txt`, the license text for the Source Serif Pro font. - pub static LICENSE: &'static [u8] = include_bytes!("static/SourceSerifPro-LICENSE.md"); + pub static LICENSE: &[u8] = include_bytes!("static/SourceSerifPro-LICENSE.md"); } /// Files related to the Source Code Pro font. pub mod source_code_pro { /// The file `SourceCodePro-Regular.woff`, the Regular variant of the Source Code Pro font. - pub static REGULAR: &'static [u8] = include_bytes!("static/SourceCodePro-Regular.woff"); + pub static REGULAR: &[u8] = include_bytes!("static/SourceCodePro-Regular.woff"); /// The file `SourceCodePro-Semibold.woff`, the Semibold variant of the Source Code Pro font. - pub static SEMIBOLD: &'static [u8] = include_bytes!("static/SourceCodePro-Semibold.woff"); + pub static SEMIBOLD: &[u8] = include_bytes!("static/SourceCodePro-Semibold.woff"); /// The file `SourceCodePro-LICENSE.txt`, the license text of the Source Code Pro font. - pub static LICENSE: &'static [u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); + pub static LICENSE: &[u8] = include_bytes!("static/SourceCodePro-LICENSE.txt"); } /// Files related to the sidebar in rustdoc sources. pub mod sidebar { /// File script to handle sidebar. - pub static SOURCE_SCRIPT: &'static str = include_str!("static/source-script.js"); + pub static SOURCE_SCRIPT: &str = include_str!("static/source-script.js"); } From cca3d5216099de7333501b65a4d5cffe03270d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 7 Mar 2020 00:15:46 +0100 Subject: [PATCH 0867/1250] libtest: declare variables as floats instead of casting them (clippy::unnecessary_cast) --- src/libtest/stats.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index aab8d012fdf..077005371c0 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -204,7 +204,7 @@ impl Stats for [f64] { } fn median(&self) -> f64 { - self.percentile(50 as f64) + self.percentile(50_f64) } fn var(&self) -> f64 { @@ -230,7 +230,7 @@ impl Stats for [f64] { } fn std_dev_pct(&self) -> f64 { - let hundred = 100 as f64; + let hundred = 100_f64; (self.std_dev() / self.mean()) * hundred } @@ -244,7 +244,7 @@ impl Stats for [f64] { } fn median_abs_dev_pct(&self) -> f64 { - let hundred = 100 as f64; + let hundred = 100_f64; (self.median_abs_dev() / self.median()) * hundred } @@ -257,11 +257,11 @@ impl Stats for [f64] { fn quartiles(&self) -> (f64, f64, f64) { let mut tmp = self.to_vec(); local_sort(&mut tmp); - let first = 25f64; + let first = 25_f64; let a = percentile_of_sorted(&tmp, first); - let second = 50f64; + let second = 50_f64; let b = percentile_of_sorted(&tmp, second); - let third = 75f64; + let third = 75_f64; let c = percentile_of_sorted(&tmp, third); (a, b, c) } @@ -281,7 +281,7 @@ fn percentile_of_sorted(sorted_samples: &[f64], pct: f64) -> f64 { } let zero: f64 = 0.0; assert!(zero <= pct); - let hundred = 100f64; + let hundred = 100_f64; assert!(pct <= hundred); if pct == hundred { return sorted_samples[sorted_samples.len() - 1]; @@ -307,7 +307,7 @@ pub fn winsorize(samples: &mut [f64], pct: f64) { let mut tmp = samples.to_vec(); local_sort(&mut tmp); let lo = percentile_of_sorted(&tmp, pct); - let hundred = 100 as f64; + let hundred = 100_f64; let hi = percentile_of_sorted(&tmp, hundred - pct); for samp in samples { if *samp > hi { From 77af19eb71632a3b3561ec2ae4f544925b517d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 7 Mar 2020 00:19:25 +0100 Subject: [PATCH 0868/1250] remove unneeded mutable references (cippy::unnecessary_mut_passed) --- src/librustc_infer/traits/auto_trait.rs | 4 ++-- src/librustc_mir/transform/generator.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_infer/traits/auto_trait.rs b/src/librustc_infer/traits/auto_trait.rs index 3166fe06576..f3df0b036de 100644 --- a/src/librustc_infer/traits/auto_trait.rs +++ b/src/librustc_infer/traits/auto_trait.rs @@ -113,7 +113,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { return AutoTraitResult::ExplicitImpl; } - return tcx.infer_ctxt().enter(|mut infcx| { + return tcx.infer_ctxt().enter(|infcx| { let mut fresh_preds = FxHashSet::default(); // Due to the way projections are handled by SelectionContext, we need to run @@ -164,7 +164,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { let (full_env, full_user_env) = self .evaluate_predicates( - &mut infcx, + &infcx, trait_did, ty, new_env, diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d060a0eab3d..27a1373cdcc 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -944,7 +944,7 @@ fn create_generator_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut body); - dump_mir(tcx, None, "generator_drop", &0, source, &mut body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(())); body } From f326f0f70fe48d3d8a47cfff373bff1402078850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 7 Mar 2020 00:37:51 +0100 Subject: [PATCH 0869/1250] libtest: remove redundant argument to writeln!() (clippy::writeln_empty_string) --- src/librustc_mir/util/liveness.rs | 4 ++-- src/librustc_mir/util/pretty.rs | 10 +++++----- src/libtest/console.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index b12ad1e4c15..f6c6f555495 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -293,7 +293,7 @@ fn dump_matched_mir_node<'tcx>( writeln!(file, "// MIR local liveness analysis for `{}`", node_path)?; writeln!(file, "// source = {:?}", source)?; writeln!(file, "// pass_name = {}", pass_name)?; - writeln!(file, "")?; + writeln!(file)?; write_mir_fn(tcx, source, body, &mut file, result)?; Ok(()) }); @@ -316,7 +316,7 @@ pub fn write_mir_fn<'tcx>( write_basic_block(tcx, block, body, &mut |_, _| Ok(()), w)?; print(w, " ", &result.outs)?; if block.index() + 1 != body.basic_blocks().len() { - writeln!(w, "")?; + writeln!(w)?; } } diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs index 1fd5f3c4395..c7cfa8917e6 100644 --- a/src/librustc_mir/util/pretty.rs +++ b/src/librustc_mir/util/pretty.rs @@ -134,7 +134,7 @@ fn dump_matched_mir_node<'tcx, F>( if let Some(ref layout) = body.generator_layout { writeln!(file, "// generator_layout = {:?}", layout)?; } - writeln!(file, "")?; + writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; write_user_type_annotations(body, &mut file)?; write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?; @@ -242,13 +242,13 @@ pub fn write_mir_pretty<'tcx>( first = false; } else { // Put empty lines between all items - writeln!(w, "")?; + writeln!(w)?; } write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?; for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() { - writeln!(w, "")?; + writeln!(w)?; let src = MirSource { instance: ty::InstanceDef::Item(def_id), promoted: Some(i) }; write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?; } @@ -271,7 +271,7 @@ where extra_data(PassWhere::BeforeBlock(block), w)?; write_basic_block(tcx, block, body, extra_data, w)?; if block.index() + 1 != body.basic_blocks().len() { - writeln!(w, "")?; + writeln!(w)?; } } @@ -529,7 +529,7 @@ pub fn write_mir_intro<'tcx>( write_scope_tree(tcx, body, &scope_tree, w, OUTERMOST_SOURCE_SCOPE, 1)?; // Add an empty line before the first block is printed. - writeln!(w, "")?; + writeln!(w)?; Ok(()) } diff --git a/src/libtest/console.rs b/src/libtest/console.rs index 149c9202e6e..ff741e3bd53 100644 --- a/src/libtest/console.rs +++ b/src/libtest/console.rs @@ -169,7 +169,7 @@ pub fn list_tests_console(opts: &TestOpts, tests: Vec) -> io::Res if !quiet { if ntest != 0 || nbench != 0 { - writeln!(output, "")?; + writeln!(output)?; } writeln!(output, "{}, {}", plural(ntest, "test"), plural(nbench, "benchmark"))?; From 3f87f8cfee8e8a79ebc1f94ba5114ce51baf447d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 7 Mar 2020 00:48:31 +0100 Subject: [PATCH 0870/1250] Use writeln!(fmt, "word") instead of write!(fmt, "word\n") (clippy::write_with_newline) --- src/libstd/sys_common/backtrace.rs | 2 +- src/libtest/formatters/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/backtrace.rs b/src/libstd/sys_common/backtrace.rs index 289ee07babf..2c7ba8f8ea1 100644 --- a/src/libstd/sys_common/backtrace.rs +++ b/src/libstd/sys_common/backtrace.rs @@ -70,7 +70,7 @@ unsafe fn _print_fmt(fmt: &mut fmt::Formatter<'_>, print_fmt: PrintFmt) -> fmt:: let mut print_path = move |fmt: &mut fmt::Formatter<'_>, bows: BytesOrWideString<'_>| { output_filename(fmt, bows, print_fmt, cwd.as_ref()) }; - write!(fmt, "stack backtrace:\n")?; + writeln!(fmt, "stack backtrace:")?; let mut bt_fmt = BacktraceFmt::new(fmt, print_fmt, &mut print_path); bt_fmt.add_context()?; let mut idx = 0; diff --git a/src/libtest/formatters/mod.rs b/src/libtest/formatters/mod.rs index a64c0fc263d..1fb840520a6 100644 --- a/src/libtest/formatters/mod.rs +++ b/src/libtest/formatters/mod.rs @@ -36,5 +36,5 @@ pub(crate) fn write_stderr_delimiter(test_output: &mut Vec, test_name: &Test Some(_) => test_output.push(b'\n'), None => (), } - write!(test_output, "---- {} stderr ----\n", test_name).unwrap(); + writeln!(test_output, "---- {} stderr ----", test_name).unwrap(); } From 83511383706e069bc7c6b3a7d957846ad51e818f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 7 Mar 2020 10:57:02 +0100 Subject: [PATCH 0871/1250] reduce references on match patterns (clippy::match_ref_pats) --- src/libstd/sys_common/process.rs | 2 +- src/libstd/sys_common/wtf8.rs | 8 ++++---- src/libtest/types.rs | 8 ++++---- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/libstd/sys_common/process.rs b/src/libstd/sys_common/process.rs index 042641852b3..f3a2962098b 100644 --- a/src/libstd/sys_common/process.rs +++ b/src/libstd/sys_common/process.rs @@ -47,7 +47,7 @@ impl CommandEnv { } } for (key, maybe_val) in self.vars.iter() { - if let &Some(ref val) = maybe_val { + if let Some(ref val) = maybe_val { env::set_var(key, val); } else { env::remove_var(key); diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 1d96cdfe460..7509e1ee35d 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -603,8 +603,8 @@ impl Wtf8 { if len < 3 { return None; } - match &self.bytes[(len - 3)..] { - &[0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes[(len - 3)..] { + [0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), _ => None, } } @@ -615,8 +615,8 @@ impl Wtf8 { if len < 3 { return None; } - match &self.bytes[..3] { - &[0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes[..3] { + [0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), _ => None, } } diff --git a/src/libtest/types.rs b/src/libtest/types.rs index 2619f99592a..5b75d2f367f 100644 --- a/src/libtest/types.rs +++ b/src/libtest/types.rs @@ -59,10 +59,10 @@ impl TestName { } pub fn with_padding(&self, padding: NamePadding) -> TestName { - let name = match self { - &TestName::StaticTestName(name) => Cow::Borrowed(name), - &TestName::DynTestName(ref name) => Cow::Owned(name.clone()), - &TestName::AlignedTestName(ref name, _) => name.clone(), + let name = match *self { + TestName::StaticTestName(name) => Cow::Borrowed(name), + TestName::DynTestName(ref name) => Cow::Owned(name.clone()), + TestName::AlignedTestName(ref name, _) => name.clone(), }; TestName::AlignedTestName(name, padding) From 5ac41a1a8d28493c7aa927ae49c664b9b9dce476 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 7 Mar 2020 21:51:34 +0100 Subject: [PATCH 0872/1250] Don't insert panic when generator can not unwind --- src/librustc_mir/transform/generator.rs | 46 ++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index cc8d2807b47..0502e57533d 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1008,6 +1008,45 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { false } +fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { + // Nothing can unwind when landing pads are off. + if tcx.sess.no_landing_pads() { + return false; + } + + // Unwinds can only start at certain terminators. + for block in body.basic_blocks() { + match block.terminator().kind { + // These never unwind. + TerminatorKind::Goto { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::FalseEdges { .. } + | TerminatorKind::FalseUnwind { .. } => {} + + // Resume will *continue* unwinding, but if there's no other unwinding terminator it + // will never be reached. + TerminatorKind::Resume => {} + + TerminatorKind::Yield { .. } => { + unreachable!("`can_unwind` called before generator transform") + } + + // These may unwind. + TerminatorKind::Drop { .. } + | TerminatorKind::DropAndReplace { .. } + | TerminatorKind::Call { .. } + | TerminatorKind::Assert { .. } => return true, + } + } + + // If we didn't find an unwinding terminator, the function cannot unwind. + false +} + fn create_generator_resume_function<'tcx>( tcx: TyCtxt<'tcx>, transform: TransformVisitor<'tcx>, @@ -1041,7 +1080,12 @@ fn create_generator_resume_function<'tcx>( ); } - cases.insert(2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind)))); + if can_unwind(tcx, body) { + cases.insert( + 2, + (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), + ); + } insert_switch(body, cases, &transform, TerminatorKind::Unreachable); From b1b558f1f0cf5caab5c44c88e7050cba71c6be0d Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 7 Mar 2020 16:58:29 +0100 Subject: [PATCH 0873/1250] refactor: Exhaustive matching in method/probe.rs --- src/librustc_typeck/check/method/probe.rs | 114 ++++++++-------------- 1 file changed, 39 insertions(+), 75 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index a52cabd8894..179ed2f55d5 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -572,7 +572,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } fn assemble_inherent_candidates(&mut self) { - let steps = self.steps.clone(); + let steps = Lrc::clone(&self.steps); for step in steps.iter() { self.assemble_probe(&step.self_ty); } @@ -635,87 +635,51 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { self.assemble_inherent_impl_for_primitive(lang_def_id); } ty::Slice(_) => { - let lang_def_id = lang_items.slice_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_u8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_alloc_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.slice_u8_alloc_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => { - let lang_def_id = lang_items.const_ptr_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => { - let lang_def_id = lang_items.mut_ptr_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I8) => { - let lang_def_id = lang_items.i8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I16) => { - let lang_def_id = lang_items.i16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I32) => { - let lang_def_id = lang_items.i32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I64) => { - let lang_def_id = lang_items.i64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::I128) => { - let lang_def_id = lang_items.i128_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Int(ast::IntTy::Isize) => { - let lang_def_id = lang_items.isize_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U8) => { - let lang_def_id = lang_items.u8_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U16) => { - let lang_def_id = lang_items.u16_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U32) => { - let lang_def_id = lang_items.u32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - } - ty::Uint(ast::UintTy::U64) => { - let lang_def_id = lang_items.u64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + for &lang_def_id in &[ + lang_items.slice_impl(), + lang_items.slice_u8_impl(), + lang_items.slice_alloc_impl(), + lang_items.slice_u8_alloc_impl(), + ] { + self.assemble_inherent_impl_for_primitive(lang_def_id); + } } - ty::Uint(ast::UintTy::U128) => { - let lang_def_id = lang_items.u128_impl(); + ty::RawPtr(ty::TypeAndMut { ty: _, mutbl }) => { + let lang_def_id = match mutbl { + hir::Mutability::Not => lang_items.const_ptr_impl(), + hir::Mutability::Mut => lang_items.mut_ptr_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::Uint(ast::UintTy::Usize) => { - let lang_def_id = lang_items.usize_impl(); + ty::Int(i) => { + let lang_def_id = match i { + ast::IntTy::I8 => lang_items.i8_impl(), + ast::IntTy::I16 => lang_items.i16_impl(), + ast::IntTy::I32 => lang_items.i32_impl(), + ast::IntTy::I64 => lang_items.i64_impl(), + ast::IntTy::I128 => lang_items.i128_impl(), + ast::IntTy::Isize => lang_items.isize_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::Float(ast::FloatTy::F32) => { - let lang_def_id = lang_items.f32_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.f32_runtime_impl(); + ty::Uint(i) => { + let lang_def_id = match i { + ast::UintTy::U8 => lang_items.u8_impl(), + ast::UintTy::U16 => lang_items.u16_impl(), + ast::UintTy::U32 => lang_items.u32_impl(), + ast::UintTy::U64 => lang_items.u64_impl(), + ast::UintTy::U128 => lang_items.u128_impl(), + ast::UintTy::Usize => lang_items.usize_impl(), + }; self.assemble_inherent_impl_for_primitive(lang_def_id); } - ty::Float(ast::FloatTy::F64) => { - let lang_def_id = lang_items.f64_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); - - let lang_def_id = lang_items.f64_runtime_impl(); - self.assemble_inherent_impl_for_primitive(lang_def_id); + ty::Float(f) => { + let (lang_def_id1, lang_def_id2) = match f { + ast::FloatTy::F32 => (lang_items.f32_impl(), lang_items.f32_runtime_impl()), + ast::FloatTy::F64 => (lang_items.f64_impl(), lang_items.f64_runtime_impl()), + }; + self.assemble_inherent_impl_for_primitive(lang_def_id1); + self.assemble_inherent_impl_for_primitive(lang_def_id2); } _ => {} } From 6095fa146ce994c1650376257ab488156e6e745a Mon Sep 17 00:00:00 2001 From: Markus Westerlind Date: Sat, 7 Mar 2020 20:17:00 +0100 Subject: [PATCH 0874/1250] refactor: Move a borrow_mut and unwrap out of a loop --- src/librustc_typeck/check/method/mod.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 9b8d88e94b6..542a1ac4536 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -459,12 +459,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ProbeScope::TraitsInScope, )?; debug!("resolve_ufcs: pick={:?}", pick); - for import_id in pick.import_ids { - let import_def_id = tcx.hir().local_def_id(import_id); - debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); - Lrc::get_mut(&mut self.tables.borrow_mut().used_trait_imports) - .unwrap() - .insert(import_def_id); + { + let mut tables = self.tables.borrow_mut(); + let used_trait_imports = Lrc::get_mut(&mut tables.used_trait_imports).unwrap(); + for import_id in pick.import_ids { + let import_def_id = tcx.hir().local_def_id(import_id); + debug!("resolve_ufcs: used_trait_import: {:?}", import_def_id); + used_trait_imports.insert(import_def_id); + } } let def_kind = pick.item.def_kind(); From 46aeef6e655a85087f82bb0d1f94a97e83009218 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Mar 2020 00:55:29 +0100 Subject: [PATCH 0875/1250] Poison generators when any terminator unwinds This didn't cause issues before since generator types were always considered to "need drop", leading to unwind paths (including a `Resume` block) always getting generated. --- src/librustc_mir/transform/generator.rs | 36 +++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 0502e57533d..ffbf4ae9393 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1055,11 +1055,37 @@ fn create_generator_resume_function<'tcx>( body: &mut BodyAndCache<'tcx>, can_return: bool, ) { + let can_unwind = can_unwind(tcx, body); + // Poison the generator when it unwinds - for block in body.basic_blocks_mut() { - let source_info = block.terminator().source_info; - if let &TerminatorKind::Resume = &block.terminator().kind { - block.statements.push(transform.set_discr(VariantIdx::new(POISONED), source_info)); + if can_unwind { + let poison_block = BasicBlock::new(body.basic_blocks().len()); + let source_info = source_info(body); + body.basic_blocks_mut().push(BasicBlockData { + statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)], + terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }), + is_cleanup: true, + }); + + for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() { + let source_info = block.terminator().source_info; + + if let TerminatorKind::Resume = block.terminator().kind { + // An existing `Resume` terminator is redirected to jump to our dedicated + // "poisoning block" above. + if idx != poison_block { + *block.terminator_mut() = Terminator { + source_info, + kind: TerminatorKind::Goto { target: poison_block }, + }; + } + } else if !block.is_cleanup { + // Any terminators that *can* unwind but don't have an unwind target set are also + // pointed at our poisoning block (unless they're part of the cleanup path). + if let Some(unwind @ None) = block.terminator_mut().unwind_mut() { + *unwind = Some(poison_block); + } + } } } @@ -1080,7 +1106,7 @@ fn create_generator_resume_function<'tcx>( ); } - if can_unwind(tcx, body) { + if can_unwind { cases.insert( 2, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), From 8d9f633f4d78777487010ae119454dc9674e42ee Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Mar 2020 01:23:00 +0100 Subject: [PATCH 0876/1250] Change index for SwitchInt case The indices do not matter here, and this fixes an index out of bounds panic when compiling a generator that can unwind but not return. --- src/librustc_mir/transform/generator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index ffbf4ae9393..841d18268b1 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1108,7 +1108,7 @@ fn create_generator_resume_function<'tcx>( if can_unwind { cases.insert( - 2, + 1, (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), ); } From 2cbccced0856260c6acafabecb3030465dff28c2 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Mar 2020 01:47:54 +0100 Subject: [PATCH 0877/1250] Add test for unnecessary panic branches --- src/test/mir-opt/generator-tiny.rs | 34 ++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/test/mir-opt/generator-tiny.rs diff --git a/src/test/mir-opt/generator-tiny.rs b/src/test/mir-opt/generator-tiny.rs new file mode 100644 index 00000000000..09e943bd962 --- /dev/null +++ b/src/test/mir-opt/generator-tiny.rs @@ -0,0 +1,34 @@ +//! Tests that generators that cannot return or unwind don't have unnecessary +//! panic branches. + +// compile-flags: -Zno-landing-pads + +#![feature(generators, generator_trait)] + +struct HasDrop; + +impl Drop for HasDrop { + fn drop(&mut self) {} +} + +fn callee() {} + +fn main() { + let _gen = |_x: u8| { + let _d = HasDrop; + loop { + yield; + callee(); + } + }; +} + +// END RUST SOURCE + +// START rustc.main-{{closure}}.generator_resume.0.mir +// bb0: { +// ... +// switchInt(move _11) -> [0u32: bb1, 3u32: bb5, otherwise: bb6]; +// } +// ... +// END rustc.main-{{closure}}.generator_resume.0.mir From dbed65afaede1a819c5a7319685721339b61733b Mon Sep 17 00:00:00 2001 From: 12101111 Date: Sun, 8 Mar 2020 14:24:02 +0800 Subject: [PATCH 0878/1250] Simplify checking of crt_static_feature() --- src/librustc_session/session.rs | 36 +++++++++------------------------ 1 file changed, 10 insertions(+), 26 deletions(-) diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 619fbdcf7f8..3cb8ba4af11 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -556,33 +556,17 @@ impl Session { let found_negative = requested_features.clone().any(|r| r == "-crt-static"); let found_positive = requested_features.clone().any(|r| r == "+crt-static"); - if self.target.target.options.crt_static_default { - // `proc-macro` always required to be compiled to dylibs. - // We don't use a static crt unless the `+crt-static` feature was passed. - if !self.target.target.options.crt_static_allows_dylibs { - match crate_type { - Some(config::CrateType::ProcMacro) => found_positive, - Some(_) => !found_negative, - None => { - // FIXME: When crate_type is not available, - // we use compiler options to determine the crate_type. - // We can't check `#![crate_type = "proc-macro"]` here. - if self.opts.crate_types.contains(&config::CrateType::ProcMacro) { - found_positive - } else { - !found_negative - } - } - } - } else { - // If the target we're compiling for requests a static crt by default, - // then see if the `-crt-static` feature was passed to disable that. - !found_negative - } - } else { - // If the target we're compiling for don't have a static crt by default then see if the - // `+crt-static` feature was passed. + if found_positive || found_negative { found_positive + } else if crate_type == Some(config::CrateType::ProcMacro) + || self.opts.crate_types.contains(&config::CrateType::ProcMacro) + { + // FIXME: When crate_type is not available, + // we use compiler options to determine the crate_type. + // We can't check `#![crate_type = "proc-macro"]` here. + false + } else { + self.target.target.options.crt_static_default } } From 57f1bb15b3f0d2fdd737804c7b7821fe1b40e256 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 13 Feb 2020 18:41:55 +0100 Subject: [PATCH 0879/1250] clean up E0308 explanation --- src/librustc_error_codes/error_codes/E0308.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0308.md b/src/librustc_error_codes/error_codes/E0308.md index a907ca27297..7d87d54194e 100644 --- a/src/librustc_error_codes/error_codes/E0308.md +++ b/src/librustc_error_codes/error_codes/E0308.md @@ -1,10 +1,6 @@ -This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = "I am not a number!"; @@ -15,3 +11,9 @@ let x: i32 = "I am not a number!"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. From 4db15d89a08580ad0c825a0c67b4b14e103cf1cd Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 7 Mar 2020 18:42:09 +0100 Subject: [PATCH 0880/1250] Cleanup E0391 explanation --- src/librustc_error_codes/error_codes/E0391.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0391.md b/src/librustc_error_codes/error_codes/E0391.md index 5db9ad16d08..dff50ccaa0b 100644 --- a/src/librustc_error_codes/error_codes/E0391.md +++ b/src/librustc_error_codes/error_codes/E0391.md @@ -1,7 +1,6 @@ -This error indicates that some types or traits depend on each other -and therefore cannot be constructed. +A type dependency cycle has been encountered. -The following example contains a circular dependency between two traits: +Erroneous code example: ```compile_fail,E0391 trait FirstTrait : SecondTrait { @@ -12,3 +11,6 @@ trait SecondTrait : FirstTrait { } ``` + +The previous example contains a circular dependency between two traits: +`FirstTrait` depends on `SecondTrait` which itself depends on `FirstTrait`. From 2676afeca49cfaeac99a5a558493fd16a0b08675 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 8 Mar 2020 10:44:23 +0100 Subject: [PATCH 0881/1250] clean up E0392 explanation --- src/librustc_error_codes/error_codes/E0392.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0392.md b/src/librustc_error_codes/error_codes/E0392.md index 1d93e904e37..f373d89456d 100644 --- a/src/librustc_error_codes/error_codes/E0392.md +++ b/src/librustc_error_codes/error_codes/E0392.md @@ -1,5 +1,6 @@ -This error indicates that a type or lifetime parameter has been declared -but not actually used. Here is an example that demonstrates the error: +A type or lifetime parameter has been declared but is not actually used. + +Erroneous code example: ```compile_fail,E0392 enum Foo { From f77afc8f9c63d789519c0b1a733462ca654d894a Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Sat, 7 Mar 2020 12:04:40 +0100 Subject: [PATCH 0882/1250] Allow ZSTs in `AllocRef` --- src/liballoc/alloc.rs | 34 +++++++++++++++++---- src/liballoc/raw_vec.rs | 38 +++++++++++------------- src/liballoc/raw_vec/tests.rs | 2 +- src/libcore/alloc.rs | 56 ++++++++--------------------------- src/libstd/alloc.rs | 47 ++++++++++++++++++++++------- 5 files changed, 96 insertions(+), 81 deletions(-) diff --git a/src/liballoc/alloc.rs b/src/liballoc/alloc.rs index 73e8121868a..9f82b2c6fa6 100644 --- a/src/liballoc/alloc.rs +++ b/src/liballoc/alloc.rs @@ -165,13 +165,19 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 { #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for Global { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) + fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + if layout.size() == 0 { + Ok((layout.dangling(), 0)) + } else { + unsafe { NonNull::new(alloc(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) } + } } #[inline] unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - dealloc(ptr.as_ptr(), layout) + if layout.size() != 0 { + dealloc(ptr.as_ptr(), layout) + } } #[inline] @@ -181,12 +187,28 @@ unsafe impl AllocRef for Global { layout: Layout, new_size: usize, ) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(realloc(ptr.as_ptr(), layout, new_size)).ok_or(AllocErr).map(|p| (p, new_size)) + match (layout.size(), new_size) { + (0, 0) => Ok((layout.dangling(), 0)), + (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())), + (_, 0) => { + self.dealloc(ptr, layout); + Ok((layout.dangling(), 0)) + } + (_, _) => NonNull::new(realloc(ptr.as_ptr(), layout, new_size)) + .ok_or(AllocErr) + .map(|p| (p, new_size)), + } } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) + fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + if layout.size() == 0 { + Ok((layout.dangling(), 0)) + } else { + unsafe { + NonNull::new(alloc_zeroed(layout)).ok_or(AllocErr).map(|p| (p, layout.size())) + } + } } } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 345834d7daa..b31fec7f037 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -73,30 +73,28 @@ impl RawVec { } fn allocate_in(mut capacity: usize, zeroed: bool, mut a: A) -> Self { - unsafe { - let elem_size = mem::size_of::(); + let elem_size = mem::size_of::(); - let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); - alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); + let alloc_size = capacity.checked_mul(elem_size).unwrap_or_else(|| capacity_overflow()); + alloc_guard(alloc_size).unwrap_or_else(|_| capacity_overflow()); - // Handles ZSTs and `capacity == 0` alike. - let ptr = if alloc_size == 0 { - NonNull::::dangling() - } else { - let align = mem::align_of::(); - let layout = Layout::from_size_align(alloc_size, align).unwrap(); - let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) }; - match result { - Ok((ptr, size)) => { - capacity = size / elem_size; - ptr.cast() - } - Err(_) => handle_alloc_error(layout), + // Handles ZSTs and `capacity == 0` alike. + let ptr = if alloc_size == 0 { + NonNull::::dangling() + } else { + let align = mem::align_of::(); + let layout = Layout::from_size_align(alloc_size, align).unwrap(); + let result = if zeroed { a.alloc_zeroed(layout) } else { a.alloc(layout) }; + match result { + Ok((ptr, size)) => { + capacity = size / elem_size; + ptr.cast() } - }; + Err(_) => handle_alloc_error(layout), + } + }; - RawVec { ptr: ptr.into(), cap: capacity, a } - } + RawVec { ptr: ptr.into(), cap: capacity, a } } } diff --git a/src/liballoc/raw_vec/tests.rs b/src/liballoc/raw_vec/tests.rs index 860058debe1..21a8a76d0a7 100644 --- a/src/liballoc/raw_vec/tests.rs +++ b/src/liballoc/raw_vec/tests.rs @@ -20,7 +20,7 @@ fn allocator_param() { fuel: usize, } unsafe impl AllocRef for BoundedAlloc { - unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { let size = layout.size(); if size > self.fuel { return Err(AllocErr); diff --git a/src/libcore/alloc.rs b/src/libcore/alloc.rs index 0a7a8ab266a..d2a513451cc 100644 --- a/src/libcore/alloc.rs +++ b/src/libcore/alloc.rs @@ -606,20 +606,11 @@ pub unsafe trait GlobalAlloc { /// method (`dealloc`) or by being passed to a reallocation method /// (see above) that returns `Ok`. /// -/// A note regarding zero-sized types and zero-sized layouts: many -/// methods in the `AllocRef` trait state that allocation requests -/// must be non-zero size, or else undefined behavior can result. -/// -/// * If an `AllocRef` implementation chooses to return `Ok` in this -/// case (i.e., the pointer denotes a zero-sized inaccessible block) -/// then that returned pointer must be considered "currently -/// allocated". On such an allocator, *all* methods that take -/// currently-allocated pointers as inputs must accept these -/// zero-sized pointers, *without* causing undefined behavior. -/// -/// * In other words, if a zero-sized pointer can flow out of an -/// allocator, then that allocator must likewise accept that pointer -/// flowing back into its deallocation and reallocation methods. +/// Unlike [`GlobalAlloc`], zero-sized allocations are allowed in +/// `AllocRef`. If an underlying allocator does not support this (like +/// jemalloc) or return a null pointer (such as `libc::malloc`), this case +/// must be caught. In this case [`Layout::dangling()`] can be used to +/// create a dangling, but aligned `NonNull`. /// /// Some of the methods require that a layout *fit* a memory block. /// What it means for a layout to "fit" a memory block means (or @@ -649,6 +640,9 @@ pub unsafe trait GlobalAlloc { /// * if an allocator does not support overallocating, it is fine to /// simply return `layout.size()` as the allocated size. /// +/// [`GlobalAlloc`]: self::GlobalAlloc +/// [`Layout::dangling()`]: self::Layout::dangling +/// /// # Safety /// /// The `AllocRef` trait is an `unsafe` trait for a number of reasons, and @@ -669,14 +663,6 @@ pub unsafe trait GlobalAlloc { /// the future. #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe trait AllocRef { - // (Note: some existing allocators have unspecified but well-defined - // behavior in response to a zero size allocation request ; - // e.g., in C, `malloc` of 0 will either return a null pointer or a - // unique pointer, but will not have arbitrary undefined - // behavior. - // However in jemalloc for example, - // `mallocx(0)` is documented as undefined behavior.) - /// On success, returns a pointer meeting the size and alignment /// guarantees of `layout` and the actual size of the allocated block, /// which must be greater than or equal to `layout.size()`. @@ -690,15 +676,6 @@ pub unsafe trait AllocRef { /// behavior, e.g., to ensure initialization to particular sets of /// bit patterns.) /// - /// # Safety - /// - /// This function is unsafe because undefined behavior can result - /// if the caller does not ensure that `layout` has non-zero size. - /// - /// (Extension subtraits might provide more specific bounds on - /// behavior, e.g., guarantee a sentinel address or a null pointer - /// in response to a zero-size allocation request.) - /// /// # Errors /// /// Returning `Err` indicates that either memory is exhausted or @@ -716,7 +693,7 @@ pub unsafe trait AllocRef { /// rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr>; + fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr>; /// Deallocate the memory referenced by `ptr`. /// @@ -738,10 +715,6 @@ pub unsafe trait AllocRef { /// Behaves like `alloc`, but also ensures that the contents /// are set to zero before being returned. /// - /// # Safety - /// - /// This function is unsafe for the same reasons that `alloc` is. - /// /// # Errors /// /// Returning `Err` indicates that either memory is exhausted or @@ -753,17 +726,17 @@ pub unsafe trait AllocRef { /// rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { let size = layout.size(); let result = self.alloc(layout); if let Ok((p, _)) = result { - ptr::write_bytes(p.as_ptr(), 0, size); + unsafe { ptr::write_bytes(p.as_ptr(), 0, size) } } result } // == METHODS FOR MEMORY REUSE == - // realloc. alloc_excess, realloc_excess + // realloc, realloc_zeroed, grow_in_place, grow_in_place_zeroed, shrink_in_place /// Returns a pointer suitable for holding data described by /// a new layout with `layout`’s alignment and a size given @@ -793,8 +766,6 @@ pub unsafe trait AllocRef { /// * `layout` must *fit* the `ptr` (see above). (The `new_size` /// argument need not fit it.) /// - /// * `new_size` must be greater than zero. - /// /// * `new_size`, when rounded up to the nearest multiple of `layout.align()`, /// must not overflow (i.e., the rounded value must be less than `usize::MAX`). /// @@ -1009,8 +980,7 @@ pub unsafe trait AllocRef { /// * `layout` must *fit* the `ptr` (see above); note the /// `new_size` argument need not fit it, /// - /// * `new_size` must not be greater than `layout.size()` - /// (and must be greater than zero), + /// * `new_size` must not be greater than `layout.size()`, /// /// # Errors /// diff --git a/src/libstd/alloc.rs b/src/libstd/alloc.rs index 2da18e06d99..25f3ddcbeba 100644 --- a/src/libstd/alloc.rs +++ b/src/libstd/alloc.rs @@ -133,24 +133,41 @@ pub use alloc_crate::alloc::*; #[derive(Debug, Default, Copy, Clone)] pub struct System; -// The AllocRef impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`. +// The AllocRef impl checks the layout size to be non-zero and forwards to the GlobalAlloc impl, +// which is in `std::sys::*::alloc`. #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocRef for System { #[inline] - unsafe fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(GlobalAlloc::alloc(self, layout)).ok_or(AllocErr).map(|p| (p, layout.size())) + fn alloc(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + if layout.size() == 0 { + Ok((layout.dangling(), 0)) + } else { + unsafe { + NonNull::new(GlobalAlloc::alloc(self, layout)) + .ok_or(AllocErr) + .map(|p| (p, layout.size())) + } + } } #[inline] - unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)) - .ok_or(AllocErr) - .map(|p| (p, layout.size())) + fn alloc_zeroed(&mut self, layout: Layout) -> Result<(NonNull, usize), AllocErr> { + if layout.size() == 0 { + Ok((layout.dangling(), 0)) + } else { + unsafe { + NonNull::new(GlobalAlloc::alloc_zeroed(self, layout)) + .ok_or(AllocErr) + .map(|p| (p, layout.size())) + } + } } #[inline] unsafe fn dealloc(&mut self, ptr: NonNull, layout: Layout) { - GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + if layout.size() != 0 { + GlobalAlloc::dealloc(self, ptr.as_ptr(), layout) + } } #[inline] @@ -160,9 +177,17 @@ unsafe impl AllocRef for System { layout: Layout, new_size: usize, ) -> Result<(NonNull, usize), AllocErr> { - NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)) - .ok_or(AllocErr) - .map(|p| (p, new_size)) + match (layout.size(), new_size) { + (0, 0) => Ok((layout.dangling(), 0)), + (0, _) => self.alloc(Layout::from_size_align_unchecked(new_size, layout.align())), + (_, 0) => { + self.dealloc(ptr, layout); + Ok((layout.dangling(), 0)) + } + (_, _) => NonNull::new(GlobalAlloc::realloc(self, ptr.as_ptr(), layout, new_size)) + .ok_or(AllocErr) + .map(|p| (p, new_size)), + } } } From 64460a12af8786a1859279d2944fd2fc67a3a159 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 8 Mar 2020 11:09:48 +0100 Subject: [PATCH 0883/1250] Update tests --- .../ui/json-bom-plus-crlf-multifile.stderr | 44 +++++++++++-------- src/test/ui/json-bom-plus-crlf.stderr | 44 +++++++++++-------- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/test/ui/json-bom-plus-crlf-multifile.stderr b/src/test/ui/json-bom-plus-crlf-multifile.stderr index ab0feb3c451..026943669f8 100644 --- a/src/test/ui/json-bom-plus-crlf-multifile.stderr +++ b/src/test/ui/json-bom-plus-crlf-multifile.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":612,"byte_end":618,"line_start":17,"line_end":17,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":621,"byte_end":622,"line_start":17,"line_end":17,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:17:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":672,"byte_end":678,"line_start":19,"line_end":19,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":681,"byte_end":682,"line_start":19,"line_end":19,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:19:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":735,"byte_end":741,"line_start":22,"line_end":22,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":745,"byte_end":746,"line_start":23,"line_end":23,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:23:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":801,"byte_end":809,"line_start":25,"line_end":26,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf-multifile-aux.rs","byte_start":792,"byte_end":798,"line_start":25,"line_end":25,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf-multifile-aux.rs:25:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors diff --git a/src/test/ui/json-bom-plus-crlf.stderr b/src/test/ui/json-bom-plus-crlf.stderr index 1dd898db3ad..735a46b8c87 100644 --- a/src/test/ui/json-bom-plus-crlf.stderr +++ b/src/test/ui/json-bom-plus-crlf.stderr @@ -1,10 +1,6 @@ -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a -variable. It can occur for several cases, the most common of which is a -mismatch in the expected type that the compiler inferred for a variable's -initializing expression, and the actual type explicitly assigned to the -variable. +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -15,15 +11,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":597,"byte_end":603,"line_start":16,"line_end":16,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":606,"byte_end":607,"line_start":16,"line_end":16,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1; // Error in the middle of line.","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:16:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -34,15 +32,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":657,"byte_end":663,"line_start":18,"line_end":18,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = 1","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":666,"byte_end":667,"line_start":18,"line_end":18,"column_start":22,"column_end":23,"is_primary":true,"text":[{"text":" let s : String = 1","highlight_start":22,"highlight_end":23}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:18:22: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -53,15 +53,17 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` -"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types -"} -{"message":"mismatched types","code":{"code":"E0308","explanation":"This error occurs when the compiler was unable to infer the concrete type of a + +This error occurs when the compiler was unable to infer the concrete type of a variable. It can occur for several cases, the most common of which is a mismatch in the expected type that the compiler inferred for a variable's initializing expression, and the actual type explicitly assigned to the variable. +"},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":"expected struct `std::string::String`, found integer","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":720,"byte_end":726,"line_start":21,"line_end":21,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String =","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"try using a conversion method","code":null,"level":"help","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":730,"byte_end":731,"line_start":22,"line_end":22,"column_start":1,"column_end":2,"is_primary":true,"text":[{"text":"1; // Error after the newline.","highlight_start":1,"highlight_end":2}],"label":null,"suggested_replacement":"1.to_string()","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"$DIR/json-bom-plus-crlf.rs:22:1: error[E0308]: mismatched types +"} +{"message":"mismatched types","code":{"code":"E0308","explanation":"Expected type did not match the received type. -For example: +Erroneous code example: ```compile_fail,E0308 let x: i32 = \"I am not a number!\"; @@ -72,6 +74,12 @@ let x: i32 = \"I am not a number!\"; // | // type `i32` assigned to variable `x` ``` + +This error occurs when the compiler was unable to infer the concrete type of a +variable. It can occur for several cases, the most common of which is a +mismatch in the expected type that the compiler inferred for a variable's +initializing expression, and the actual type explicitly assigned to the +variable. "},"level":"error","spans":[{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":786,"byte_end":794,"line_start":24,"line_end":25,"column_start":22,"column_end":6,"is_primary":true,"text":[{"text":" let s : String = (","highlight_start":22,"highlight_end":23},{"text":" ); // Error spanning the newline.","highlight_start":1,"highlight_end":6}],"label":"expected struct `std::string::String`, found `()`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"$DIR/json-bom-plus-crlf.rs","byte_start":777,"byte_end":783,"line_start":24,"line_end":24,"column_start":13,"column_end":19,"is_primary":false,"text":[{"text":" let s : String = (","highlight_start":13,"highlight_end":19}],"label":"expected due to this","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"$DIR/json-bom-plus-crlf.rs:24:22: error[E0308]: mismatched types "} {"message":"aborting due to 4 previous errors","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to 4 previous errors From a95f00fe1b064f548b6513fbf88afc223f6c4f9c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Mar 2020 12:22:20 +0100 Subject: [PATCH 0884/1250] fix type size mismatch on 32bit --- src/test/ui/consts/const-eval/ub-enum.rs | 5 ++- src/test/ui/consts/const-eval/ub-enum.stderr | 34 ++++++++++---------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/test/ui/consts/const-eval/ub-enum.rs b/src/test/ui/consts/const-eval/ub-enum.rs index 499be5107f9..1922d59891f 100644 --- a/src/test/ui/consts/const-eval/ub-enum.rs +++ b/src/test/ui/consts/const-eval/ub-enum.rs @@ -1,4 +1,3 @@ -// ignore-tidy-linelength #![feature(const_transmute, never_type)] #![allow(const_err)] // make sure we cannot allow away the errors tested here @@ -88,9 +87,9 @@ const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute //~^ ERROR is undefined behavior // All variants are uninhabited but also have data. -const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; +const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) }; //~^ ERROR is undefined behavior -const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; +const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) }; //~^ ERROR is undefined behavior fn main() { diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index e0cf2cd610f..10a3d2fa1ab 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -1,5 +1,5 @@ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:24:1 + --> $DIR/ub-enum.rs:23:1 | LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 1, but expected a valid enum discriminant @@ -7,7 +7,7 @@ LL | const BAD_ENUM: Enum = unsafe { mem::transmute(1usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:27:1 + --> $DIR/ub-enum.rs:26:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -15,7 +15,7 @@ LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:30:1 + --> $DIR/ub-enum.rs:29:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -23,7 +23,7 @@ LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:42:1 + --> $DIR/ub-enum.rs:41:1 | LL | const BAD_ENUM2: Enum2 = unsafe { mem::transmute(0usize) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0, but expected a valid enum discriminant @@ -31,7 +31,7 @@ LL | const BAD_ENUM2: Enum2 = 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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:44:1 + --> $DIR/ub-enum.rs:43:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -39,7 +39,7 @@ LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:47:1 + --> $DIR/ub-enum.rs:46:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at .0., but expected initialized plain (non-pointer) bytes @@ -47,7 +47,7 @@ LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:56:1 + --> $DIR/ub-enum.rs:55:1 | LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized bytes at ., but expected initialized plain (non-pointer) bytes @@ -55,7 +55,7 @@ LL | const BAD_ENUM2_UNDEF : Enum2 = unsafe { MaybeUninit { uninit: () }.init }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:60:1 + --> $DIR/ub-enum.rs:59:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a pointer at ., but expected initialized plain (non-pointer) bytes @@ -63,7 +63,7 @@ LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:77:1 + --> $DIR/ub-enum.rs:76:1 | LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute(1u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0 @@ -71,7 +71,7 @@ LL | const BAD_UNINHABITED_VARIANT1: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:79:1 + --> $DIR/ub-enum.rs:78:1 | LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute(3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0 @@ -79,7 +79,7 @@ LL | const BAD_UNINHABITED_VARIANT2: UninhDiscriminant = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:87:1 + --> $DIR/ub-enum.rs:86:1 | LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) })); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected a valid unicode codepoint @@ -87,18 +87,18 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:91:1 + --> $DIR/ub-enum.rs:90:1 | -LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.1 +LL | const BAD_UNINHABITED_WITH_DATA1: Result<(i32, Never), (i32, !)> = unsafe { mem::transmute(1u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of the never type `!` at ..0.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 rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-enum.rs:93:1 + --> $DIR/ub-enum.rs:92:1 | -LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1usize) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.1 +LL | const BAD_UNINHABITED_WITH_DATA2: Result<(i32, !), (i32, Never)> = unsafe { mem::transmute(1u64) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a value of uninhabited type Never at ..0.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 rustc repository if you believe it should not be considered undefined behavior. From cb58de81654d92074a4abdbf90400f35f6a0062f Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 8 Mar 2020 13:51:26 +0100 Subject: [PATCH 0885/1250] Apply suggestions from code review Co-Authored-By: bjorn3 --- src/librustc_mir/transform/generator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 841d18268b1..b386582947f 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -997,14 +997,14 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { return false; } - // If there's no return terminator the function also won't return. + // If there's a return terminator the function may return. for block in body.basic_blocks() { if let TerminatorKind::Return = block.terminator().kind { return true; } } - // Otherwise we assume that the function may return. + // Otherwise the function can't return. false } From 6d03bbd480ef9bef09321fbfdc00229a03091b11 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 8 Mar 2020 14:24:32 +0100 Subject: [PATCH 0886/1250] constify `mem::discriminant` --- src/libcore/intrinsics.rs | 1 + src/libcore/lib.rs | 1 + src/libcore/mem/mod.rs | 3 ++- src/librustc_mir/interpret/intrinsics.rs | 5 +++++ src/librustc_span/symbol.rs | 1 + src/test/ui/consts/const_discriminant.rs | 22 ++++++++++++++++++++++ 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/const_discriminant.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index a889eff75c0..63c5d782e65 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1852,6 +1852,7 @@ extern "rust-intrinsic" { /// /// The stabilized version of this intrinsic is /// [`std::mem::discriminant`](../../std/mem/fn.discriminant.html) + #[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] pub fn discriminant_value(v: &T) -> u64; /// Rust's "try catch" construct which invokes the function pointer `f` with diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 41fb4a77c7a..cac61c2c674 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -72,6 +72,7 @@ #![feature(concat_idents)] #![feature(const_ascii_ctype_on_intrinsics)] #![feature(const_alloc_layout)] +#![feature(const_discriminant)] #![feature(const_if_match)] #![feature(const_loop)] #![feature(const_checked_int_methods)] diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 90144d11dc9..c23d0adab5c 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -864,6 +864,7 @@ impl fmt::Debug for Discriminant { /// assert_ne!(mem::discriminant(&Foo::B(3)), mem::discriminant(&Foo::C(3))); /// ``` #[stable(feature = "discriminant_value", since = "1.21.0")] -pub fn discriminant(v: &T) -> Discriminant { +#[rustc_const_unstable(feature = "const_discriminant", issue = "69821")] +pub const fn discriminant(v: &T) -> Discriminant { Discriminant(intrinsics::discriminant_value(v), PhantomData) } diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 891afbf437f..1e5ed76c467 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -216,6 +216,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { }; self.write_scalar(val, dest)?; } + sym::discriminant_value => { + let place = self.deref_operand(args[0])?; + let discr_val = self.read_discriminant(place.into())?.0; + self.write_scalar(Scalar::from_uint(discr_val, dest.layout.size), dest)?; + } sym::unchecked_shl | sym::unchecked_shr | sym::unchecked_add diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index c39f9f360c0..0d37e9c2c7b 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -265,6 +265,7 @@ symbols! { derive, diagnostic, direct, + discriminant_value, doc, doc_alias, doc_cfg, diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs new file mode 100644 index 00000000000..5a32ff29158 --- /dev/null +++ b/src/test/ui/consts/const_discriminant.rs @@ -0,0 +1,22 @@ +// run-pass +#![feature(const_discriminant)] + +use std::mem::{discriminant, Discriminant}; + +enum Test { + A(u8), + B, + C { a: u8, b: u8 }, +} + +const TEST_A: Discriminant = discriminant(&Test::A(5)); +const TEST_A_OTHER: Discriminant = discriminant(&Test::A(17)); +const TEST_B: Discriminant = discriminant(&Test::B); + +fn main() { + assert_eq!(TEST_A, TEST_A_OTHER); + assert_eq!(TEST_A, discriminant(&Test::A(17))); + assert_eq!(TEST_B, discriminant(&Test::B)); + assert_ne!(TEST_A, TEST_B); + assert_ne!(TEST_B, discriminant(&Test::C { a: 42, b: 7 })); +} From 7a89bf166719d46b85c2d00686380587e46ec10d Mon Sep 17 00:00:00 2001 From: 12101111 Date: Sun, 8 Mar 2020 21:49:52 +0800 Subject: [PATCH 0887/1250] override flags from compiletest --- src/test/ui/proc-macro/musl-proc-macro.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/ui/proc-macro/musl-proc-macro.rs b/src/test/ui/proc-macro/musl-proc-macro.rs index 223f00eb043..7ea3726b751 100644 --- a/src/test/ui/proc-macro/musl-proc-macro.rs +++ b/src/test/ui/proc-macro/musl-proc-macro.rs @@ -1,6 +1,7 @@ // Test proc-macro crate can be built without addtional RUSTFLAGS // on musl target - +// override -Ctarget-feature=-crt-static from compiletest +// compile-flags: -Ctarget-feature= // build-pass // only-musl #![crate_type = "proc-macro"] From 22f2385a738827fb682bc72bb9e1d794bb436672 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 8 Mar 2020 15:12:46 +0100 Subject: [PATCH 0888/1250] prevent potential promotion in const_discriminant --- src/test/ui/consts/const_discriminant.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index 5a32ff29158..564434bb6fa 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -3,6 +3,8 @@ use std::mem::{discriminant, Discriminant}; +fn identity(x: T) -> T { x } + enum Test { A(u8), B, @@ -15,8 +17,8 @@ const TEST_B: Discriminant = discriminant(&Test::B); fn main() { assert_eq!(TEST_A, TEST_A_OTHER); - assert_eq!(TEST_A, discriminant(&Test::A(17))); - assert_eq!(TEST_B, discriminant(&Test::B)); + assert_eq!(TEST_A, discriminant(identity(&Test::A(17)))); + assert_eq!(TEST_B, discriminant(identity(&Test::B))); assert_ne!(TEST_A, TEST_B); - assert_ne!(TEST_B, discriminant(&Test::C { a: 42, b: 7 })); + assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 }))); } From 528cbc4879ceab332d509e4959fcea8baa7e8b92 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Mar 2020 16:43:03 +0100 Subject: [PATCH 0889/1250] fix memory leak when vec::IntoIter panics during drop --- src/liballoc/vec.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 61416f2b906..913e261ef12 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2626,13 +2626,21 @@ impl Clone for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] unsafe impl<#[may_dangle] T> Drop for IntoIter { fn drop(&mut self) { + struct DropGuard<'a, T>(&'a mut IntoIter); + + impl Drop for DropGuard<'_, T> { + fn drop(&mut self) { + // RawVec handles deallocation + let _ = unsafe { RawVec::from_raw_parts(self.0.buf.as_ptr(), self.0.cap) }; + } + } + + let guard = DropGuard(self); // destroy the remaining elements unsafe { - ptr::drop_in_place(self.as_mut_slice()); + ptr::drop_in_place(guard.0.as_mut_slice()); } - - // RawVec handles deallocation - let _ = unsafe { RawVec::from_raw_parts(self.buf.as_ptr(), self.cap) }; + // now `guard` will be dropped and do the rest } } From 6bbb9b86c4d4be72a92676e2d51dcc8032e1fe3e Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 8 Mar 2020 17:04:02 +0100 Subject: [PATCH 0890/1250] test discriminant of enum with uninhabited variant --- src/test/ui/consts/const_discriminant.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index 564434bb6fa..9aac3c4532f 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -15,10 +15,21 @@ const TEST_A: Discriminant = discriminant(&Test::A(5)); const TEST_A_OTHER: Discriminant = discriminant(&Test::A(17)); const TEST_B: Discriminant = discriminant(&Test::B); +enum Void {} + +enum SingleVariant { + V, + Never(Void), +} + +const TEST_V: Discriminant = discriminant(&SingleVariant::V); + fn main() { assert_eq!(TEST_A, TEST_A_OTHER); assert_eq!(TEST_A, discriminant(identity(&Test::A(17)))); assert_eq!(TEST_B, discriminant(identity(&Test::B))); assert_ne!(TEST_A, TEST_B); assert_ne!(TEST_B, discriminant(identity(&Test::C { a: 42, b: 7 }))); + + assert_eq!(TEST_V, discriminant(identity(&SingleVariant::V))); } From 4b724e82d2b1065eea10a96fafb19e1390edf0d7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sun, 8 Mar 2020 18:56:15 +0100 Subject: [PATCH 0891/1250] allow dead code in discriminant test --- src/test/ui/consts/const_discriminant.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index 9aac3c4532f..c67be3c3713 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -1,5 +1,6 @@ // run-pass #![feature(const_discriminant)] +#![allow(dead_code)] use std::mem::{discriminant, Discriminant}; From 48975946565e9a0adedb39a308db2fd2eeaa2839 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 8 Mar 2020 19:05:18 +0100 Subject: [PATCH 0892/1250] miri: ICE on invalid terminators --- src/librustc_mir/interpret/terminator.rs | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index ea8378574a3..85fd502c69c 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -114,15 +114,12 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Unreachable => throw_ub!(Unreachable), // These should never occur for MIR we actually run. - DropAndReplace { .. } | FalseEdges { .. } | FalseUnwind { .. } => { - bug!("{:#?} should have been eliminated by MIR pass", terminator.kind) - } - - // These are not (yet) supported. It is unclear if they even can occur in - // MIR that we actually run. - Yield { .. } | GeneratorDrop | Abort => { - throw_unsup_format!("Unsupported terminator kind: {:#?}", terminator.kind) - } + DropAndReplace { .. } + | FalseEdges { .. } + | FalseUnwind { .. } + | Yield { .. } + | GeneratorDrop + | Abort => bug!("{:#?} should have been eliminated by MIR pass", terminator.kind), } Ok(()) From 0468929ce3f3e142287124a37f3318cc3b53a52b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 08:40:13 +0100 Subject: [PATCH 0893/1250] move error allocation test to error.rs --- src/librustc/mir/interpret/error.rs | 18 +++++++++++- src/librustc_mir/transform/const_prop.rs | 35 ++++++------------------ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 28e197b2a7f..2310867400c 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -354,7 +354,7 @@ pub enum UnsupportedOpInfo<'tcx> { Unsupported(String), /// When const-prop encounters a situation it does not support, it raises this error. - /// This must not allocate for performance reasons. + /// This must not allocate for performance reasons (hence `str`, not `String`). ConstPropUnsupported(&'tcx str), // -- Everything below is not categorized yet -- @@ -612,3 +612,19 @@ impl fmt::Debug for InterpError<'_> { } } } + +impl InterpError<'_> { + /// Some errors allocate to be created as they contain free-from strings. + /// And sometiems we want to be sure that did not happen as it is a + /// waste of resources. + pub fn allocates(&self) -> bool { + match self { + InterpError::MachineStop(_) + | InterpError::Unsupported(UnsupportedOpInfo::Unsupported(_)) + | InterpError::Unsupported(UnsupportedOpInfo::ValidationFailure(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) + | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) => true, + _ => false, + } + } +} diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0560f77f5c9..1fea9281b93 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -404,32 +404,15 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { let r = match f(self) { Ok(val) => Some(val), Err(error) => { - use rustc::mir::interpret::{ - InterpError::*, UndefinedBehaviorInfo, UnsupportedOpInfo, - }; - match error.kind { - MachineStop(_) => bug!("ConstProp does not stop"), - - // Some error shouldn't come up because creating them causes - // an allocation, which we should avoid. When that happens, - // dedicated error variants should be introduced instead. - // Only test this in debug builds though to avoid disruptions. - Unsupported(UnsupportedOpInfo::Unsupported(_)) - | Unsupported(UnsupportedOpInfo::ValidationFailure(_)) - | UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) - | UndefinedBehavior(UndefinedBehaviorInfo::UbExperimental(_)) - if cfg!(debug_assertions) => - { - bug!("const-prop encountered allocating error: {:?}", error.kind); - } - - Unsupported(_) - | UndefinedBehavior(_) - | InvalidProgram(_) - | ResourceExhaustion(_) => { - // Ignore these errors. - } - } + // Some errors shouldn't come up because creating them causes + // an allocation, which we should avoid. When that happens, + // dedicated error variants should be introduced instead. + // Only test this in debug builds though to avoid disruptions. + debug_assert!( + !error.kind.allocates(), + "const-prop encountered allocating error: {}", + error + ); None } }; From 938f8522ecf6c463bc06503251a23c3ded35ca25 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 4 Mar 2020 08:43:03 +0100 Subject: [PATCH 0894/1250] miri validation: debug-complain about unexpected errors --- src/librustc_mir/interpret/validity.rs | 27 ++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 84717cbeaa9..b3de44f36d2 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -46,6 +46,8 @@ macro_rules! try_validation { ($e:expr, $what:expr, $where:expr, $details:expr) => {{ match $e { Ok(x) => x, + // We re-throw the error, so we are okay with allocation: + // this can only slow down builds that fail anyway. Err(_) => throw_validation_failure!($what, $where, $details), } }}; @@ -53,6 +55,8 @@ macro_rules! try_validation { ($e:expr, $what:expr, $where:expr) => {{ match $e { Ok(x) => x, + // We re-throw the error, so we are okay with allocation: + // this can only slow down builds that fail anyway. Err(_) => throw_validation_failure!($what, $where), } }}; @@ -359,10 +363,13 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M format_args!("a dangling {} (created from integer)", kind), self.path ), - _ => throw_validation_failure!( - format_args!("a dangling {} (not entirely in bounds)", kind), - self.path - ), + err_unsup!(PointerOutOfBounds { .. }) | err_unsup!(DanglingPointerDeref) => { + throw_validation_failure!( + format_args!("a dangling {} (not entirely in bounds)", kind), + self.path + ) + } + _ => bug!("Unexpected error during ptr inbounds test: {}", err), } } }; @@ -638,6 +645,7 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> err_unsup!(ReadPointerAsBytes) => { throw_validation_failure!("a pointer", self.path, "plain (non-pointer) bytes") } + // Propagate upwards (that will also check for unexpected errors). _ => return Err(err), }, } @@ -797,7 +805,14 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Try to cast to ptr *once* instead of all the time. let op = self.force_op_ptr(op).unwrap_or(op); - // Run it - visitor.visit_value(op) + // Run it. + match visitor.visit_value(op) { + Ok(()) => Ok(()), + Err(err) if matches!(err.kind, err_unsup!(ValidationFailure { .. })) => Err(err), + Err(err) if cfg!(debug_assertions) => { + bug!("Unexpected error during validation: {}", err) + } + Err(err) => Err(err), + } } } From 4971d03ccfe9452753deb84fd958fd0b0e63f156 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 5 Mar 2020 23:31:39 +0100 Subject: [PATCH 0895/1250] fix some cases of unexpected exceptions leaving validation --- src/librustc/mir/interpret/error.rs | 13 ++-- src/librustc_mir/const_eval/eval_queries.rs | 7 +- src/librustc_mir/interpret/eval_context.rs | 12 +--- src/librustc_mir/interpret/place.rs | 8 +-- src/librustc_mir/interpret/validity.rs | 64 +++++++++++++++---- src/librustc_mir/transform/const_prop.rs | 5 +- src/test/ui/consts/const-eval/dangling.rs | 2 +- src/test/ui/consts/const-eval/dangling.stderr | 2 +- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 6 +- .../ui/consts/const-eval/ub-wide-ptr.stderr | 58 +++++++++++------ .../ui/consts/const-points-to-static.stderr | 2 +- src/test/ui/consts/issue-63952.stderr | 2 +- .../const_refers_to_static.stderr | 4 +- 13 files changed, 122 insertions(+), 63 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 2310867400c..731c3ee0d6a 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -245,7 +245,7 @@ fn print_backtrace(backtrace: &mut Backtrace) { eprintln!("\n\nAn error occurred in miri:\n{:?}", backtrace); } -impl From for InterpErrorInfo<'tcx> { +impl From for InterpErrorInfo<'_> { fn from(err: ErrorHandled) -> Self { match err { ErrorHandled::Reported => err_inval!(ReferencedConstant), @@ -291,7 +291,7 @@ pub enum InvalidProgramInfo<'tcx> { Layout(layout::LayoutError<'tcx>), } -impl fmt::Debug for InvalidProgramInfo<'tcx> { +impl fmt::Debug for InvalidProgramInfo<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use InvalidProgramInfo::*; match self { @@ -304,7 +304,7 @@ impl fmt::Debug for InvalidProgramInfo<'tcx> { } /// Error information for when the program caused Undefined Behavior. -pub enum UndefinedBehaviorInfo { +pub enum UndefinedBehaviorInfo<'tcx> { /// Free-form case. Only for errors that are never caught! Ub(String), /// Free-form case for experimental UB. Only for errors that are never caught! @@ -321,9 +321,11 @@ pub enum UndefinedBehaviorInfo { RemainderByZero, /// Overflowing inbounds pointer arithmetic. PointerArithOverflow, + /// Invalid metadata in a wide pointer (using `str` to avoid allocations). + InvalidMeta(&'tcx str), } -impl fmt::Debug for UndefinedBehaviorInfo { +impl fmt::Debug for UndefinedBehaviorInfo<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UndefinedBehaviorInfo::*; match self { @@ -338,6 +340,7 @@ impl fmt::Debug for UndefinedBehaviorInfo { DivisionByZero => write!(f, "dividing by zero"), RemainderByZero => write!(f, "calculating the remainder with a divisor of zero"), PointerArithOverflow => write!(f, "overflowing in-bounds pointer arithmetic"), + InvalidMeta(msg) => write!(f, "invalid metadata in wide pointer: {}", msg), } } } @@ -577,7 +580,7 @@ impl fmt::Debug for ResourceExhaustionInfo { pub enum InterpError<'tcx> { /// The program caused undefined behavior. - UndefinedBehavior(UndefinedBehaviorInfo), + UndefinedBehavior(UndefinedBehaviorInfo<'tcx>), /// The program did something the interpreter does not support (some of these *might* be UB /// but the interpreter is not sure). Unsupported(UnsupportedOpInfo<'tcx>), diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index 7a8e61db6d0..ffbff00cf37 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -186,7 +186,12 @@ fn validate_and_turn_into_const<'tcx>( if cid.promoted.is_none() { let mut ref_tracking = RefTracking::new(mplace); while let Some((mplace, path)) = ref_tracking.todo.pop() { - ecx.validate_operand(mplace.into(), path, Some(&mut ref_tracking))?; + ecx.const_validate_operand( + mplace.into(), + path, + &mut ref_tracking, + /*may_ref_to_static*/ is_static, + )?; } } // Now that we validated, turn this into a proper constant. diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index e683422e611..9b28b7a20c0 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -457,10 +457,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Check if this brought us over the size limit. if size.bytes() >= self.tcx.data_layout().obj_size_bound() { - throw_ub_format!( - "wide pointer metadata contains invalid information: \ - total size is bigger than largest supported object" - ); + throw_ub!(InvalidMeta("total size is bigger than largest supported object")); } Ok(Some((size, align))) } @@ -476,10 +473,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Make sure the slice is not too big. let size = elem.size.checked_mul(len, &*self.tcx).ok_or_else(|| { - err_ub_format!( - "invalid slice: \ - total size is bigger than largest supported object" - ) + err_ub!(InvalidMeta("slice is bigger than largest supported object")) })?; Ok(Some((size, elem.align.abi))) } @@ -685,7 +679,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // invariant -- that is, unless a function somehow has a ptr to // its return place... but the way MIR is currently generated, the // return place is always a local and then this cannot happen. - self.validate_operand(self.place_to_op(return_place)?, vec![], None)?; + self.validate_operand(self.place_to_op(return_place)?)?; } } else { // Uh, that shouldn't happen... the function did not intend to return diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index fff9c740f7e..a4815b9696e 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -689,7 +689,7 @@ where if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! - self.validate_operand(self.place_to_op(dest)?, vec![], None)?; + self.validate_operand(self.place_to_op(dest)?)?; } Ok(()) @@ -706,7 +706,7 @@ where if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! - self.validate_operand(dest.into(), vec![], None)?; + self.validate_operand(dest.into())?; } Ok(()) @@ -843,7 +843,7 @@ where if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! - self.validate_operand(self.place_to_op(dest)?, vec![], None)?; + self.validate_operand(self.place_to_op(dest)?)?; } Ok(()) @@ -951,7 +951,7 @@ where if M::enforce_validity(self) { // Data got changed, better make sure it matches the type! - self.validate_operand(dest.into(), vec![], None)?; + self.validate_operand(dest.into())?; } Ok(()) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index b3de44f36d2..05bb010959b 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -171,6 +171,7 @@ struct ValidityVisitor<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> { path: Vec, ref_tracking_for_consts: Option<&'rt mut RefTracking, Vec>>, + may_ref_to_static: bool, ecx: &'rt InterpCx<'mir, 'tcx, M>, } @@ -324,9 +325,17 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M self.check_wide_ptr_meta(place.meta, place.layout)?; } // Make sure this is dereferenceable and all. - let (size, align) = self - .ecx - .size_and_align_of(place.meta, place.layout)? + let size_and_align = match self.ecx.size_and_align_of(place.meta, place.layout) { + Ok(res) => res, + Err(err) => match err.kind { + err_ub!(InvalidMeta(msg)) => throw_validation_failure!( + format_args!("invalid {} metadata: {}", kind, msg), + self.path + ), + _ => bug!("Unexpected error during ptr size_and_align_of: {}", err), + }, + }; + let (size, align) = size_and_align // for the purpose of validity, consider foreign types to have // alignment and size determined by the layout (size will be 0, // alignment should take attributes into account). @@ -387,6 +396,12 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, 'tcx, M if !did.is_local() || self.ecx.tcx.is_foreign_item(did) { return Ok(()); } + if !self.may_ref_to_static && self.ecx.tcx.is_static(did) { + throw_validation_failure!( + format_args!("a {} pointing to a static variable", kind), + self.path + ); + } } } // Proceed recursively even for ZST, no reason to skip them! @@ -781,26 +796,20 @@ impl<'rt, 'mir, 'tcx, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> } impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { - /// This function checks the data at `op`. `op` is assumed to cover valid memory if it - /// is an indirect operand. - /// It will error if the bits at the destination do not match the ones described by the layout. - /// - /// `ref_tracking_for_consts` can be `None` to avoid recursive checking below references. - /// This also toggles between "run-time" (no recursion) and "compile-time" (with recursion) - /// validation (e.g., pointer values are fine in integers at runtime) and various other const - /// specific validation checks. - pub fn validate_operand( + fn validate_operand_internal( &self, op: OpTy<'tcx, M::PointerTag>, path: Vec, ref_tracking_for_consts: Option< &mut RefTracking, Vec>, >, + may_ref_to_static: bool, ) -> InterpResult<'tcx> { - trace!("validate_operand: {:?}, {:?}", *op, op.layout.ty); + trace!("validate_operand_internal: {:?}, {:?}", *op, op.layout.ty); // Construct a visitor - let mut visitor = ValidityVisitor { path, ref_tracking_for_consts, ecx: self }; + let mut visitor = + ValidityVisitor { path, ref_tracking_for_consts, may_ref_to_static, ecx: self }; // Try to cast to ptr *once* instead of all the time. let op = self.force_op_ptr(op).unwrap_or(op); @@ -815,4 +824,31 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Err(err) => Err(err), } } + + /// This function checks the data at `op` to be const-valid. + /// `op` is assumed to cover valid memory if it is an indirect operand. + /// It will error if the bits at the destination do not match the ones described by the layout. + /// + /// `ref_tracking` is used to record references that we encounter so that they + /// can be checked recursively by an outside driving loop. + /// + /// `may_ref_to_static` controls whether references are allowed to point to statics. + #[inline(always)] + pub fn const_validate_operand( + &self, + op: OpTy<'tcx, M::PointerTag>, + path: Vec, + ref_tracking: &mut RefTracking, Vec>, + may_ref_to_static: bool, + ) -> InterpResult<'tcx> { + self.validate_operand_internal(op, path, Some(ref_tracking), may_ref_to_static) + } + + /// This function checks the data at `op` to be runtime-valid. + /// `op` is assumed to cover valid memory if it is an indirect operand. + /// It will error if the bits at the destination do not match the ones described by the layout. + #[inline(always)] + pub fn validate_operand(&self, op: OpTy<'tcx, M::PointerTag>) -> InterpResult<'tcx> { + self.validate_operand_internal(op, vec![], None, false) + } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 1fea9281b93..a07c8575b30 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -637,11 +637,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_info: SourceInfo, ) { trace!("attepting to replace {:?} with {:?}", rval, value); - if let Err(e) = self.ecx.validate_operand( + if let Err(e) = self.ecx.const_validate_operand( value, vec![], // FIXME: is ref tracking too expensive? - Some(&mut interpret::RefTracking::empty()), + &mut interpret::RefTracking::empty(), + /*may_ref_to_static*/ true, ) { trace!("validation error, attempt failed: {:?}", e); return; diff --git a/src/test/ui/consts/const-eval/dangling.rs b/src/test/ui/consts/const-eval/dangling.rs index b5d72d46f28..c6b8e8eb611 100644 --- a/src/test/ui/consts/const-eval/dangling.rs +++ b/src/test/ui/consts/const-eval/dangling.rs @@ -6,7 +6,7 @@ use std::{mem, usize}; const TEST: () = { unsafe { //~ NOTE let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); let _val = &*slice; //~ ERROR: any use of this value will cause an error - //~^ NOTE: total size is bigger than largest supported object + //~^ NOTE: slice is bigger than largest supported object //~^^ on by default } }; diff --git a/src/test/ui/consts/const-eval/dangling.stderr b/src/test/ui/consts/const-eval/dangling.stderr index 286de080097..b9ddc93b03b 100644 --- a/src/test/ui/consts/const-eval/dangling.stderr +++ b/src/test/ui/consts/const-eval/dangling.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | / const TEST: () = { unsafe { LL | | let slice: *const [u8] = mem::transmute((1usize, usize::MAX)); LL | | let _val = &*slice; - | | ^^^^^^^ invalid slice: total size is bigger than largest supported object + | | ^^^^^^^ invalid metadata in wide pointer: slice is bigger than largest supported object LL | | LL | | LL | | } }; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 26d37884746..2d48309b727 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -31,12 +31,16 @@ const STR_VALID: &str = unsafe { mem::transmute((&42u8, 1usize)) }; // bad str const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; //~^ ERROR it is undefined behavior to use this value +const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); +//~^ ERROR it is undefined behavior to use this value // bad str const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value // bad str in user-defined unsized type const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; //~^ ERROR it is undefined behavior to use this value +const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; +//~^ ERROR it is undefined behavior to use this value // invalid UTF-8 const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; @@ -83,7 +87,7 @@ const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute // # raw slice const RAW_SLICE_VALID: *const [u8] = unsafe { mem::transmute((&42u8, 1usize)) }; // ok const RAW_SLICE_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, 999usize)) }; // ok because raw -const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::max_value())) }; // ok because raw +const RAW_SLICE_MUCH_TOO_LONG: *const [u8] = unsafe { mem::transmute((&42u8, usize::MAX)) }; // ok because raw const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { //~^ ERROR it is undefined behavior to use this value let uninit_len = MaybeUninit:: { uninit: () }; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 22adf0e55ee..a562c64b124 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -7,7 +7,15 @@ LL | const STR_TOO_LONG: &str = unsafe { mem::transmute((&42u8, 999usize)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:35:1 + --> $DIR/ub-wide-ptr.rs:34:1 + | +LL | const NESTED_STR_MUCH_TOO_LONG: (&str,) = (unsafe { mem::transmute((&42, usize::MAX)) },); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object at .0 + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:37:1 | LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -15,7 +23,7 @@ LL | const STR_LENGTH_PTR: &str = unsafe { mem::transmute((&42u8, &3)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:38:1 + --> $DIR/ub-wide-ptr.rs:40:1 | LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -25,13 +33,21 @@ LL | const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:42:1 | +LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. + +error[E0080]: it is undefined behavior to use this value + --> $DIR/ub-wide-ptr.rs:46:1 + | LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:45:1 + --> $DIR/ub-wide-ptr.rs:49:1 | LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 @@ -39,7 +55,7 @@ LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:52:1 + --> $DIR/ub-wide-ptr.rs:56:1 | LL | / const SLICE_LENGTH_UNINIT: &[u8] = unsafe { LL | | @@ -51,7 +67,7 @@ LL | | }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:58:1 + --> $DIR/ub-wide-ptr.rs:62:1 | LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling reference (not entirely in bounds) @@ -59,7 +75,7 @@ LL | const SLICE_TOO_LONG: &[u8] = unsafe { mem::transmute((&42u8, 999usize)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:61:1 + --> $DIR/ub-wide-ptr.rs:65:1 | LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -67,7 +83,7 @@ LL | const SLICE_LENGTH_PTR: &[u8] = unsafe { mem::transmute((&42u8, &3)) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:64:1 + --> $DIR/ub-wide-ptr.rs:68:1 | LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a dangling box (not entirely in bounds) @@ -75,7 +91,7 @@ LL | const SLICE_TOO_LONG_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, 999us = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:67:1 + --> $DIR/ub-wide-ptr.rs:71:1 | LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered non-integer slice length in wide pointer @@ -83,7 +99,7 @@ LL | const SLICE_LENGTH_PTR_BOX: Box<[u8]> = unsafe { mem::transmute((&42u8, &3) = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:71:1 + --> $DIR/ub-wide-ptr.rs:75:1 | LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .[0], but expected a boolean @@ -91,7 +107,7 @@ LL | const SLICE_CONTENT_INVALID: &[bool] = &[unsafe { mem::transmute(3u8) }]; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:77:1 + --> $DIR/ub-wide-ptr.rs:81:1 | LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3u8) }, [false]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..0, but expected a boolean @@ -99,7 +115,7 @@ LL | const MYSLICE_PREFIX_BAD: &MySliceBool = &MySlice(unsafe { mem::transmute(3 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:80:1 + --> $DIR/ub-wide-ptr.rs:84:1 | LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::transmute(3u8) }]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at ..1[0], but expected a boolean @@ -107,7 +123,7 @@ LL | const MYSLICE_SUFFIX_BAD: &MySliceBool = &MySlice(true, [unsafe { mem::tran = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:87:1 + --> $DIR/ub-wide-ptr.rs:91:1 | LL | / const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { LL | | @@ -119,7 +135,7 @@ LL | | }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:95:1 + --> $DIR/ub-wide-ptr.rs:99:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -127,7 +143,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:98:1 + --> $DIR/ub-wide-ptr.rs:102:1 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -135,7 +151,7 @@ LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:101:1 + --> $DIR/ub-wide-ptr.rs:105:1 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -143,7 +159,7 @@ LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4u = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:105:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 3 at .., but expected a boolean @@ -151,7 +167,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:109:1 + --> $DIR/ub-wide-ptr.rs:113:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -159,7 +175,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:111:1 + --> $DIR/ub-wide-ptr.rs:115:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling or unaligned vtable pointer in wide pointer or too small vtable @@ -167,17 +183,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:117:5 + --> $DIR/ub-wide-ptr.rs:121:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid use of NULL pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:121:5 + --> $DIR/ub-wide-ptr.rs:125:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocation N which has size N -error: aborting due to 22 previous errors +error: aborting due to 24 previous errors For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-points-to-static.stderr b/src/test/ui/consts/const-points-to-static.stderr index 8949358e293..f2ca7ff7825 100644 --- a/src/test/ui/consts/const-points-to-static.stderr +++ b/src/test/ui/consts/const-points-to-static.stderr @@ -8,7 +8,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-points-to-static.rs:5:1 | LL | const TEST: &u8 = &MY_STATIC; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/issue-63952.stderr b/src/test/ui/consts/issue-63952.stderr index d5ed970fc35..5e85be45b16 100644 --- a/src/test/ui/consts/issue-63952.stderr +++ b/src/test/ui/consts/issue-63952.stderr @@ -8,7 +8,7 @@ LL | | ptr: &42, ... | LL | | .slice LL | | }; - | |__^ invalid slice: total size is bigger than largest supported object + | |__^ type validation failed: encountered invalid reference metadata: slice is bigger than largest supported object | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr index 15e13942481..ad777cfe8ea 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static.stderr @@ -48,7 +48,7 @@ LL | | static FOO: AtomicUsize = AtomicUsize::new(0); LL | | unsafe { &*(&FOO as *const _ as *const usize) } LL | | LL | | }; - | |__^ constant accesses static + | |__^ type validation failed: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -97,7 +97,7 @@ LL | | static FOO: usize = 0; LL | | &FOO LL | | LL | | }; - | |__^ constant accesses static + | |__^ type validation failed: encountered a reference pointing to a static variable | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From 85e1466232eadd2ec6b9c2ae0aa4030a39fde04f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Mar 2020 11:30:57 +0100 Subject: [PATCH 0896/1250] Fix typo Co-Authored-By: bjorn3 --- src/librustc/mir/interpret/error.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 731c3ee0d6a..5869c76345a 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -617,8 +617,8 @@ impl fmt::Debug for InterpError<'_> { } impl InterpError<'_> { - /// Some errors allocate to be created as they contain free-from strings. - /// And sometiems we want to be sure that did not happen as it is a + /// Some errors allocate to be created as they contain free-form strings. + /// And sometimes we want to be sure that did not happen as it is a /// waste of resources. pub fn allocates(&self) -> bool { match self { From ed3014a2b9470a89165f2762ba746ee7736d5590 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 6 Mar 2020 18:14:41 +0100 Subject: [PATCH 0897/1250] use static strings instead of tcx --- src/librustc/mir/interpret/error.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/mir/interpret/error.rs b/src/librustc/mir/interpret/error.rs index 5869c76345a..b46095927b7 100644 --- a/src/librustc/mir/interpret/error.rs +++ b/src/librustc/mir/interpret/error.rs @@ -304,7 +304,7 @@ impl fmt::Debug for InvalidProgramInfo<'_> { } /// Error information for when the program caused Undefined Behavior. -pub enum UndefinedBehaviorInfo<'tcx> { +pub enum UndefinedBehaviorInfo { /// Free-form case. Only for errors that are never caught! Ub(String), /// Free-form case for experimental UB. Only for errors that are never caught! @@ -322,10 +322,10 @@ pub enum UndefinedBehaviorInfo<'tcx> { /// Overflowing inbounds pointer arithmetic. PointerArithOverflow, /// Invalid metadata in a wide pointer (using `str` to avoid allocations). - InvalidMeta(&'tcx str), + InvalidMeta(&'static str), } -impl fmt::Debug for UndefinedBehaviorInfo<'_> { +impl fmt::Debug for UndefinedBehaviorInfo { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { use UndefinedBehaviorInfo::*; match self { @@ -358,7 +358,7 @@ pub enum UnsupportedOpInfo<'tcx> { /// When const-prop encounters a situation it does not support, it raises this error. /// This must not allocate for performance reasons (hence `str`, not `String`). - ConstPropUnsupported(&'tcx str), + ConstPropUnsupported(&'static str), // -- Everything below is not categorized yet -- FunctionAbiMismatch(Abi, Abi), @@ -580,7 +580,7 @@ impl fmt::Debug for ResourceExhaustionInfo { pub enum InterpError<'tcx> { /// The program caused undefined behavior. - UndefinedBehavior(UndefinedBehaviorInfo<'tcx>), + UndefinedBehavior(UndefinedBehaviorInfo), /// The program did something the interpreter does not support (some of these *might* be UB /// but the interpreter is not sure). Unsupported(UnsupportedOpInfo<'tcx>), From d32924f89d1324386588bd23b0437cdeca1e0fc8 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 05:00:03 +0900 Subject: [PATCH 0898/1250] Check if output is immediate value --- src/librustc_codegen_llvm/asm.rs | 10 ++++++++-- src/test/ui/asm/issue-62046.rs | 11 +++++++++++ src/test/ui/asm/issue-62046.stderr | 11 +++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/asm/issue-62046.rs create mode 100644 src/test/ui/asm/issue-62046.stderr diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs index c8f0fe8c723..7975a70ab26 100644 --- a/src/librustc_codegen_llvm/asm.rs +++ b/src/librustc_codegen_llvm/asm.rs @@ -29,11 +29,17 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let mut indirect_outputs = vec![]; for (i, (out, &place)) in ia.outputs.iter().zip(&outputs).enumerate() { if out.is_rw { - inputs.push(self.load_operand(place).immediate()); + let operand = self.load_operand(place); + if let OperandValue::Immediate(_) = operand.val { + inputs.push(operand.immediate()); + } ext_constraints.push(i.to_string()); } if out.is_indirect { - indirect_outputs.push(self.load_operand(place).immediate()); + let operand = self.load_operand(place); + if let OperandValue::Immediate(_) = operand.val { + indirect_outputs.push(operand.immediate()); + } } else { output_types.push(place.layout.llvm_type(self.cx())); } diff --git a/src/test/ui/asm/issue-62046.rs b/src/test/ui/asm/issue-62046.rs new file mode 100644 index 00000000000..105dadd5fd3 --- /dev/null +++ b/src/test/ui/asm/issue-62046.rs @@ -0,0 +1,11 @@ +// build-fail +// ignore-emscripten no asm! support + +#![feature(asm)] + +fn main() { + unsafe { + asm!("nop" : "+r"("r15")); + //~^ malformed inline assembly + } +} diff --git a/src/test/ui/asm/issue-62046.stderr b/src/test/ui/asm/issue-62046.stderr new file mode 100644 index 00000000000..a38a300548d --- /dev/null +++ b/src/test/ui/asm/issue-62046.stderr @@ -0,0 +1,11 @@ +error[E0668]: malformed inline assembly + --> $DIR/issue-62046.rs:8:9 + | +LL | asm!("nop" : "+r"("r15")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0668`. From af0c44cb2908989159322a4f2bf6ce046a7be5fc Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:11:40 +0900 Subject: [PATCH 0899/1250] Add test for issue-54239 --- .../issue-54239-private-type-triggers-lint.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs diff --git a/src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs b/src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs new file mode 100644 index 00000000000..16cf7ad52e4 --- /dev/null +++ b/src/test/ui/async-await/issue-54239-private-type-triggers-lint.rs @@ -0,0 +1,17 @@ +// Regression test for #54239, shouldn't trigger lint. +// check-pass +// edition:2018 + +#![deny(missing_debug_implementations)] + +struct DontLookAtMe(i32); + +async fn secret() -> DontLookAtMe { + DontLookAtMe(41) +} + +pub async fn looking() -> i32 { // Shouldn't trigger lint here. + secret().await.0 +} + +fn main() {} From fc8be08a8e786514819ffff7c4239879afb8ea3c Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:11:58 +0900 Subject: [PATCH 0900/1250] Add test for issue-57200 --- src/test/ui/impl-trait/issue-57200.rs | 14 ++++++++++++++ src/test/ui/impl-trait/issue-57200.stderr | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-57200.rs create mode 100644 src/test/ui/impl-trait/issue-57200.stderr diff --git a/src/test/ui/impl-trait/issue-57200.rs b/src/test/ui/impl-trait/issue-57200.rs new file mode 100644 index 00000000000..9a7290b3b75 --- /dev/null +++ b/src/test/ui/impl-trait/issue-57200.rs @@ -0,0 +1,14 @@ +// Regression test for #57200 + +#![feature(impl_trait_in_bindings)] +#![allow(incomplete_features)] + +fn bug<'a, 'b, T>() +where + 'a: 'b, +{ + let f: impl Fn(&'a T) -> &'b T = |x| x; + //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-57200.stderr b/src/test/ui/impl-trait/issue-57200.stderr new file mode 100644 index 00000000000..42fd0045315 --- /dev/null +++ b/src/test/ui/impl-trait/issue-57200.stderr @@ -0,0 +1,8 @@ +error: lifetimes in impl Trait types in bindings are not currently supported + --> $DIR/issue-57200.rs:10:12 + | +LL | let f: impl Fn(&'a T) -> &'b T = |x| x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 437c07f6621739037e52560f54a880acaaaf27ac Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:12:06 +0900 Subject: [PATCH 0901/1250] Add test for issue-57201 --- src/test/ui/impl-trait/issue-57201.rs | 14 ++++++++++++++ src/test/ui/impl-trait/issue-57201.stderr | 8 ++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-57201.rs create mode 100644 src/test/ui/impl-trait/issue-57201.stderr diff --git a/src/test/ui/impl-trait/issue-57201.rs b/src/test/ui/impl-trait/issue-57201.rs new file mode 100644 index 00000000000..79b19b52d20 --- /dev/null +++ b/src/test/ui/impl-trait/issue-57201.rs @@ -0,0 +1,14 @@ +// Regression test for #57201 + +#![feature(impl_trait_in_bindings)] +#![allow(incomplete_features)] + +fn bug<'a, 'b, T>() +where + 'a: 'b, +{ + let f: &impl Fn(&'a T) -> &'b T = &|x| x; + //~^ ERROR: lifetimes in impl Trait types in bindings are not currently supported +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-57201.stderr b/src/test/ui/impl-trait/issue-57201.stderr new file mode 100644 index 00000000000..5defd15b6b5 --- /dev/null +++ b/src/test/ui/impl-trait/issue-57201.stderr @@ -0,0 +1,8 @@ +error: lifetimes in impl Trait types in bindings are not currently supported + --> $DIR/issue-57201.rs:10:13 + | +LL | let f: &impl Fn(&'a T) -> &'b T = &|x| x; + | ^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 0005f29d89e9b5ab59f9159acb7aab51b5dad187 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:12:25 +0900 Subject: [PATCH 0902/1250] Add test for issue-60473 --- src/test/ui/impl-trait/issue-60473.rs | 16 ++++++++++++++++ src/test/ui/impl-trait/issue-60473.stderr | 11 +++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-60473.rs create mode 100644 src/test/ui/impl-trait/issue-60473.stderr diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs new file mode 100644 index 00000000000..596d8a2dd74 --- /dev/null +++ b/src/test/ui/impl-trait/issue-60473.rs @@ -0,0 +1,16 @@ +// Regression test for #60473 + +#![feature(impl_trait_in_bindings)] +#![allow(incomplete_features)] + +struct A<'a>(&'a ()); + +trait Trait { +} + +impl Trait for () { +} + +fn main() { + let x: impl Trait = (); //~ ERROR: opaque type expands to a recursive type +} diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr new file mode 100644 index 00000000000..6a07f29727c --- /dev/null +++ b/src/test/ui/impl-trait/issue-60473.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/issue-60473.rs:15:12 + | +LL | let x: impl Trait = (); + | ^^^^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. From 95d478546ff3b3b3f533e6b86274bde432148ab3 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:12:41 +0900 Subject: [PATCH 0903/1250] Add test for issue-64620 --- src/test/ui/generator/issue-64620-yield-array-element.rs | 9 +++++++++ .../ui/generator/issue-64620-yield-array-element.stderr | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 src/test/ui/generator/issue-64620-yield-array-element.rs create mode 100644 src/test/ui/generator/issue-64620-yield-array-element.stderr diff --git a/src/test/ui/generator/issue-64620-yield-array-element.rs b/src/test/ui/generator/issue-64620-yield-array-element.rs new file mode 100644 index 00000000000..2cbe8f51614 --- /dev/null +++ b/src/test/ui/generator/issue-64620-yield-array-element.rs @@ -0,0 +1,9 @@ +// Regression test for #64620 + +#![feature(generators)] + +pub fn crash(arr: [usize; 1]) { + yield arr[0]; //~ ERROR: yield expression outside of generator literal +} + +fn main() {} diff --git a/src/test/ui/generator/issue-64620-yield-array-element.stderr b/src/test/ui/generator/issue-64620-yield-array-element.stderr new file mode 100644 index 00000000000..48383c2ed08 --- /dev/null +++ b/src/test/ui/generator/issue-64620-yield-array-element.stderr @@ -0,0 +1,9 @@ +error[E0627]: yield expression outside of generator literal + --> $DIR/issue-64620-yield-array-element.rs:6:5 + | +LL | yield arr[0]; + | ^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0627`. From 579ce86d4b813c89eb8a483f79c427565b06c7d2 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 09:12:53 +0900 Subject: [PATCH 0904/1250] Add test for issue-67166 --- src/test/ui/impl-trait/issue-67166.rs | 11 +++++++++++ src/test/ui/impl-trait/issue-67166.stderr | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 src/test/ui/impl-trait/issue-67166.rs create mode 100644 src/test/ui/impl-trait/issue-67166.stderr diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs new file mode 100644 index 00000000000..a877d4cfe3b --- /dev/null +++ b/src/test/ui/impl-trait/issue-67166.rs @@ -0,0 +1,11 @@ +// Regression test for #67166 + +#![feature(impl_trait_in_bindings)] +#![allow(incomplete_features)] + +pub fn run() { + let _foo: Box = Box::new(()); + //~^ ERROR: opaque type expands to a recursive type +} + +fn main() {} diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr new file mode 100644 index 00000000000..abf30f67d5f --- /dev/null +++ b/src/test/ui/impl-trait/issue-67166.stderr @@ -0,0 +1,11 @@ +error[E0720]: opaque type expands to a recursive type + --> $DIR/issue-67166.rs:7:19 + | +LL | let _foo: Box = Box::new(()); + | ^^^^^^^^^^^^^^ expands to a recursive type + | + = note: type resolves to itself + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0720`. From 75e6cfc79b39253ee0e4fafc7805c7b0a1f24ef2 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Mon, 9 Mar 2020 08:39:34 +0800 Subject: [PATCH 0905/1250] run crt-static test on all target --- src/test/ui/proc-macro/{musl-proc-macro.rs => crt-static.rs} | 1 - 1 file changed, 1 deletion(-) rename src/test/ui/proc-macro/{musl-proc-macro.rs => crt-static.rs} (96%) diff --git a/src/test/ui/proc-macro/musl-proc-macro.rs b/src/test/ui/proc-macro/crt-static.rs similarity index 96% rename from src/test/ui/proc-macro/musl-proc-macro.rs rename to src/test/ui/proc-macro/crt-static.rs index 7ea3726b751..bed45c6a5b8 100644 --- a/src/test/ui/proc-macro/musl-proc-macro.rs +++ b/src/test/ui/proc-macro/crt-static.rs @@ -3,7 +3,6 @@ // override -Ctarget-feature=-crt-static from compiletest // compile-flags: -Ctarget-feature= // build-pass -// only-musl #![crate_type = "proc-macro"] extern crate proc_macro; From 58303b77e0f7b35edd6791b6000cfbaef9cc1cfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 6 Mar 2020 00:00:00 +0000 Subject: [PATCH 0906/1250] Use slices in preference to 0-terminated strings Additionally whenever possible match C API provided by the LLVM. --- .../debuginfo/metadata.rs | 247 ++++++++++-------- src/librustc_codegen_llvm/debuginfo/mod.rs | 22 +- .../debuginfo/namespace.rs | 12 +- src/librustc_codegen_llvm/llvm/ffi.rs | 26 +- src/rustllvm/RustWrapper.cpp | 146 ++++++----- 5 files changed, 266 insertions(+), 187 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 19bd0b6f7e6..5cf3d74f243 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -37,7 +37,6 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::const_cstr; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; @@ -49,7 +48,6 @@ use rustc_target::abi::HasDataLayout; use libc::{c_longlong, c_uint}; use std::collections::hash_map::Entry; -use std::ffi::CString; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; use std::iter; @@ -227,11 +225,14 @@ impl TypeMap<'ll, 'tcx> { /// Gets the unique type ID string for an enum variant part. /// Variant parts are not types and shouldn't really have their own ID, /// but it makes `set_members_of_composite_type()` simpler. - fn get_unique_type_id_str_of_enum_variant_part(&mut self, enum_type_id: UniqueTypeId) -> &str { + fn get_unique_type_id_str_of_enum_variant_part( + &mut self, + enum_type_id: UniqueTypeId, + ) -> String { let variant_part_type_id = format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)); - let interner_key = self.unique_id_interner.intern(&variant_part_type_id); - self.unique_id_interner.get(interner_key) + self.unique_id_interner.intern(&variant_part_type_id); + variant_part_type_id } } @@ -640,9 +641,11 @@ pub fn type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>, usage_site_span: Sp // type is going to see *something* weird - the only // question is what exactly it will see. let (size, align) = cx.size_and_align_of(t); + let name = ""; llvm::LLVMRustDIBuilderCreateBasicType( DIB(cx), - SmallCStr::new("").as_ptr(), + name.as_ptr().cast(), + name.len(), size.bits(), align.bits() as u32, DW_ATE_unsigned, @@ -786,16 +789,17 @@ fn file_metadata_raw( let (file_name, directory) = v.key(); debug!("file_metadata: file_name: {:?}, directory: {:?}", file_name, directory); - let file_name = SmallCStr::new(if let Some(file_name) = file_name { - &file_name - } else { - "" - }); - let directory = - SmallCStr::new(if let Some(directory) = directory { &directory } else { "" }); + let file_name = file_name.as_deref().unwrap_or(""); + let directory = directory.as_deref().unwrap_or(""); let file_metadata = unsafe { - llvm::LLVMRustDIBuilderCreateFile(DIB(cx), file_name.as_ptr(), directory.as_ptr()) + llvm::LLVMRustDIBuilderCreateFile( + DIB(cx), + file_name.as_ptr().cast(), + file_name.len(), + directory.as_ptr().cast(), + directory.len(), + ) }; v.insert(file_metadata); @@ -819,11 +823,11 @@ fn basic_type_metadata(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { }; let (size, align) = cx.size_and_align_of(t); - let name = SmallCStr::new(name); let ty_metadata = unsafe { llvm::LLVMRustDIBuilderCreateBasicType( DIB(cx), - name.as_ptr(), + name.as_ptr().cast(), + name.len(), size.bits(), align.bits() as u32, encoding, @@ -851,14 +855,15 @@ fn pointer_type_metadata( ) -> &'ll DIType { let (pointer_size, pointer_align) = cx.size_and_align_of(pointer_type); let name = compute_debuginfo_type_name(cx.tcx, pointer_type, false); - let name = SmallCStr::new(&name); unsafe { llvm::LLVMRustDIBuilderCreatePointerType( DIB(cx), pointee_type_metadata, pointer_size.bits(), pointer_align.bits() as u32, - name.as_ptr(), + 0, // Ignore DWARF address space. + name.as_ptr().cast(), + name.len(), ) } } @@ -889,11 +894,9 @@ pub fn compile_unit_metadata( let producer = format!("clang LLVM ({})", rustc_producer); let name_in_debuginfo = name_in_debuginfo.to_string_lossy(); - let name_in_debuginfo = SmallCStr::new(&name_in_debuginfo); - let work_dir = SmallCStr::new(&tcx.sess.working_dir.0.to_string_lossy()); - let producer = CString::new(producer).unwrap(); + let work_dir = tcx.sess.working_dir.0.to_string_lossy(); let flags = "\0"; - let split_name = "\0"; + let split_name = ""; // FIXME(#60020): // @@ -916,19 +919,23 @@ pub fn compile_unit_metadata( unsafe { let file_metadata = llvm::LLVMRustDIBuilderCreateFile( debug_context.builder, - name_in_debuginfo.as_ptr(), - work_dir.as_ptr(), + name_in_debuginfo.as_ptr().cast(), + name_in_debuginfo.len(), + work_dir.as_ptr().cast(), + work_dir.len(), ); let unit_metadata = llvm::LLVMRustDIBuilderCreateCompileUnit( debug_context.builder, DW_LANG_RUST, file_metadata, - producer.as_ptr(), + producer.as_ptr().cast(), + producer.len(), tcx.sess.opts.optimize != config::OptLevel::No, flags.as_ptr().cast(), 0, split_name.as_ptr().cast(), + split_name.len(), kind, ); @@ -1021,12 +1028,12 @@ impl<'ll> MemberDescription<'ll> { cx: &CodegenCx<'ll, '_>, composite_type_metadata: &'ll DIScope, ) -> &'ll DIType { - let member_name = CString::new(self.name).unwrap(); unsafe { llvm::LLVMRustDIBuilderCreateVariantMemberType( DIB(cx), composite_type_metadata, - member_name.as_ptr(), + self.name.as_ptr().cast(), + self.name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, self.size.bits(), @@ -1827,9 +1834,13 @@ fn prepare_enum_metadata( let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(cx.tcx), rustc_span::DUMMY_SP); + let item_name; let discriminant_name = match enum_type.kind { - ty::Adt(..) => SmallCStr::new(&cx.tcx.item_name(enum_def_id).as_str()), - ty::Generator(..) => SmallCStr::new(&enum_name), + ty::Adt(..) => { + item_name = cx.tcx.item_name(enum_def_id).as_str(); + &*item_name + } + ty::Generator(..) => enum_name.as_str(), _ => bug!(), }; @@ -1837,7 +1848,8 @@ fn prepare_enum_metadata( llvm::LLVMRustDIBuilderCreateEnumerationType( DIB(cx), containing_scope, - discriminant_name.as_ptr(), + discriminant_name.as_ptr().cast(), + discriminant_name.len(), file_metadata, UNKNOWN_LINE_NUMBER, discriminant_size.bits(), @@ -1872,11 +1884,6 @@ fn prepare_enum_metadata( _ => {} } - let enum_name = SmallCStr::new(&enum_name); - let unique_type_id_str = SmallCStr::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id), - ); - if use_enum_fallback(cx) { let discriminant_type_metadata = match layout.variants { layout::Variants::Single { .. } @@ -1891,20 +1898,27 @@ fn prepare_enum_metadata( } => Some(discriminant_type_metadata(discr.value)), }; - let enum_metadata = unsafe { - llvm::LLVMRustDIBuilderCreateUnionType( - DIB(cx), - containing_scope, - enum_name.as_ptr(), - file_metadata, - UNKNOWN_LINE_NUMBER, - layout.size.bits(), - layout.align.abi.bits() as u32, - DIFlags::FlagZero, - None, - 0, // RuntimeLang - unique_type_id_str.as_ptr(), - ) + let enum_metadata = { + let type_map = debug_context(cx).type_map.borrow(); + let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id); + + unsafe { + llvm::LLVMRustDIBuilderCreateUnionType( + DIB(cx), + containing_scope, + enum_name.as_ptr().cast(), + enum_name.len(), + file_metadata, + UNKNOWN_LINE_NUMBER, + layout.size.bits(), + layout.align.abi.bits() as u32, + DIFlags::FlagZero, + None, + 0, // RuntimeLang + unique_type_id_str.as_ptr().cast(), + unique_type_id_str.len(), + ) + } }; return create_and_register_recursive_type_forward_declaration( @@ -1924,10 +1938,9 @@ fn prepare_enum_metadata( } let discriminator_name = match &enum_type.kind { - ty::Generator(..) => Some(SmallCStr::new(&"__state")), - _ => None, + ty::Generator(..) => "__state", + _ => "", }; - let discriminator_name = discriminator_name.map(|n| n.as_ptr()).unwrap_or(ptr::null_mut()); let discriminator_metadata = match layout.variants { // A single-variant enum has no discriminant. layout::Variants::Single { .. } => None, @@ -1955,7 +1968,8 @@ fn prepare_enum_metadata( Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), containing_scope, - discriminator_name, + discriminator_name.as_ptr().cast(), + discriminator_name.len(), file_metadata, UNKNOWN_LINE_NUMBER, size.bits(), @@ -1981,7 +1995,8 @@ fn prepare_enum_metadata( Some(llvm::LLVMRustDIBuilderCreateMemberType( DIB(cx), containing_scope, - discriminator_name, + discriminator_name.as_ptr().cast(), + discriminator_name.len(), file_metadata, UNKNOWN_LINE_NUMBER, size.bits(), @@ -2010,18 +2025,18 @@ fn prepare_enum_metadata( } }; - let variant_part_unique_type_id_str = SmallCStr::new( - debug_context(cx) - .type_map - .borrow_mut() - .get_unique_type_id_str_of_enum_variant_part(unique_type_id), - ); + let variant_part_unique_type_id_str = debug_context(cx) + .type_map + .borrow_mut() + .get_unique_type_id_str_of_enum_variant_part(unique_type_id); let empty_array = create_DIArray(DIB(cx), &[]); + let name = ""; let variant_part = unsafe { llvm::LLVMRustDIBuilderCreateVariantPart( DIB(cx), containing_scope, - ptr::null_mut(), + name.as_ptr().cast(), + name.len(), file_metadata, UNKNOWN_LINE_NUMBER, layout.size.bits(), @@ -2029,29 +2044,38 @@ fn prepare_enum_metadata( DIFlags::FlagZero, discriminator_metadata, empty_array, - variant_part_unique_type_id_str.as_ptr(), + variant_part_unique_type_id_str.as_ptr().cast(), + variant_part_unique_type_id_str.len(), ) }; outer_fields.push(Some(variant_part)); - // The variant part must be wrapped in a struct according to DWARF. - let type_array = create_DIArray(DIB(cx), &outer_fields); - let struct_wrapper = unsafe { - llvm::LLVMRustDIBuilderCreateStructType( - DIB(cx), - Some(containing_scope), - enum_name.as_ptr(), - file_metadata, - UNKNOWN_LINE_NUMBER, - layout.size.bits(), - layout.align.abi.bits() as u32, - DIFlags::FlagZero, - None, - type_array, - 0, - None, - unique_type_id_str.as_ptr(), - ) + let struct_wrapper = { + // The variant part must be wrapped in a struct according to DWARF. + let type_array = create_DIArray(DIB(cx), &outer_fields); + + let type_map = debug_context(cx).type_map.borrow(); + let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id); + + unsafe { + llvm::LLVMRustDIBuilderCreateStructType( + DIB(cx), + Some(containing_scope), + enum_name.as_ptr().cast(), + enum_name.len(), + file_metadata, + UNKNOWN_LINE_NUMBER, + layout.size.bits(), + layout.align.abi.bits() as u32, + DIFlags::FlagZero, + None, + type_array, + 0, + None, + unique_type_id_str.as_ptr().cast(), + unique_type_id_str.len(), + ) + } }; return create_and_register_recursive_type_forward_declaration( @@ -2156,12 +2180,13 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> Option<&' cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, rustc_span::DUMMY_SP); - let name = SmallCStr::new(&name.as_str()); + let name = &name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, - name.as_ptr(), + name.as_ptr().cast(), + name.len(), actual_type_metadata, unknown_file_metadata(cx), 0, @@ -2200,10 +2225,9 @@ fn create_struct_stub( ) -> &'ll DICompositeType { let (struct_size, struct_align) = cx.size_and_align_of(struct_type); - let name = SmallCStr::new(struct_type_name); - let unique_type_id = SmallCStr::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id), - ); + let type_map = debug_context(cx).type_map.borrow(); + let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id); + let metadata_stub = unsafe { // `LLVMRustDIBuilderCreateStructType()` wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions @@ -2213,7 +2237,8 @@ fn create_struct_stub( llvm::LLVMRustDIBuilderCreateStructType( DIB(cx), containing_scope, - name.as_ptr(), + struct_type_name.as_ptr().cast(), + struct_type_name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, struct_size.bits(), @@ -2223,7 +2248,8 @@ fn create_struct_stub( empty_array, 0, None, - unique_type_id.as_ptr(), + unique_type_id.as_ptr().cast(), + unique_type_id.len(), ) }; @@ -2239,10 +2265,9 @@ fn create_union_stub( ) -> &'ll DICompositeType { let (union_size, union_align) = cx.size_and_align_of(union_type); - let name = SmallCStr::new(union_type_name); - let unique_type_id = SmallCStr::new( - debug_context(cx).type_map.borrow().get_unique_type_id_as_string(unique_type_id), - ); + let type_map = debug_context(cx).type_map.borrow(); + let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id); + let metadata_stub = unsafe { // `LLVMRustDIBuilderCreateUnionType()` wants an empty array. A null // pointer will lead to hard to trace and debug LLVM assertions @@ -2252,7 +2277,8 @@ fn create_union_stub( llvm::LLVMRustDIBuilderCreateUnionType( DIB(cx), containing_scope, - name.as_ptr(), + union_type_name.as_ptr().cast(), + union_type_name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, union_size.bits(), @@ -2260,7 +2286,8 @@ fn create_union_stub( DIFlags::FlagZero, Some(empty_array), 0, // RuntimeLang - unique_type_id.as_ptr(), + unique_type_id.as_ptr().cast(), + unique_type_id.len(), ) }; @@ -2294,13 +2321,15 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).monomorphic_ty(cx.tcx); let type_metadata = type_metadata(cx, variable_type, span); - let var_name = SmallCStr::new(&tcx.item_name(def_id).as_str()); + let var_name = tcx.item_name(def_id).as_str(); let linkage_name = if no_mangle { None } else { - let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)); - Some(SmallCStr::new(&linkage_name.name.as_str())) + Some(mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name.as_str()) }; + // When empty, linkage_name field is omitted, + // which is what we want for no_mangle statics + let linkage_name = linkage_name.as_deref().unwrap_or(""); let global_align = cx.align_of(variable_type); @@ -2308,10 +2337,10 @@ pub fn create_global_var_metadata(cx: &CodegenCx<'ll, '_>, def_id: DefId, global llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), Some(var_scope), - var_name.as_ptr(), - // If null, linkage_name field is omitted, - // which is what we want for no_mangle statics - linkage_name.as_ref().map_or(ptr::null(), |name| name.as_ptr()), + var_name.as_ptr().cast(), + var_name.len(), + linkage_name.as_ptr().cast(), + linkage_name.len(), file_metadata, line_number, type_metadata, @@ -2339,8 +2368,7 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & // pointer will lead to hard to trace and debug LLVM assertions // later on in `llvm/lib/IR/Value.cpp`. let empty_array = create_DIArray(DIB(cx), &[]); - - let name = const_cstr!("vtable"); + let name = "vtable"; // Create a new one each time. We don't want metadata caching // here, because each vtable will refer to a unique containing @@ -2348,7 +2376,8 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & let vtable_type = llvm::LLVMRustDIBuilderCreateStructType( DIB(cx), NO_SCOPE_METADATA, - name.as_ptr(), + name.as_ptr().cast(), + name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, Size::ZERO.bits(), @@ -2358,14 +2387,18 @@ pub fn create_vtable_metadata(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, vtable: & empty_array, 0, Some(type_metadata), - name.as_ptr(), + name.as_ptr().cast(), + name.len(), ); + let linkage_name = ""; llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), NO_SCOPE_METADATA, - name.as_ptr(), - ptr::null(), + name.as_ptr().cast(), + name.len(), + linkage_name.as_ptr().cast(), + linkage_name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, vtable_type, diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index a68441f14cb..8deab1be3d3 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -25,13 +25,11 @@ use rustc::ty::{self, Instance, ParamEnv, Ty}; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::small_c_str::SmallCStr; use rustc_index::vec::IndexVec; use libc::c_uint; use log::debug; use std::cell::RefCell; -use std::ffi::CString; use rustc::ty::layout::{self, HasTyCtxt, LayoutOf, Size}; use rustc_ast::ast; @@ -273,13 +271,11 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { // Get the linkage_name, which is just the symbol name let linkage_name = mangled_name_of_instance(self, instance); + let linkage_name = linkage_name.name.as_str(); // FIXME(eddyb) does this need to be separate from `loc.line` for some reason? let scope_line = loc.line; - let function_name = CString::new(name).unwrap(); - let linkage_name = SmallCStr::new(&linkage_name.name.as_str()); - let mut flags = DIFlags::FlagPrototyped; if fn_abi.ret.layout.abi.is_uninhabited() { @@ -303,8 +299,10 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { llvm::LLVMRustDIBuilderCreateFunction( DIB(self), containing_scope, - function_name.as_ptr(), - linkage_name.as_ptr(), + name.as_ptr().cast(), + name.len(), + linkage_name.as_ptr().cast(), + linkage_name.len(), file_metadata, loc.line as c_uint, function_type_metadata, @@ -424,12 +422,13 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); let actual_type_metadata = type_metadata(cx, actual_type, rustc_span::DUMMY_SP); - let name = SmallCStr::new(&name.as_str()); + let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( DIB(cx), None, - name.as_ptr(), + name.as_ptr().cast(), + name.len(), actual_type_metadata, file_metadata, 0, @@ -542,13 +541,14 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { }; let align = self.align_of(variable_type); - let name = SmallCStr::new(&variable_name.as_str()); + let name = variable_name.as_str(); unsafe { llvm::LLVMRustDIBuilderCreateVariable( DIB(self), dwarf_tag, scope_metadata, - name.as_ptr(), + name.as_ptr().cast(), + name.len(), file_metadata, loc.line as c_uint, type_metadata, diff --git a/src/librustc_codegen_llvm/debuginfo/namespace.rs b/src/librustc_codegen_llvm/debuginfo/namespace.rs index 582f4952074..55a3540809b 100644 --- a/src/librustc_codegen_llvm/debuginfo/namespace.rs +++ b/src/librustc_codegen_llvm/debuginfo/namespace.rs @@ -1,6 +1,5 @@ // Namespace Handling. -use super::metadata::{unknown_file_metadata, UNKNOWN_LINE_NUMBER}; use super::utils::{debug_context, DIB}; use rustc::ty::{self, Instance}; @@ -10,8 +9,6 @@ use crate::llvm::debuginfo::DIScope; use rustc::hir::map::DefPathData; use rustc_hir::def_id::DefId; -use rustc_data_structures::small_c_str::SmallCStr; - pub fn mangled_name_of_instance<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, instance: Instance<'tcx>, @@ -34,16 +31,15 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope { DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate), data => data.as_symbol(), }; - - let namespace_name = SmallCStr::new(&namespace_name.as_str()); + let namespace_name = namespace_name.as_str(); let scope = unsafe { llvm::LLVMRustDIBuilderCreateNameSpace( DIB(cx), parent_scope, - namespace_name.as_ptr(), - unknown_file_metadata(cx), - UNKNOWN_LINE_NUMBER, + namespace_name.as_ptr().cast(), + namespace_name.len(), + false, // ExportSymbols (only relevant for C++ anonymous namespaces) ) }; diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 8b796e0423b..31a0f528090 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -1607,17 +1607,21 @@ extern "C" { Lang: c_uint, File: &'a DIFile, Producer: *const c_char, + ProducerLen: size_t, isOptimized: bool, Flags: *const c_char, RuntimeVer: c_uint, SplitName: *const c_char, + SplitNameLen: size_t, kind: DebugEmissionKind, ) -> &'a DIDescriptor; pub fn LLVMRustDIBuilderCreateFile( Builder: &DIBuilder<'a>, Filename: *const c_char, + FilenameLen: size_t, Directory: *const c_char, + DirectoryLen: size_t, ) -> &'a DIFile; pub fn LLVMRustDIBuilderCreateSubroutineType( @@ -1630,7 +1634,9 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, + NameLen: size_t, LinkageName: *const c_char, + LinkageNameLen: size_t, File: &'a DIFile, LineNo: c_uint, Ty: &'a DIType, @@ -1645,6 +1651,7 @@ extern "C" { pub fn LLVMRustDIBuilderCreateBasicType( Builder: &DIBuilder<'a>, Name: *const c_char, + NameLen: size_t, SizeInBits: u64, AlignInBits: u32, Encoding: c_uint, @@ -1655,13 +1662,16 @@ extern "C" { PointeeTy: &'a DIType, SizeInBits: u64, AlignInBits: u32, + AddressSpace: c_uint, Name: *const c_char, + NameLen: size_t, ) -> &'a DIDerivedType; pub fn LLVMRustDIBuilderCreateStructType( Builder: &DIBuilder<'a>, Scope: Option<&'a DIDescriptor>, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, SizeInBits: u64, @@ -1672,12 +1682,14 @@ extern "C" { RunTimeLang: c_uint, VTableHolder: Option<&'a DIType>, UniqueId: *const c_char, + UniqueIdLen: size_t, ) -> &'a DICompositeType; pub fn LLVMRustDIBuilderCreateMemberType( Builder: &DIBuilder<'a>, Scope: &'a DIDescriptor, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNo: c_uint, SizeInBits: u64, @@ -1691,6 +1703,7 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, SizeInBits: u64, @@ -1719,7 +1732,9 @@ extern "C" { Builder: &DIBuilder<'a>, Context: Option<&'a DIScope>, Name: *const c_char, + NameLen: size_t, LinkageName: *const c_char, + LinkageNameLen: size_t, File: &'a DIFile, LineNo: c_uint, Ty: &'a DIType, @@ -1734,6 +1749,7 @@ extern "C" { Tag: c_uint, Scope: &'a DIDescriptor, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNo: c_uint, Ty: &'a DIType, @@ -1785,6 +1801,7 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, SizeInBits: u64, @@ -1798,6 +1815,7 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNumber: c_uint, SizeInBits: u64, @@ -1806,12 +1824,14 @@ extern "C" { Elements: Option<&'a DIArray>, RunTimeLang: c_uint, UniqueId: *const c_char, + UniqueIdLen: size_t, ) -> &'a DIType; pub fn LLVMRustDIBuilderCreateVariantPart( Builder: &DIBuilder<'a>, Scope: &'a DIScope, Name: *const c_char, + NameLen: size_t, File: &'a DIFile, LineNo: c_uint, SizeInBits: u64, @@ -1820,6 +1840,7 @@ extern "C" { Discriminator: Option<&'a DIDerivedType>, Elements: &'a DIArray, UniqueId: *const c_char, + UniqueIdLen: size_t, ) -> &'a DIDerivedType; pub fn LLVMSetUnnamedAddr(GlobalVar: &Value, UnnamedAddr: Bool); @@ -1828,6 +1849,7 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, + NameLen: size_t, Ty: &'a DIType, File: &'a DIFile, LineNo: c_uint, @@ -1838,8 +1860,8 @@ extern "C" { Builder: &DIBuilder<'a>, Scope: Option<&'a DIScope>, Name: *const c_char, - File: &'a DIFile, - LineNo: c_uint, + NameLen: size_t, + ExportSymbols: bool, ) -> &'a DINameSpace; pub fn LLVMRustDICompositeTypeReplaceArrays( diff --git a/src/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp index 0e430d3881e..aeddd4cfb9f 100644 --- a/src/rustllvm/RustWrapper.cpp +++ b/src/rustllvm/RustWrapper.cpp @@ -665,20 +665,24 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) { extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, - const char *Producer, bool isOptimized, const char *Flags, - unsigned RuntimeVer, const char *SplitName, + const char *Producer, size_t ProducerLen, bool isOptimized, + const char *Flags, unsigned RuntimeVer, + const char *SplitName, size_t SplitNameLen, LLVMRustDebugEmissionKind Kind) { auto *File = unwrapDI(FileRef); - return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized, - Flags, RuntimeVer, SplitName, + return wrap(Builder->createCompileUnit(Lang, File, StringRef(Producer, ProducerLen), + isOptimized, Flags, RuntimeVer, + StringRef(SplitName, SplitNameLen), fromRust(Kind))); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateFile(LLVMRustDIBuilderRef Builder, const char *Filename, - const char *Directory) { - return wrap(Builder->createFile(Filename, Directory)); +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFile( + LLVMRustDIBuilderRef Builder, + const char *Filename, size_t FilenameLen, + const char *Directory, size_t DirectoryLen) { + return wrap(Builder->createFile(StringRef(Filename, FilenameLen), + StringRef(Directory, DirectoryLen))); } extern "C" LLVMMetadataRef @@ -690,8 +694,10 @@ LLVMRustDIBuilderCreateSubroutineType(LLVMRustDIBuilderRef Builder, } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, - const char *LinkageName, LLVMMetadataRef File, unsigned LineNo, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, + const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, unsigned ScopeLine, LLVMRustDIFlags Flags, LLVMRustDISPFlags SPFlags, LLVMValueRef Fn, LLVMMetadataRef TParam, LLVMMetadataRef Decl) { @@ -705,8 +711,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( llvmFlags |= DINode::DIFlags::FlagMainSubprogram; #endif DISubprogram *Sub = Builder->createFunction( - unwrapDI(Scope), Name, LinkageName, unwrapDI(File), - LineNo, unwrapDI(Ty), ScopeLine, llvmFlags, + unwrapDI(Scope), + StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), + unwrapDI(File), LineNo, + unwrapDI(Ty), ScopeLine, llvmFlags, llvmSPFlags, TParams, unwrapDIPtr(Decl)); #else bool IsLocalToUnit = isSet(SPFlags & LLVMRustDISPFlags::SPFlagLocalToUnit); @@ -716,8 +725,11 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( if (isSet(SPFlags & LLVMRustDISPFlags::SPFlagMainSubprogram)) llvmFlags |= DINode::DIFlags::FlagMainSubprogram; DISubprogram *Sub = Builder->createFunction( - unwrapDI(Scope), Name, LinkageName, unwrapDI(File), - LineNo, unwrapDI(Ty), IsLocalToUnit, IsDefinition, + unwrapDI(Scope), + StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), + unwrapDI(File), LineNo, + unwrapDI(Ty), IsLocalToUnit, IsDefinition, ScopeLine, llvmFlags, IsOptimized, TParams, unwrapDIPtr(Decl)); #endif @@ -725,53 +737,59 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateFunction( return wrap(Sub); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateBasicType(LLVMRustDIBuilderRef Builder, const char *Name, - uint64_t SizeInBits, uint32_t AlignInBits, - unsigned Encoding) { - return wrap(Builder->createBasicType(Name, SizeInBits, Encoding)); +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateBasicType( + LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, + uint64_t SizeInBits, uint32_t AlignInBits, unsigned Encoding) { + return wrap(Builder->createBasicType(StringRef(Name, NameLen), SizeInBits, Encoding)); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreatePointerType( LLVMRustDIBuilderRef Builder, LLVMMetadataRef PointeeTy, - uint64_t SizeInBits, uint32_t AlignInBits, const char *Name) { + uint64_t SizeInBits, uint32_t AlignInBits, unsigned AddressSpace, + const char *Name, size_t NameLen) { return wrap(Builder->createPointerType(unwrapDI(PointeeTy), SizeInBits, AlignInBits, - /* DWARFAddressSpace */ None, - Name)); + AddressSpace, + StringRef(Name, NameLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStructType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef DerivedFrom, LLVMMetadataRef Elements, unsigned RunTimeLang, LLVMMetadataRef VTableHolder, - const char *UniqueId) { + const char *UniqueId, size_t UniqueIdLen) { return wrap(Builder->createStructType( - unwrapDI(Scope), Name, unwrapDI(File), LineNumber, + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, fromRust(Flags), unwrapDI(DerivedFrom), DINodeArray(unwrapDI(Elements)), RunTimeLang, - unwrapDI(VTableHolder), UniqueId)); + unwrapDI(VTableHolder), StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantPart( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Discriminator, - LLVMMetadataRef Elements, const char *UniqueId) { + LLVMMetadataRef Elements, const char *UniqueId, size_t UniqueIdLen) { return wrap(Builder->createVariantPart( - unwrapDI(Scope), Name, unwrapDI(File), LineNumber, + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, fromRust(Flags), unwrapDI(Discriminator), - DINodeArray(unwrapDI(Elements)), UniqueId)); + DINodeArray(unwrapDI(Elements)), StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { - return wrap(Builder->createMemberType(unwrapDI(Scope), Name, + return wrap(Builder->createMemberType(unwrapDI(Scope), + StringRef(Name, NameLen), unwrapDI(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, fromRust(Flags), unwrapDI(Ty))); @@ -779,14 +797,15 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateMemberType( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariantMemberType( LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, - const char *Name, LLVMMetadataRef File, unsigned LineNo, uint64_t SizeInBits, - uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNo, + uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits, LLVMValueRef Discriminant, LLVMRustDIFlags Flags, LLVMMetadataRef Ty) { llvm::ConstantInt* D = nullptr; if (Discriminant) { D = unwrap(Discriminant); } - return wrap(Builder->createVariantMemberType(unwrapDI(Scope), Name, + return wrap(Builder->createVariantMemberType(unwrapDI(Scope), + StringRef(Name, NameLen), unwrapDI(File), LineNo, SizeInBits, AlignInBits, OffsetInBits, D, fromRust(Flags), unwrapDI(Ty))); @@ -808,8 +827,10 @@ LLVMRustDIBuilderCreateLexicalBlockFile(LLVMRustDIBuilderRef Builder, } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, const char *Name, - const char *LinkageName, LLVMMetadataRef File, unsigned LineNo, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Context, + const char *Name, size_t NameLen, + const char *LinkageName, size_t LinkageNameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool IsLocalToUnit, LLVMValueRef V, LLVMMetadataRef Decl = nullptr, uint32_t AlignInBits = 0) { llvm::GlobalVariable *InitVal = cast(unwrap(V)); @@ -825,7 +846,8 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( } llvm::DIGlobalVariableExpression *VarExpr = Builder->createGlobalVariableExpression( - unwrapDI(Context), Name, LinkageName, + unwrapDI(Context), StringRef(Name, NameLen), + StringRef(LinkageName, LinkageNameLen), unwrapDI(File), LineNo, unwrapDI(Ty), IsLocalToUnit, #if LLVM_VERSION_GE(10, 0) /* isDefined */ true, @@ -843,17 +865,20 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticVariable( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateVariable( LLVMRustDIBuilderRef Builder, unsigned Tag, LLVMMetadataRef Scope, - const char *Name, LLVMMetadataRef File, unsigned LineNo, + const char *Name, size_t NameLen, + LLVMMetadataRef File, unsigned LineNo, LLVMMetadataRef Ty, bool AlwaysPreserve, LLVMRustDIFlags Flags, unsigned ArgNo, uint32_t AlignInBits) { if (Tag == 0x100) { // DW_TAG_auto_variable return wrap(Builder->createAutoVariable( - unwrapDI(Scope), Name, unwrapDI(File), LineNo, + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNo, unwrapDI(Ty), AlwaysPreserve, fromRust(Flags), AlignInBits)); } else { return wrap(Builder->createParameterVariable( - unwrapDI(Scope), Name, ArgNo, unwrapDI(File), - LineNo, unwrapDI(Ty), AlwaysPreserve, fromRust(Flags))); + unwrapDI(Scope), StringRef(Name, NameLen), ArgNo, + unwrapDI(File), LineNo, + unwrapDI(Ty), AlwaysPreserve, fromRust(Flags))); } } @@ -894,47 +919,50 @@ extern "C" LLVMValueRef LLVMRustDIBuilderInsertDeclareAtEnd( extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerator( LLVMRustDIBuilderRef Builder, const char *Name, size_t NameLen, int64_t Value, bool IsUnsigned) { - return wrap(Builder->createEnumerator({Name, NameLen}, Value, IsUnsigned)); + return wrap(Builder->createEnumerator(StringRef(Name, NameLen), Value, IsUnsigned)); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef Elements, LLVMMetadataRef ClassTy, bool IsScoped) { return wrap(Builder->createEnumerationType( - unwrapDI(Scope), Name, unwrapDI(File), LineNumber, + unwrapDI(Scope), StringRef(Name, NameLen), + unwrapDI(File), LineNumber, SizeInBits, AlignInBits, DINodeArray(unwrapDI(Elements)), unwrapDI(ClassTy), "", IsScoped)); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef File, unsigned LineNumber, uint64_t SizeInBits, uint32_t AlignInBits, LLVMRustDIFlags Flags, LLVMMetadataRef Elements, - unsigned RunTimeLang, const char *UniqueId) { + unsigned RunTimeLang, const char *UniqueId, size_t UniqueIdLen) { return wrap(Builder->createUnionType( - unwrapDI(Scope), Name, unwrapDI(File), LineNumber, - SizeInBits, AlignInBits, fromRust(Flags), - DINodeArray(unwrapDI(Elements)), RunTimeLang, UniqueId)); + unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(File), + LineNumber, SizeInBits, AlignInBits, fromRust(Flags), + DINodeArray(unwrapDI(Elements)), RunTimeLang, + StringRef(UniqueId, UniqueIdLen))); } extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateTemplateTypeParameter( - LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name, + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, LLVMMetadataRef Ty, LLVMMetadataRef File, unsigned LineNo, unsigned ColumnNo) { return wrap(Builder->createTemplateTypeParameter( - unwrapDI(Scope), Name, unwrapDI(Ty))); + unwrapDI(Scope), StringRef(Name, NameLen), unwrapDI(Ty))); } -extern "C" LLVMMetadataRef -LLVMRustDIBuilderCreateNameSpace(LLVMRustDIBuilderRef Builder, - LLVMMetadataRef Scope, const char *Name, - LLVMMetadataRef File, unsigned LineNo) { +extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateNameSpace( + LLVMRustDIBuilderRef Builder, LLVMMetadataRef Scope, + const char *Name, size_t NameLen, bool ExportSymbols) { return wrap(Builder->createNameSpace( - unwrapDI(Scope), Name, - false // ExportSymbols (only relevant for C++ anonymous namespaces) - )); + unwrapDI(Scope), StringRef(Name, NameLen), ExportSymbols + )); } extern "C" void From e54a829b5795ff137e280628566e44edebe6f14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 6 Mar 2020 00:00:00 +0000 Subject: [PATCH 0907/1250] Avoid unnecessary interning of enum variant part id --- src/librustc_codegen_llvm/debuginfo/metadata.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 5cf3d74f243..46c4a511114 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -229,10 +229,7 @@ impl TypeMap<'ll, 'tcx> { &mut self, enum_type_id: UniqueTypeId, ) -> String { - let variant_part_type_id = - format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)); - self.unique_id_interner.intern(&variant_part_type_id); - variant_part_type_id + format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)) } } From 676b9bc477dfe58971b7df9df4e3a053bb187dee Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 3 Mar 2020 15:04:57 -0800 Subject: [PATCH 0908/1250] unix: Don't override existing SIGSEGV/BUS handlers Although `stack_overflow::init` runs very early in the process, even before `main`, there may already be signal handlers installed for things like the address sanitizer. In that case, just leave it alone, and don't bother trying to allocate our own signal stacks either. --- src/libstd/sys/unix/stack_overflow.rs | 28 +++++++++++++++++++-------- src/test/ui/sanitize/badfree.rs | 19 ++++++++++++++++++ 2 files changed, 39 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/sanitize/badfree.rs diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 528fe321efb..9e8be550755 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -13,6 +13,10 @@ impl Handler { pub unsafe fn new() -> Handler { make_handler() } + + fn null() -> Handler { + Handler { _data: crate::ptr::null_mut() } + } } impl Drop for Handler { @@ -108,13 +112,20 @@ mod imp { } static mut MAIN_ALTSTACK: *mut libc::c_void = ptr::null_mut(); + static mut NEED_ALTSTACK: bool = false; pub unsafe fn init() { let mut action: sigaction = mem::zeroed(); - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler as sighandler_t; - sigaction(SIGSEGV, &action, ptr::null_mut()); - sigaction(SIGBUS, &action, ptr::null_mut()); + for &signal in &[SIGSEGV, SIGBUS] { + sigaction(signal, ptr::null_mut(), &mut action); + // Configure our signal handler if one is not already set. + if action.sa_sigaction == SIG_DFL { + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + action.sa_sigaction = signal_handler as sighandler_t; + sigaction(signal, &action, ptr::null_mut()); + NEED_ALTSTACK = true; + } + } let handler = make_handler(); MAIN_ALTSTACK = handler._data; @@ -152,6 +163,9 @@ mod imp { } pub unsafe fn make_handler() -> Handler { + if !NEED_ALTSTACK { + return Handler::null(); + } let mut stack = mem::zeroed(); sigaltstack(ptr::null(), &mut stack); // Configure alternate signal stack, if one is not already set. @@ -160,7 +174,7 @@ mod imp { sigaltstack(&stack, ptr::null_mut()); Handler { _data: stack.ss_sp as *mut libc::c_void } } else { - Handler { _data: ptr::null_mut() } + Handler::null() } } @@ -191,14 +205,12 @@ mod imp { target_os = "openbsd" )))] mod imp { - use crate::ptr; - pub unsafe fn init() {} pub unsafe fn cleanup() {} pub unsafe fn make_handler() -> super::Handler { - super::Handler { _data: ptr::null_mut() } + super::Handler::null() } pub unsafe fn drop_handler(_handler: &mut super::Handler) {} diff --git a/src/test/ui/sanitize/badfree.rs b/src/test/ui/sanitize/badfree.rs new file mode 100644 index 00000000000..1ca082c8b47 --- /dev/null +++ b/src/test/ui/sanitize/badfree.rs @@ -0,0 +1,19 @@ +// needs-sanitizer-support +// only-x86_64 +// +// compile-flags: -Z sanitizer=address -O +// +// run-fail +// error-pattern: AddressSanitizer: SEGV + +use std::ffi::c_void; + +extern "C" { + fn free(ptr: *mut c_void); +} + +fn main() { + unsafe { + free(1 as *mut c_void); + } +} From ef98ec055ea30466a83f0b0efb2e40ebd3f89011 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Mon, 9 Mar 2020 16:50:46 +0900 Subject: [PATCH 0909/1250] Add FIXMEs --- src/test/ui/impl-trait/issue-57200.rs | 1 + src/test/ui/impl-trait/issue-57200.stderr | 2 +- src/test/ui/impl-trait/issue-57201.rs | 1 + src/test/ui/impl-trait/issue-57201.stderr | 2 +- src/test/ui/impl-trait/issue-60473.rs | 3 ++- src/test/ui/impl-trait/issue-60473.stderr | 2 +- src/test/ui/impl-trait/issue-67166.rs | 2 +- src/test/ui/impl-trait/issue-67166.stderr | 2 +- 8 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/test/ui/impl-trait/issue-57200.rs b/src/test/ui/impl-trait/issue-57200.rs index 9a7290b3b75..e0c71d1ac9a 100644 --- a/src/test/ui/impl-trait/issue-57200.rs +++ b/src/test/ui/impl-trait/issue-57200.rs @@ -1,4 +1,5 @@ // Regression test for #57200 +// FIXME: The error is temporary hack, we'll revisit here at some point. #![feature(impl_trait_in_bindings)] #![allow(incomplete_features)] diff --git a/src/test/ui/impl-trait/issue-57200.stderr b/src/test/ui/impl-trait/issue-57200.stderr index 42fd0045315..b44f332d58c 100644 --- a/src/test/ui/impl-trait/issue-57200.stderr +++ b/src/test/ui/impl-trait/issue-57200.stderr @@ -1,5 +1,5 @@ error: lifetimes in impl Trait types in bindings are not currently supported - --> $DIR/issue-57200.rs:10:12 + --> $DIR/issue-57200.rs:11:12 | LL | let f: impl Fn(&'a T) -> &'b T = |x| x; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/issue-57201.rs b/src/test/ui/impl-trait/issue-57201.rs index 79b19b52d20..c1a98d8897b 100644 --- a/src/test/ui/impl-trait/issue-57201.rs +++ b/src/test/ui/impl-trait/issue-57201.rs @@ -1,4 +1,5 @@ // Regression test for #57201 +// FIXME: The error is temporary hack, we'll revisit here at some point. #![feature(impl_trait_in_bindings)] #![allow(incomplete_features)] diff --git a/src/test/ui/impl-trait/issue-57201.stderr b/src/test/ui/impl-trait/issue-57201.stderr index 5defd15b6b5..462b17bf45e 100644 --- a/src/test/ui/impl-trait/issue-57201.stderr +++ b/src/test/ui/impl-trait/issue-57201.stderr @@ -1,5 +1,5 @@ error: lifetimes in impl Trait types in bindings are not currently supported - --> $DIR/issue-57201.rs:10:13 + --> $DIR/issue-57201.rs:11:13 | LL | let f: &impl Fn(&'a T) -> &'b T = &|x| x; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/impl-trait/issue-60473.rs b/src/test/ui/impl-trait/issue-60473.rs index 596d8a2dd74..50cf0c8c6d6 100644 --- a/src/test/ui/impl-trait/issue-60473.rs +++ b/src/test/ui/impl-trait/issue-60473.rs @@ -12,5 +12,6 @@ impl Trait for () { } fn main() { - let x: impl Trait = (); //~ ERROR: opaque type expands to a recursive type + let x: impl Trait = (); // FIXME: The error doesn't seem correct. + //~^ ERROR: opaque type expands to a recursive type } diff --git a/src/test/ui/impl-trait/issue-60473.stderr b/src/test/ui/impl-trait/issue-60473.stderr index 6a07f29727c..2d95be4e52c 100644 --- a/src/test/ui/impl-trait/issue-60473.stderr +++ b/src/test/ui/impl-trait/issue-60473.stderr @@ -1,7 +1,7 @@ error[E0720]: opaque type expands to a recursive type --> $DIR/issue-60473.rs:15:12 | -LL | let x: impl Trait = (); +LL | let x: impl Trait = (); // FIXME: The error doesn't seem correct. | ^^^^^^^^^^^^^ expands to a recursive type | = note: type resolves to itself diff --git a/src/test/ui/impl-trait/issue-67166.rs b/src/test/ui/impl-trait/issue-67166.rs index a877d4cfe3b..de7433a9bfc 100644 --- a/src/test/ui/impl-trait/issue-67166.rs +++ b/src/test/ui/impl-trait/issue-67166.rs @@ -4,7 +4,7 @@ #![allow(incomplete_features)] pub fn run() { - let _foo: Box = Box::new(()); + let _foo: Box = Box::new(()); // FIXME: The error doesn't much make sense. //~^ ERROR: opaque type expands to a recursive type } diff --git a/src/test/ui/impl-trait/issue-67166.stderr b/src/test/ui/impl-trait/issue-67166.stderr index abf30f67d5f..56cba3cff0b 100644 --- a/src/test/ui/impl-trait/issue-67166.stderr +++ b/src/test/ui/impl-trait/issue-67166.stderr @@ -1,7 +1,7 @@ error[E0720]: opaque type expands to a recursive type --> $DIR/issue-67166.rs:7:19 | -LL | let _foo: Box = Box::new(()); +LL | let _foo: Box = Box::new(()); // FIXME: The error doesn't much make sense. | ^^^^^^^^^^^^^^ expands to a recursive type | = note: type resolves to itself From c06fa0be82842b1b5c610e7d4243002305fa845f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 9 Mar 2020 09:31:15 +0100 Subject: [PATCH 0910/1250] clean up E0393 explanation --- src/librustc_error_codes/error_codes/E0393.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0393.md b/src/librustc_error_codes/error_codes/E0393.md index 7cce99401cf..3e853cf1b8a 100644 --- a/src/librustc_error_codes/error_codes/E0393.md +++ b/src/librustc_error_codes/error_codes/E0393.md @@ -1,5 +1,6 @@ A type parameter which references `Self` in its default value was not specified. -Example of erroneous code: + +Erroneous code example: ```compile_fail,E0393 trait A {} From 314da73797ede5da3ed658208aa31d6aab9cfbf0 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Mon, 9 Mar 2020 10:12:44 +0100 Subject: [PATCH 0911/1250] discrimant test must not be inlined! --- src/test/ui/consts/const_discriminant.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/consts/const_discriminant.rs b/src/test/ui/consts/const_discriminant.rs index c67be3c3713..55e2918c85f 100644 --- a/src/test/ui/consts/const_discriminant.rs +++ b/src/test/ui/consts/const_discriminant.rs @@ -4,6 +4,7 @@ use std::mem::{discriminant, Discriminant}; +#[inline(never)] fn identity(x: T) -> T { x } enum Test { From 925e9a2188dcd6e1988ceaa3ab8d64fcdb3d6d1e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 4 Mar 2020 23:37:52 +0300 Subject: [PATCH 0912/1250] rustc_parse: Use `Token::ident` where possible --- src/librustc_builtin_macros/format.rs | 65 ++++++++++++------------ src/librustc_expand/mbe/macro_parser.rs | 18 +++---- src/librustc_parse/parser/diagnostics.rs | 12 +++-- src/librustc_parse/parser/expr.rs | 50 +++++++++--------- src/librustc_parse/parser/item.rs | 19 +++---- src/librustc_parse/parser/mod.rs | 8 +-- src/librustc_parse/parser/path.rs | 6 +-- 7 files changed, 86 insertions(+), 92 deletions(-) diff --git a/src/librustc_builtin_macros/format.rs b/src/librustc_builtin_macros/format.rs index 1baec5eafe6..2883159a9f3 100644 --- a/src/librustc_builtin_macros/format.rs +++ b/src/librustc_builtin_macros/format.rs @@ -156,44 +156,43 @@ fn parse_args<'a>( if p.token == token::Eof { break; } // accept trailing commas - if p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq) { - named = true; - let name = if let token::Ident(name, _) = p.normalized_token.kind { + match p.token.ident() { + Some((ident, _)) if p.look_ahead(1, |t| *t == token::Eq) => { + named = true; p.bump(); - name - } else { - unreachable!(); - }; + p.expect(&token::Eq)?; + let e = p.parse_expr()?; + if let Some(prev) = names.get(&ident.name) { + ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", ident)) + .span_label(args[*prev].span, "previously here") + .span_label(e.span, "duplicate argument") + .emit(); + continue; + } - p.expect(&token::Eq)?; - let e = p.parse_expr()?; - if let Some(prev) = names.get(&name) { - ecx.struct_span_err(e.span, &format!("duplicate argument named `{}`", name)) - .span_label(args[*prev].span, "previously here") - .span_label(e.span, "duplicate argument") - .emit(); - continue; + // Resolve names into slots early. + // Since all the positional args are already seen at this point + // if the input is valid, we can simply append to the positional + // args. And remember the names. + let slot = args.len(); + names.insert(ident.name, slot); + args.push(e); } - - // Resolve names into slots early. - // Since all the positional args are already seen at this point - // if the input is valid, we can simply append to the positional - // args. And remember the names. - let slot = args.len(); - names.insert(name, slot); - args.push(e); - } else { - let e = p.parse_expr()?; - if named { - let mut err = ecx - .struct_span_err(e.span, "positional arguments cannot follow named arguments"); - err.span_label(e.span, "positional arguments must be before named arguments"); - for pos in names.values() { - err.span_label(args[*pos].span, "named argument"); + _ => { + let e = p.parse_expr()?; + if named { + let mut err = ecx.struct_span_err( + e.span, + "positional arguments cannot follow named arguments", + ); + err.span_label(e.span, "positional arguments must be before named arguments"); + for pos in names.values() { + err.span_label(args[*pos].span, "named argument"); + } + err.emit(); } - err.emit(); + args.push(e); } - args.push(e); } } Ok((fmtstr, args, names)) diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index d2a5c54aae4..efba3a8ccb1 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -750,15 +750,9 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na /// The token is an identifier, but not `_`. /// We prohibit passing `_` to macros expecting `ident` for now. -fn get_macro_name(token: &Token) -> Option<(Name, bool)> { - match token.kind { - token::Ident(name, is_raw) if name != kw::Underscore => Some((name, is_raw)), - token::Interpolated(ref nt) => match **nt { - token::NtIdent(ident, is_raw) if ident.name != kw::Underscore => { - Some((ident.name, is_raw)) - } - _ => None, - }, +fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> { + match token.ident() { + Some((ident, is_raw)) if ident.name != kw::Underscore => Some((ident, is_raw)), _ => None, } } @@ -783,7 +777,7 @@ fn may_begin_with(token: &Token, name: Name) -> bool { && !token.is_keyword(kw::Let) } sym::ty => token.can_begin_type(), - sym::ident => get_macro_name(token).is_some(), + sym::ident => get_macro_ident(token).is_some(), sym::literal => token.can_begin_literal_or_bool(), sym::vis => match token.kind { // The follow-set of :vis + "priv" keyword + interpolated @@ -888,9 +882,9 @@ fn parse_nt_inner<'a>(p: &mut Parser<'a>, sp: Span, name: Symbol) -> PResult<'a, sym::ty => token::NtTy(p.parse_ty()?), // this could be handled like a token, since it is one sym::ident => { - if let Some((name, is_raw)) = get_macro_name(&p.token) { + if let Some((ident, is_raw)) = get_macro_ident(&p.token) { p.bump(); - token::NtIdent(Ident::new(name, p.normalized_prev_token.span), is_raw) + token::NtIdent(ident, is_raw) } else { let token_str = pprust::token_to_string(&p.token); let msg = &format!("expected ident, found {}", &token_str); diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 6587e763d50..7c1df531ad1 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -192,17 +192,19 @@ impl<'a> Parser<'a> { TokenKind::CloseDelim(token::DelimToken::Brace), TokenKind::CloseDelim(token::DelimToken::Paren), ]; - if let token::Ident(name, false) = self.normalized_token.kind { - if Ident::new(name, self.normalized_token.span).is_raw_guess() - && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) + match self.token.ident() { + Some((ident, false)) + if ident.is_raw_guess() + && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) => { err.span_suggestion( - self.normalized_token.span, + ident.span, "you can escape reserved keywords to use them as identifiers", - format!("r#{}", name), + format!("r#{}", ident.name), Applicability::MaybeIncorrect, ); } + _ => {} } if let Some(token_descr) = super::token_descr_opt(&self.token) { err.span_label(self.token.span, format!("expected identifier, found {}", token_descr)); diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index e7c47b0be8e..66266aa5dc4 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -97,9 +97,10 @@ impl<'a> Parser<'a> { fn parse_expr_catch_underscore(&mut self) -> PResult<'a, P> { match self.parse_expr() { Ok(expr) => Ok(expr), - Err(mut err) => match self.normalized_token.kind { - token::Ident(name, false) - if name == kw::Underscore && self.look_ahead(1, |t| t == &token::Comma) => + Err(mut err) => match self.token.ident() { + Some((ident, false)) + if ident.name == kw::Underscore + && self.look_ahead(1, |t| t == &token::Comma) => { // Special-case handling of `foo(_, _, _)` err.emit(); @@ -331,21 +332,19 @@ impl<'a> Parser<'a> { /// /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively. fn check_assoc_op(&self) -> Option> { - Some(Spanned { - node: match (AssocOp::from_token(&self.token), &self.normalized_token.kind) { - (Some(op), _) => op, - (None, token::Ident(sym::and, false)) => { - self.error_bad_logical_op("and", "&&", "conjunction"); - AssocOp::LAnd - } - (None, token::Ident(sym::or, false)) => { - self.error_bad_logical_op("or", "||", "disjunction"); - AssocOp::LOr - } - _ => return None, - }, - span: self.normalized_token.span, - }) + let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) { + (Some(op), _) => (op, self.token.span), + (None, Some((ident, false))) if ident.name == sym::and => { + self.error_bad_logical_op("and", "&&", "conjunction"); + (AssocOp::LAnd, ident.span) + } + (None, Some((ident, false))) if ident.name == sym::or => { + self.error_bad_logical_op("or", "||", "disjunction"); + (AssocOp::LOr, ident.span) + } + _ => return None, + }; + Some(source_map::respan(span, op)) } /// Error on `and` and `or` suggesting `&&` and `||` respectively. @@ -1907,20 +1906,23 @@ impl<'a> Parser<'a> { /// Use in case of error after field-looking code: `S { foo: () with a }`. fn find_struct_error_after_field_looking_code(&self) -> Option { - if let token::Ident(name, _) = self.normalized_token.kind { - if !self.token.is_reserved_ident() && self.look_ahead(1, |t| *t == token::Colon) { - return Some(ast::Field { - ident: Ident::new(name, self.normalized_token.span), + match self.token.ident() { + Some((ident, is_raw)) + if (is_raw || !ident.is_reserved()) + && self.look_ahead(1, |t| *t == token::Colon) => + { + Some(ast::Field { + ident, span: self.token.span, expr: self.mk_expr_err(self.token.span), is_shorthand: false, attrs: AttrVec::new(), id: DUMMY_NODE_ID, is_placeholder: false, - }); + }) } + _ => None, } - None } fn recover_struct_comma_after_dotdot(&mut self, span: Span) { diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 01dd2f885ff..c1b38591f56 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -750,10 +750,10 @@ impl<'a> Parser<'a> { } fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { - match self.normalized_token.kind { - token::Ident(name @ kw::Underscore, false) => { + match self.token.ident() { + Some((ident, false)) if ident.name == kw::Underscore => { self.bump(); - Ok(Ident::new(name, self.normalized_prev_token.span)) + Ok(ident) } _ => self.parse_ident(), } @@ -1609,15 +1609,12 @@ impl<'a> Parser<'a> { /// Returns the parsed optional self parameter and whether a self shortcut was used. fn parse_self_param(&mut self) -> PResult<'a, Option> { // Extract an identifier *after* having confirmed that the token is one. - let expect_self_ident = |this: &mut Self| { - match this.normalized_token.kind { - // Preserve hygienic context. - token::Ident(name, _) => { - this.bump(); - Ident::new(name, this.normalized_prev_token.span) - } - _ => unreachable!(), + let expect_self_ident = |this: &mut Self| match this.token.ident() { + Some((ident, false)) => { + this.bump(); + ident } + _ => unreachable!(), }; // Is `self` `n` tokens ahead? let is_isolated_self = |this: &Self, n| { diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 74101fef8e3..0e3cee45dcd 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -480,9 +480,9 @@ impl<'a> Parser<'a> { } fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, ast::Ident> { - match self.normalized_token.kind { - token::Ident(name, _) => { - if self.token.is_reserved_ident() { + match self.token.ident() { + Some((ident, is_raw)) => { + if !is_raw && ident.is_reserved() { let mut err = self.expected_ident_found(); if recover { err.emit(); @@ -491,7 +491,7 @@ impl<'a> Parser<'a> { } } self.bump(); - Ok(Ident::new(name, self.normalized_prev_token.span)) + Ok(ident) } _ => Err(match self.prev_token.kind { TokenKind::DocComment(..) => { diff --git a/src/librustc_parse/parser/path.rs b/src/librustc_parse/parser/path.rs index 355b6429a74..f88b4fe6ff0 100644 --- a/src/librustc_parse/parser/path.rs +++ b/src/librustc_parse/parser/path.rs @@ -240,10 +240,10 @@ impl<'a> Parser<'a> { } pub(super) fn parse_path_segment_ident(&mut self) -> PResult<'a, Ident> { - match self.normalized_token.kind { - token::Ident(name, _) if name.is_path_segment_keyword() => { + match self.token.ident() { + Some((ident, false)) if ident.is_path_segment_keyword() => { self.bump(); - Ok(Ident::new(name, self.normalized_prev_token.span)) + Ok(ident) } _ => self.parse_ident(), } From f4a03c44d5859dea64dea7fdbaef5377f37c5dd2 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Thu, 5 Mar 2020 00:34:57 +0300 Subject: [PATCH 0913/1250] rustc_ast: Introduce `Token::uninterpolated_span` --- src/librustc_ast/attr/mod.rs | 4 ++++ src/librustc_ast/token.rs | 30 ++++++++++++++++++++++++++++++ src/librustc_parse/parser/expr.rs | 17 ++++++++++------- src/librustc_parse/parser/item.rs | 2 +- src/librustc_parse/parser/mod.rs | 6 +++--- src/librustc_parse/parser/ty.rs | 2 +- 6 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index 0638e8e6676..280994116c0 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -286,6 +286,10 @@ impl MetaItem { } impl AttrItem { + pub fn span(&self) -> Span { + self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span)) + } + pub fn meta(&self, span: Span) -> Option { Some(MetaItem { path: self.path.clone(), diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index a8a2c9b2fb3..c1564882cfe 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -328,6 +328,18 @@ impl Token { mem::replace(self, Token::dummy()) } + /// For interpolated tokens returns a span of the fragment to which the interpolated + /// token refers, for all other tokens this is just a regular span. + /// It is particularly important to use this for identifiers and lifetimes + /// for which spans affect name resolution. This also includes edition checks + /// for edition-specific keyword identifiers. + pub fn uninterpolated_span(&self) -> Span { + match &self.kind { + Interpolated(nt) => nt.span(), + _ => self.span, + } + } + pub fn is_op(&self) -> bool { match self.kind { OpenDelim(..) | CloseDelim(..) | Literal(..) | DocComment(..) | Ident(..) @@ -714,6 +726,24 @@ pub enum Nonterminal { #[cfg(target_arch = "x86_64")] rustc_data_structures::static_assert_size!(Nonterminal, 40); +impl Nonterminal { + fn span(&self) -> Span { + match self { + NtItem(item) => item.span, + NtBlock(block) => block.span, + NtStmt(stmt) => stmt.span, + NtPat(pat) => pat.span, + NtExpr(expr) | NtLiteral(expr) => expr.span, + NtTy(ty) => ty.span, + NtIdent(ident, _) | NtLifetime(ident) => ident.span, + NtMeta(attr_item) => attr_item.span(), + NtPath(path) => path.span, + NtVis(vis) => vis.span, + NtTT(tt) => tt.span(), + } + } +} + impl PartialEq for Nonterminal { fn eq(&self, rhs: &Self) -> bool { match (self, rhs) { diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 66266aa5dc4..743fc3a4efa 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -849,7 +849,7 @@ impl<'a> Parser<'a> { /// Assuming we have just parsed `.`, continue parsing into an expression. fn parse_dot_suffix(&mut self, self_arg: P, lo: Span) -> PResult<'a, P> { - if self.normalized_token.span.rust_2018() && self.eat_keyword(kw::Await) { + if self.token.uninterpolated_span().rust_2018() && self.eat_keyword(kw::Await) { return self.mk_await_expr(self_arg, lo); } @@ -963,7 +963,7 @@ impl<'a> Parser<'a> { // | ^ expected expression self.bump(); Ok(self.mk_expr_err(self.token.span)) - } else if self.normalized_token.span.rust_2018() { + } else if self.token.uninterpolated_span().rust_2018() { // `Span::rust_2018()` is somewhat expensive; don't get it repeatedly. if self.check_keyword(kw::Async) { if self.is_async_block() { @@ -1396,11 +1396,14 @@ impl<'a> Parser<'a> { let movability = if self.eat_keyword(kw::Static) { Movability::Static } else { Movability::Movable }; - let asyncness = - if self.normalized_token.span.rust_2018() { self.parse_asyncness() } else { Async::No }; - if asyncness.is_async() { + let asyncness = if self.token.uninterpolated_span().rust_2018() { + self.parse_asyncness() + } else { + Async::No + }; + if let Async::Yes { span, .. } = asyncness { // Feature-gate `async ||` closures. - self.sess.gated_spans.gate(sym::async_closure, self.normalized_prev_token.span); + self.sess.gated_spans.gate(sym::async_closure, span); } let capture_clause = self.parse_capture_clause(); @@ -1756,7 +1759,7 @@ impl<'a> Parser<'a> { fn is_try_block(&self) -> bool { self.token.is_keyword(kw::Try) && self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) && - self.normalized_token.span.rust_2018() && + self.token.uninterpolated_span().rust_2018() && // Prevent `while try {} {}`, `if try {} {} else {}`, etc. !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) } diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index c1b38591f56..232ecd6fdae 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -574,7 +574,7 @@ impl<'a> Parser<'a> { && self.look_ahead(1, |t| t.is_non_raw_ident_where(|i| i.name != kw::As)) { self.bump(); // `default` - Defaultness::Default(self.normalized_prev_token.span) + Defaultness::Default(self.prev_token.uninterpolated_span()) } else { Defaultness::Final } diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 0e3cee45dcd..252a80431ac 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -884,7 +884,7 @@ impl<'a> Parser<'a> { /// Parses asyncness: `async` or nothing. fn parse_asyncness(&mut self) -> Async { if self.eat_keyword(kw::Async) { - let span = self.normalized_prev_token.span; + let span = self.prev_token.uninterpolated_span(); Async::Yes { span, closure_id: DUMMY_NODE_ID, return_impl_trait_id: DUMMY_NODE_ID } } else { Async::No @@ -894,7 +894,7 @@ impl<'a> Parser<'a> { /// Parses unsafety: `unsafe` or nothing. fn parse_unsafety(&mut self) -> Unsafe { if self.eat_keyword(kw::Unsafe) { - Unsafe::Yes(self.normalized_prev_token.span) + Unsafe::Yes(self.prev_token.uninterpolated_span()) } else { Unsafe::No } @@ -903,7 +903,7 @@ impl<'a> Parser<'a> { /// Parses constness: `const` or nothing. fn parse_constness(&mut self) -> Const { if self.eat_keyword(kw::Const) { - Const::Yes(self.normalized_prev_token.span) + Const::Yes(self.prev_token.uninterpolated_span()) } else { Const::No } diff --git a/src/librustc_parse/parser/ty.rs b/src/librustc_parse/parser/ty.rs index c4469331b66..16adf5c05a4 100644 --- a/src/librustc_parse/parser/ty.rs +++ b/src/librustc_parse/parser/ty.rs @@ -323,7 +323,7 @@ impl<'a> Parser<'a> { /// Is a `dyn B0 + ... + Bn` type allowed here? fn is_explicit_dyn_type(&mut self) -> bool { self.check_keyword(kw::Dyn) - && (self.normalized_token.span.rust_2018() + && (self.token.uninterpolated_span().rust_2018() || self.look_ahead(1, |t| { t.can_begin_bound() && !can_continue_type_after_non_fn_ident(t) })) From 43b27df5b211bc0fae74f34834ae84d17215c5ac Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 14:37:38 +0300 Subject: [PATCH 0914/1250] rustc_ast: Introduce `Token::uninterpolate` --- src/librustc_ast/token.rs | 20 ++++++++++++++++++-- src/librustc_parse/parser/expr.rs | 4 ++-- src/librustc_parse/parser/item.rs | 4 ++-- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index c1564882cfe..b80694ab6de 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -14,8 +14,8 @@ use rustc_macros::HashStable_Generic; use rustc_span::symbol::kw; use rustc_span::symbol::Symbol; use rustc_span::{self, Span, DUMMY_SP}; -use std::fmt; -use std::mem; +use std::borrow::Cow; +use std::{fmt, mem}; #[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] #[derive(HashStable_Generic)] @@ -457,6 +457,22 @@ impl Token { } } + // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token + // into the regular identifier or lifetime token it refers to, + // otherwise returns the original token. + pub fn uninterpolate(&self) -> Cow<'_, Token> { + match &self.kind { + Interpolated(nt) => match **nt { + NtIdent(ident, is_raw) => { + Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)) + } + NtLifetime(ident) => Cow::Owned(Token::new(Lifetime(ident.name), ident.span)), + _ => Cow::Borrowed(self), + }, + _ => Cow::Borrowed(self), + } + } + /// Returns an identifier if this token is an identifier. pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> { match self.kind { diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 743fc3a4efa..f7cfb028a7a 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -435,7 +435,7 @@ impl<'a> Parser<'a> { let attrs = self.parse_or_use_outer_attributes(attrs)?; let lo = self.token.span; // Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr() - let (hi, ex) = match self.normalized_token.kind { + let (hi, ex) = match self.token.uninterpolate().kind { token::Not => self.parse_unary_expr(lo, UnOp::Not), // `!expr` token::Tilde => self.recover_tilde_expr(lo), // `~expr` token::BinOp(token::Minus) => self.parse_unary_expr(lo, UnOp::Neg), // `-expr` @@ -755,7 +755,7 @@ impl<'a> Parser<'a> { } fn parse_dot_suffix_expr(&mut self, lo: Span, base: P) -> PResult<'a, P> { - match self.normalized_token.kind { + match self.token.uninterpolate().kind { token::Ident(..) => self.parse_dot_suffix(base, lo), token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix)) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 232ecd6fdae..08d71f03976 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1544,7 +1544,7 @@ impl<'a> Parser<'a> { let is_name_required = match self.token.kind { token::DotDotDot => false, - _ => req_name(self.normalized_token.span.edition()), + _ => req_name(self.token.uninterpolate().span.edition()), }; let (pat, ty) = if is_name_required || self.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); @@ -1648,7 +1648,7 @@ impl<'a> Parser<'a> { // Only a limited set of initial token sequences is considered `self` parameters; anything // else is parsed as a normal function parameter list, so some lookahead is required. let eself_lo = self.token.span; - let (eself, eself_ident, eself_hi) = match self.normalized_token.kind { + let (eself, eself_ident, eself_hi) = match self.token.uninterpolate().kind { token::BinOp(token::And) => { let eself = if is_isolated_self(self, 1) { // `&self` From 5d7f67d3b109e95fb0dca8f773a2146db4eb4a93 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 16:34:29 +0300 Subject: [PATCH 0915/1250] rustc_parse: Remove `Parser::normalized(_prev)_token` --- src/librustc_parse/lib.rs | 5 ++-- src/librustc_parse/parser/mod.rs | 42 ++++---------------------------- 2 files changed, 7 insertions(+), 40 deletions(-) diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 25f9f8fd3ad..10d524776a1 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -4,7 +4,7 @@ #![feature(crate_visibility_modifier)] use rustc_ast::ast; -use rustc_ast::token::{self, Nonterminal, Token}; +use rustc_ast::token::{self, Nonterminal}; use rustc_ast::tokenstream::{self, TokenStream, TokenTree}; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; @@ -171,8 +171,7 @@ fn maybe_source_file_to_parser( let mut parser = stream_to_parser(sess, stream, None); parser.unclosed_delims = unclosed_delims; if parser.token == token::Eof { - let span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); - parser.set_token(Token::new(token::Eof, span)); + parser.token.span = Span::new(end_pos, end_pos, parser.token.span.ctxt()); } Ok(parser) diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 252a80431ac..9376c7c1c72 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -88,21 +88,10 @@ macro_rules! maybe_recover_from_interpolated_ty_qpath { #[derive(Clone)] pub struct Parser<'a> { pub sess: &'a ParseSess, - /// The current non-normalized token. + /// The current token. pub token: Token, - /// The current normalized token. - /// "Normalized" means that some interpolated tokens - /// (`$i: ident` and `$l: lifetime` meta-variables) are replaced - /// with non-interpolated identifier and lifetime tokens they refer to. - /// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically, - /// this also includes edition checks for edition-specific keyword identifiers. - pub normalized_token: Token, - /// The previous non-normalized token. + /// The previous token. pub prev_token: Token, - /// The previous normalized token. - /// Use this if you need to check for `token::Ident` or `token::Lifetime` specifically, - /// this also includes edition checks for edition-specific keyword identifiers. - pub normalized_prev_token: Token, restrictions: Restrictions, /// Used to determine the path to externally loaded source files. pub(super) directory: Directory, @@ -374,9 +363,7 @@ impl<'a> Parser<'a> { let mut parser = Parser { sess, token: Token::dummy(), - normalized_token: Token::dummy(), prev_token: Token::dummy(), - normalized_prev_token: Token::dummy(), restrictions: Restrictions::empty(), recurse_into_file_modules, directory: Directory { @@ -609,7 +596,7 @@ impl<'a> Parser<'a> { Some((first, second)) if first == expected => { let first_span = self.sess.source_map().start_point(self.token.span); let second_span = self.token.span.with_lo(first_span.hi()); - self.set_token(Token::new(first, first_span)); + self.token = Token::new(first, first_span); self.bump_with(Token::new(second, second_span)); true } @@ -817,23 +804,6 @@ impl<'a> Parser<'a> { self.parse_delim_comma_seq(token::Paren, f) } - // Interpolated identifier (`$i: ident`) and lifetime (`$l: lifetime`) - // tokens are replaced with usual identifier and lifetime tokens, - // so the former are never encountered during normal parsing. - crate fn set_token(&mut self, token: Token) { - self.token = token; - self.normalized_token = match &self.token.kind { - token::Interpolated(nt) => match **nt { - token::NtIdent(ident, is_raw) => { - Token::new(token::Ident(ident.name, is_raw), ident.span) - } - token::NtLifetime(ident) => Token::new(token::Lifetime(ident.name), ident.span), - _ => self.token.clone(), - }, - _ => self.token.clone(), - } - } - /// Advance the parser by one token using provided token as the next one. fn bump_with(&mut self, next_token: Token) { // Bumping after EOF is a bad sign, usually an infinite loop. @@ -843,9 +813,7 @@ impl<'a> Parser<'a> { } // Update the current and previous tokens. - self.prev_token = self.token.take(); - self.normalized_prev_token = self.normalized_token.take(); - self.set_token(next_token); + self.prev_token = mem::replace(&mut self.token, next_token); // Diagnostics. self.expected_tokens.clear(); @@ -1005,7 +973,7 @@ impl<'a> Parser<'a> { &mut self.token_cursor.frame, self.token_cursor.stack.pop().unwrap(), ); - self.set_token(Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close)); + self.token = Token::new(TokenKind::CloseDelim(frame.delim), frame.span.close); self.bump(); TokenTree::Delimited(frame.span, frame.delim, frame.tree_cursor.stream) } From 9be233cbfe134f032ed2d50f7cc66e901bbe3f6f Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 7 Mar 2020 15:58:27 +0300 Subject: [PATCH 0916/1250] Use `Token::uninterpolate` in couple more places matching on `(Nt)Ident` --- src/librustc_ast/attr/mod.rs | 5 ++--- src/librustc_ast/token.rs | 32 +++++++++++-------------------- src/librustc_ast/tokenstream.rs | 7 +++++++ src/librustc_ast/util/literal.rs | 15 ++++----------- src/librustc_parse/parser/expr.rs | 3 +-- src/librustc_parse/parser/item.rs | 2 ++ src/librustc_parse/parser/pat.rs | 2 +- 7 files changed, 28 insertions(+), 38 deletions(-) diff --git a/src/librustc_ast/attr/mod.rs b/src/librustc_ast/attr/mod.rs index 280994116c0..52a59e82ae2 100644 --- a/src/librustc_ast/attr/mod.rs +++ b/src/librustc_ast/attr/mod.rs @@ -441,7 +441,7 @@ impl MetaItem { I: Iterator, { // FIXME: Share code with `parse_path`. - let path = match tokens.next() { + let path = match tokens.next().map(TokenTree::uninterpolate) { Some(TokenTree::Token(Token { kind: kind @ token::Ident(..), span })) | Some(TokenTree::Token(Token { kind: kind @ token::ModSep, span })) => 'arm: { let mut segments = if let token::Ident(name, _) = kind { @@ -457,7 +457,7 @@ impl MetaItem { }; loop { if let Some(TokenTree::Token(Token { kind: token::Ident(name, _), span })) = - tokens.next() + tokens.next().map(TokenTree::uninterpolate) { segments.push(PathSegment::from_ident(Ident::new(name, span))); } else { @@ -474,7 +474,6 @@ impl MetaItem { Path { span, segments } } Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt { - token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident), token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span), token::Nonterminal::NtPath(ref path) => path.clone(), _ => return None, diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index b80694ab6de..b022d969dec 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -357,7 +357,7 @@ impl Token { /// Returns `true` if the token can appear at the start of an expression. pub fn can_begin_expr(&self) -> bool { - match self.kind { + match self.uninterpolate().kind { Ident(name, is_raw) => ident_can_begin_expr(name, self.span, is_raw), // value name or keyword OpenDelim(..) | // tuple, array or block @@ -375,12 +375,10 @@ impl Token { Lifetime(..) | // labeled loop Pound => true, // expression attributes Interpolated(ref nt) => match **nt { - NtIdent(ident, is_raw) => ident_can_begin_expr(ident.name, ident.span, is_raw), NtLiteral(..) | NtExpr(..) | NtBlock(..) | - NtPath(..) | - NtLifetime(..) => true, + NtPath(..) => true, _ => false, }, _ => false, @@ -389,7 +387,7 @@ impl Token { /// Returns `true` if the token can appear at the start of a type. pub fn can_begin_type(&self) -> bool { - match self.kind { + match self.uninterpolate().kind { Ident(name, is_raw) => ident_can_begin_type(name, self.span, is_raw), // type name or keyword OpenDelim(Paren) | // tuple @@ -403,8 +401,7 @@ impl Token { Lt | BinOp(Shl) | // associated path ModSep => true, // global path Interpolated(ref nt) => match **nt { - NtIdent(ident, is_raw) => ident_can_begin_type(ident.name, ident.span, is_raw), - NtTy(..) | NtPath(..) | NtLifetime(..) => true, + NtTy(..) | NtPath(..) => true, _ => false, }, _ => false, @@ -445,11 +442,10 @@ impl Token { /// /// Keep this in sync with `Lit::from_token`. pub fn can_begin_literal_or_bool(&self) -> bool { - match self.kind { + match self.uninterpolate().kind { Literal(..) | BinOp(Minus) => true, Ident(name, false) if name.is_bool_lit() => true, Interpolated(ref nt) => match &**nt { - NtIdent(ident, false) if ident.name.is_bool_lit() => true, NtExpr(e) | NtLiteral(e) => matches!(e.kind, ast::ExprKind::Lit(_)), _ => false, }, @@ -475,24 +471,18 @@ impl Token { /// Returns an identifier if this token is an identifier. pub fn ident(&self) -> Option<(ast::Ident, /* is_raw */ bool)> { - match self.kind { - Ident(name, is_raw) => Some((ast::Ident::new(name, self.span), is_raw)), - Interpolated(ref nt) => match **nt { - NtIdent(ident, is_raw) => Some((ident, is_raw)), - _ => None, - }, + let token = self.uninterpolate(); + match token.kind { + Ident(name, is_raw) => Some((ast::Ident::new(name, token.span), is_raw)), _ => None, } } /// Returns a lifetime identifier if this token is a lifetime. pub fn lifetime(&self) -> Option { - match self.kind { - Lifetime(name) => Some(ast::Ident::new(name, self.span)), - Interpolated(ref nt) => match **nt { - NtLifetime(ident) => Some(ident), - _ => None, - }, + let token = self.uninterpolate(); + match token.kind { + Lifetime(name) => Some(ast::Ident::new(name, token.span)), _ => None, } } diff --git a/src/librustc_ast/tokenstream.rs b/src/librustc_ast/tokenstream.rs index 03e8fff247b..916a5ff6f46 100644 --- a/src/librustc_ast/tokenstream.rs +++ b/src/librustc_ast/tokenstream.rs @@ -116,6 +116,13 @@ impl TokenTree { pub fn close_tt(span: DelimSpan, delim: DelimToken) -> TokenTree { TokenTree::token(token::CloseDelim(delim), span.close) } + + pub fn uninterpolate(self) -> TokenTree { + match self { + TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()), + tt => tt, + } + } } impl HashStable for TokenStream diff --git a/src/librustc_ast/util/literal.rs b/src/librustc_ast/util/literal.rs index ecf17efc4e0..d1757394f3a 100644 --- a/src/librustc_ast/util/literal.rs +++ b/src/librustc_ast/util/literal.rs @@ -191,23 +191,16 @@ impl Lit { /// /// Keep this in sync with `Token::can_begin_literal_or_bool`. pub fn from_token(token: &Token) -> Result { - let lit = match token.kind { + let lit = match token.uninterpolate().kind { token::Ident(name, false) if name.is_bool_lit() => { token::Lit::new(token::Bool, name, None) } token::Literal(lit) => lit, token::Interpolated(ref nt) => { - match &**nt { - token::NtIdent(ident, false) if ident.name.is_bool_lit() => { - let lit = token::Lit::new(token::Bool, ident.name, None); - return Lit::from_lit_token(lit, ident.span); + if let token::NtExpr(expr) | token::NtLiteral(expr) = &**nt { + if let ast::ExprKind::Lit(lit) = &expr.kind { + return Ok(lit.clone()); } - token::NtExpr(expr) | token::NtLiteral(expr) => { - if let ast::ExprKind::Lit(lit) = &expr.kind { - return Ok(lit.clone()); - } - } - _ => {} } return Err(LitError::NotLiteral); } diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index f7cfb028a7a..d28b9cd9682 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -50,7 +50,6 @@ macro_rules! maybe_whole_expr { AttrVec::new(), )); } - // N.B., `NtIdent(ident)` is normalized to `Ident` in `fn bump`. _ => {} }; } @@ -482,7 +481,7 @@ impl<'a> Parser<'a> { } fn is_mistaken_not_ident_negation(&self) -> bool { - let token_cannot_continue_expr = |t: &Token| match t.kind { + let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind { // These tokens can start an expression after `!`, but // can't continue an expression after an ident token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 08d71f03976..bf612bfc0e4 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1544,6 +1544,8 @@ impl<'a> Parser<'a> { let is_name_required = match self.token.kind { token::DotDotDot => false, + // FIXME: Consider using interpolated token for this edition check, + // it should match the intent of edition hygiene better. _ => req_name(self.token.uninterpolate().span.edition()), }; let (pat, ty) = if is_name_required || self.is_named_param() { diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs index 4c041fd669d..f52a91ff598 100644 --- a/src/librustc_parse/parser/pat.rs +++ b/src/librustc_parse/parser/pat.rs @@ -151,7 +151,7 @@ impl<'a> Parser<'a> { /// Note that there are more tokens such as `@` for which we know that the `|` /// is an illegal parse. However, the user's intent is less clear in that case. fn recover_trailing_vert(&mut self, lo: Option) -> bool { - let is_end_ahead = self.look_ahead(1, |token| match &token.kind { + let is_end_ahead = self.look_ahead(1, |token| match &token.uninterpolate().kind { token::FatArrow // e.g. `a | => 0,`. | token::Ident(kw::If, false) // e.g. `a | if expr`. | token::Eq // e.g. `let a | = 0`. From 8a8870fbae1bf601ac4d29d6c0c407a352caea57 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 10:45:20 +0100 Subject: [PATCH 0917/1250] miri: add machine hook for Abort terminator --- src/librustc_mir/interpret/machine.rs | 5 +++++ src/librustc_mir/interpret/terminator.rs | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 6615cc608fb..64a34fc7dd9 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -170,6 +170,11 @@ pub trait Machine<'mir, 'tcx>: Sized { unwind: Option, ) -> InterpResult<'tcx>; + /// Called to evaluate `Abort` MIR terminator. + fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + throw_unsup_format!("aborting execution is not supported"); + } + /// Called for all binary operations where the LHS has pointer type. /// /// Returns a (value, overflowed) pair if the operation succeeded diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index 85fd502c69c..95d5276565f 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -99,6 +99,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } } + Abort => { + M::abort(self)?; + } + // When we encounter Resume, we've finished unwinding // cleanup for the current stack frame. We pop it in order // to continue unwinding the next frame @@ -118,8 +122,9 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | FalseEdges { .. } | FalseUnwind { .. } | Yield { .. } - | GeneratorDrop - | Abort => bug!("{:#?} should have been eliminated by MIR pass", terminator.kind), + | GeneratorDrop => { + bug!("{:#?} should have been eliminated by MIR pass", terminator.kind) + } } Ok(()) From 7a30bb1676690596f73659d18959877d993510ae Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Mar 2020 12:42:33 +0300 Subject: [PATCH 0918/1250] Address review comments --- src/librustc_ast/token.rs | 19 ++++++++++++++----- src/librustc_expand/mbe/macro_parser.rs | 5 +---- src/librustc_parse/parser/expr.rs | 13 ++++++------- src/librustc_parse/parser/item.rs | 2 +- 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index b022d969dec..b67b7d346f7 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -225,8 +225,15 @@ pub enum TokenKind { /* Literals */ Literal(Lit), - /* Name components */ + /// Identifier token. + /// Do not forget about `NtIdent` when you want to match on identifiers. + /// It's recommended to use `Token::(ident,uninterpolate,uninterpolated_span)` to + /// treat regular and interpolated identifiers in the same way. Ident(ast::Name, /* is_raw */ bool), + /// Lifetime identifier token. + /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. + /// It's recommended to use `Token::(lifetime,uninterpolate,uninterpolated_span)` to + /// treat regular and interpolated lifetime identifiers in the same way. Lifetime(ast::Name), Interpolated(Lrc), @@ -328,11 +335,12 @@ impl Token { mem::replace(self, Token::dummy()) } - /// For interpolated tokens returns a span of the fragment to which the interpolated - /// token refers, for all other tokens this is just a regular span. + /// For interpolated tokens, returns a span of the fragment to which the interpolated + /// token refers. For all other tokens this is just a regular span. /// It is particularly important to use this for identifiers and lifetimes - /// for which spans affect name resolution. This also includes edition checks - /// for edition-specific keyword identifiers. + /// for which spans affect name resolution and edition checks. + /// Note that keywords are also identifiers, so they should use this + /// if they keep spans or perform edition checks. pub fn uninterpolated_span(&self) -> Span { match &self.kind { Interpolated(nt) => nt.span(), @@ -453,6 +461,7 @@ impl Token { } } + // A convenience function for matching on identifiers during parsing. // Turns interpolated identifier (`$i: ident`) or lifetime (`$l: lifetime`) token // into the regular identifier or lifetime token it refers to, // otherwise returns the original token. diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index efba3a8ccb1..6d4d7f5b4f3 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -751,10 +751,7 @@ pub(super) fn parse_tt(parser: &mut Cow<'_, Parser<'_>>, ms: &[TokenTree]) -> Na /// The token is an identifier, but not `_`. /// We prohibit passing `_` to macros expecting `ident` for now. fn get_macro_ident(token: &Token) -> Option<(Ident, bool)> { - match token.ident() { - Some((ident, is_raw)) if ident.name != kw::Underscore => Some((ident, is_raw)), - _ => None, - } + token.ident().filter(|(ident, _)| ident.name != kw::Underscore) } /// Checks whether a non-terminal may begin with a particular token. diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index d28b9cd9682..bfca9f07f05 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -97,9 +97,8 @@ impl<'a> Parser<'a> { match self.parse_expr() { Ok(expr) => Ok(expr), Err(mut err) => match self.token.ident() { - Some((ident, false)) - if ident.name == kw::Underscore - && self.look_ahead(1, |t| t == &token::Comma) => + Some((Ident { name: kw::Underscore, .. }, false)) + if self.look_ahead(1, |t| t == &token::Comma) => { // Special-case handling of `foo(_, _, _)` err.emit(); @@ -333,13 +332,13 @@ impl<'a> Parser<'a> { fn check_assoc_op(&self) -> Option> { let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) { (Some(op), _) => (op, self.token.span), - (None, Some((ident, false))) if ident.name == sym::and => { + (None, Some((Ident { name: sym::and, span }, false))) => { self.error_bad_logical_op("and", "&&", "conjunction"); - (AssocOp::LAnd, ident.span) + (AssocOp::LAnd, span) } - (None, Some((ident, false))) if ident.name == sym::or => { + (None, Some((Ident { name: sym::or, span }, false))) => { self.error_bad_logical_op("or", "||", "disjunction"); - (AssocOp::LOr, ident.span) + (AssocOp::LOr, span) } _ => return None, }; diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index bf612bfc0e4..126686c8def 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -751,7 +751,7 @@ impl<'a> Parser<'a> { fn parse_ident_or_underscore(&mut self) -> PResult<'a, ast::Ident> { match self.token.ident() { - Some((ident, false)) if ident.name == kw::Underscore => { + Some((ident @ Ident { name: kw::Underscore, .. }, false)) => { self.bump(); Ok(ident) } From 1a9fc18e830dc57731e2976edb5c5f0fabc5019c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 11:16:23 +0100 Subject: [PATCH 0919/1250] panic_bounds_check: use caller_location, like PanicFnLangItem --- src/libcore/panicking.rs | 18 ++++++++++++++++++ src/librustc_codegen_ssa/mir/block.rs | 6 +++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 61b764f2d62..d58a7cfec95 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -52,6 +52,24 @@ pub fn panic(expr: &str) -> ! { panic_fmt(fmt::Arguments::new_v1(&[expr], &[]), Location::caller()) } +#[cfg(not(bootstrap))] +#[cold] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +#[track_caller] +#[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access +fn panic_bounds_check(index: usize, len: usize) -> ! { + if cfg!(feature = "panic_immediate_abort") { + unsafe { super::intrinsics::abort() } + } + + panic_fmt( + format_args!("index out of bounds: the len is {} but the index is {}", len, index), + Location::caller(), + ) +} + +// For bootstrap, we need a variant with the old argument order. +#[cfg(bootstrap)] #[cold] #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index a1b54607b80..f22c0216a78 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -415,11 +415,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); - (lang_items::PanicBoundsCheckFnLangItem, vec![location, index, len]) + // It's `fn panic_bounds_check(index: usize, len: usize)`, and + // `#[track_caller]` adds an implicit third argument. + (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location]) } _ => { let msg_str = Symbol::intern(msg.description()); let msg = bx.const_str(msg_str); + // It's `pub fn panic(expr: &str)`, with the wide reference being passed + // as two arguments, and `#[track_caller]` adds an implicit third argument. (lang_items::PanicFnLangItem, vec![msg.0, msg.1, location]) } }; From b974d6fc306d5847ad4b8bb48a99e6ca234cb6d1 Mon Sep 17 00:00:00 2001 From: Matthew Kuo Date: Sat, 7 Mar 2020 22:01:11 -0600 Subject: [PATCH 0920/1250] test(patterns): add borrowck tests for combination of pattern features Adds borrowck tests for the following features: - bindings_after_at - or_patterns - slice_patterns - box_patterns --- ...or-patterns-slice-patterns-box-patterns.rs | 224 ++++++++++++++++++ ...atterns-slice-patterns-box-patterns.stderr | 208 ++++++++++++++++ 2 files changed, 432 insertions(+) create mode 100644 src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs create mode 100644 src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs new file mode 100644 index 00000000000..b67d494866b --- /dev/null +++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs @@ -0,0 +1,224 @@ +// Tests using a combination of pattern features has the expected borrow checking behavior +#![feature(bindings_after_at)] +#![feature(or_patterns)] +#![feature(box_patterns)] + +#![feature(move_ref_pattern)] + +enum Test { + Foo, + Bar, + _Baz, +} + +// bindings_after_at + slice_patterns + +fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) { + match x { + a @ [.., _] => (), + _ => (), + }; + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_slice_patterns_borrows_binding_mut(mut x: [String; 4]) { + let r = match x { + ref mut foo @ [.., _] => Some(foo), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_slice_mut1(mut x: [String; 4]) { + let r = match x { + ref foo @ [.., ref mut bar] => (), + //~^ ERROR cannot borrow + _ => (), + }; + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_slice_mut2(mut x: [String; 4]) { + let r = match x { + [ref foo @ .., ref bar] => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_borrows_both(mut x: [String; 4]) { + let r = match x { + ref foo @ [.., ref bar] => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + or_patterns + +fn bindings_after_at_or_patterns_move(x: Option) { + match x { + foo @ Some(Test::Foo | Test::Bar) => (), + _ => (), + } + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_or_patterns_borrows(mut x: Option) { + let r = match x { + ref foo @ Some(Test::Foo | Test::Bar) => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_or_patterns_borrows_mut(mut x: Option) { + let r = match x { + ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + box_patterns + +fn bindings_after_at_box_patterns_borrows_both(mut x: Option>) { + let r = match x { + ref foo @ Some(box ref s) => Some(foo), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_box_patterns_borrows_mut(mut x: Option>) { + match x { + ref foo @ Some(box ref mut s) => (), + //~^ ERROR cannot borrow + _ => (), + }; +} + +// bindings_after_at + slice_patterns + or_patterns + +fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option; 4]) { + match x { + a @ [.., Some(Test::Foo | Test::Bar)] => (), + _ => (), + }; + + &x; + //~^ ERROR borrow of moved value +} + +fn bindings_after_at_slice_patterns_or_patterns_borrows_binding(mut x: [Option; 4]) { + let r = match x { + ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_borrows_slice(mut x: [Option; 4]) { + let r = match x { + ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + slice_patterns + box_patterns + +fn bindings_after_at_slice_patterns_box_patterns_borrows(mut x: [Option>; 4]) { + let r = match x { + [_, ref a @ Some(box ref b), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +// bindings_after_at + slice_patterns + or_patterns + box_patterns + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows( + mut x: [Option>; 4] +) { + let r = match x { + [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_mut( + mut x: [Option>; 4] +) { + let r = match x { + [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn bindings_after_at_slice_patterns_or_patterns_box_patterns_borrows_binding( + mut x: [Option>; 4] +) { + let r = match x { + ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + _ => None, + }; + + &mut x; + //~^ ERROR cannot borrow + + drop(r); +} + +fn main() {} diff --git a/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr new file mode 100644 index 00000000000..35ed2763c2b --- /dev/null +++ b/src/test/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr @@ -0,0 +1,208 @@ +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:40:9 + | +LL | ref foo @ [.., ref mut bar] => (), + | -------^^^^^^^^-----------^ + | | | + | | mutable borrow, by `bar`, occurs here + | immutable borrow, by `foo`, occurs here + +error: cannot borrow value as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:124:9 + | +LL | ref foo @ Some(box ref mut s) => (), + | -------^^^^^^^^^^^^---------^ + | | | + | | mutable borrow, by `s`, occurs here + | immutable borrow, by `foo`, occurs here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:22:5 + | +LL | fn bindings_after_at_slice_patterns_move_binding(x: [String; 4]) { + | - move occurs because `x` has type `[std::string::String; 4]`, which does not implement the `Copy` trait +LL | match x { +LL | a @ [.., _] => (), + | ----------- value moved here +... +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:32:5 + | +LL | ref mut foo @ [.., _] => Some(foo), + | --------------------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:54:5 + | +LL | [ref foo @ .., ref bar] => Some(foo), + | ------------ immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:66:5 + | +LL | ref foo @ [.., ref bar] => Some(foo), + | ----------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:80:5 + | +LL | fn bindings_after_at_or_patterns_move(x: Option) { + | - move occurs because `x` has type `std::option::Option`, which does not implement the `Copy` trait +LL | match x { +LL | foo @ Some(Test::Foo | Test::Bar) => (), + | --------------------------------- + | | + | value moved here + | value moved here +... +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:90:5 + | +LL | ref foo @ Some(Test::Foo | Test::Bar) => Some(foo), + | ------------------------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:102:5 + | +LL | ref mut foo @ Some(Test::Foo | Test::Bar) => Some(foo), + | ----------------------------------------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:116:5 + | +LL | ref foo @ Some(box ref s) => Some(foo), + | ------------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0382]: borrow of moved value: `x` + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:138:5 + | +LL | fn bindings_after_at_slice_patterns_or_patterns_moves(x: [Option; 4]) { + | - move occurs because `x` has type `[std::option::Option; 4]`, which does not implement the `Copy` trait +LL | match x { +LL | a @ [.., Some(Test::Foo | Test::Bar)] => (), + | ------------------------------------- + | | + | value moved here + | value moved here +... +LL | &x; + | ^^ value borrowed here after move + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:148:5 + | +LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(a), + | ------------------------------------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:160:5 + | +LL | ref a @ [ref b @ .., Some(Test::Foo | Test::Bar)] => Some(b), + | ---------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:174:5 + | +LL | [_, ref a @ Some(box ref b), ..] => Some(a), + | ----------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:190:5 + | +LL | [_, ref a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | ------------------------------------------- immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:204:5 + | +LL | [_, ref mut a @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | ----------------------------------------------- mutable borrow occurs here +... +LL | &x; + | ^^ immutable borrow occurs here +... +LL | drop(r); + | - mutable borrow later used here + +error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable + --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:218:5 + | +LL | ref a @ [_, ref b @ Some(box Test::Foo | box Test::Bar), ..] => Some(a), + | ------------------------------------------------------------ immutable borrow occurs here +... +LL | &mut x; + | ^^^^^^ mutable borrow occurs here +... +LL | drop(r); + | - immutable borrow later used here + +error: aborting due to 17 previous errors + +Some errors have detailed explanations: E0382, E0502. +For more information about an error, try `rustc --explain E0382`. From 67012158a379dbf58318346e87a631e7eb310bd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 26 Feb 2020 00:26:38 +0100 Subject: [PATCH 0921/1250] Move `analysis` to the query macro --- src/librustc/dep_graph/dep_node.rs | 2 -- src/librustc/query/mod.rs | 5 +++++ src/librustc/ty/query/config.rs | 9 +-------- src/librustc/ty/query/mod.rs | 7 +------ src/librustc/ty/query/plumbing.rs | 14 -------------- 5 files changed, 7 insertions(+), 30 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index eb7e2871bfc..05088dc4193 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -360,8 +360,6 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [anon] TraitSelect, [] CompileCodegenUnit(Symbol), - - [eval_always] Analysis(CrateNum), ]); pub trait RecoverKey<'tcx>: Sized { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b7f4f432838..daf89cab8af 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -60,6 +60,11 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } + query analysis(key: CrateNum) -> Result<(), ErrorReported> { + eval_always + desc { "running analysis passes on this crate" } + } + /// Maps from the `DefId` of an item (trait/struct/enum/fn) to its /// associated generics. query generics_of(key: DefId) -> &'tcx ty::Generics { diff --git a/src/librustc/ty/query/config.rs b/src/librustc/ty/query/config.rs index e0e1ca374d9..178c2362def 100644 --- a/src/librustc/ty/query/config.rs +++ b/src/librustc/ty/query/config.rs @@ -2,11 +2,10 @@ use crate::dep_graph::SerializedDepNodeIndex; use crate::dep_graph::{DepKind, DepNode}; use crate::ty::query::caches::QueryCache; use crate::ty::query::plumbing::CycleError; -use crate::ty::query::queries; use crate::ty::query::{Query, QueryState}; use crate::ty::TyCtxt; use rustc_data_structures::profiling::ProfileCategory; -use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::def_id::DefId; use crate::ich::StableHashingContext; use rustc_data_structures::fingerprint::Fingerprint; @@ -87,9 +86,3 @@ where bug!("QueryDescription::load_from_disk() called for an unsupported query.") } } - -impl<'tcx> QueryDescription<'tcx> for queries::analysis<'tcx> { - fn describe(_tcx: TyCtxt<'_>, _: CrateNum) -> Cow<'static, str> { - "running analysis passes on this crate".into() - } -} diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 8614fd5cdca..f49c64a7b87 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -104,9 +104,4 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder // Queries marked with `fatal_cycle` do not need the latter implementation, // as they will raise an fatal error on query cycles instead. -rustc_query_append! { [define_queries!][ <'tcx> - Other { - /// Runs analysis passes on the crate. - [eval_always] fn analysis: Analysis(CrateNum) -> Result<(), ErrorReported>, - }, -]} +rustc_query_append! { [define_queries!][<'tcx>] } diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index c94909549df..1769a925ec3 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -1246,20 +1246,6 @@ pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { DepKind::CompileCodegenUnit => { bug!("force_from_dep_node: encountered {:?}", dep_node) } - - DepKind::Analysis => { - let def_id = if let Some(def_id) = dep_node.extract_def_id(tcx) { - def_id - } else { - // Return from the whole function. - return false - }; - tcx.force_query::>( - def_id.krate, - DUMMY_SP, - *dep_node - ); - } ); true From cbce21767b757b209c4d4df6792995fecf02c7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 26 Feb 2020 02:20:33 +0100 Subject: [PATCH 0922/1250] Remove the need for `no_force` --- src/librustc/dep_graph/dep_node.rs | 42 ++++++------ src/librustc/dep_graph/mod.rs | 3 +- src/librustc/query/mod.rs | 2 +- src/librustc/ty/query/mod.rs | 105 ++++++++++++++++++++++++++++- src/librustc/ty/query/plumbing.rs | 92 +------------------------ src/librustc_macros/src/query.rs | 57 ++++++---------- 6 files changed, 148 insertions(+), 153 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 05088dc4193..bcb270ff0a6 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -362,29 +362,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> [] CompileCodegenUnit(Symbol), ]); -pub trait RecoverKey<'tcx>: Sized { - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; -} - -impl RecoverKey<'tcx> for CrateNum { - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.krate) - } -} - -impl RecoverKey<'tcx> for DefId { - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx) - } -} - -impl RecoverKey<'tcx> for DefIndex { - fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.index) - } -} - -trait DepNodeParams<'tcx>: fmt::Debug { +pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized { const CAN_RECONSTRUCT_QUERY_KEY: bool; /// This method turns the parameters of a DepNodeConstructor into an opaque @@ -398,6 +376,8 @@ trait DepNodeParams<'tcx>: fmt::Debug { fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { format!("{:?}", self) } + + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; } impl<'tcx, T> DepNodeParams<'tcx> for T @@ -418,6 +398,10 @@ where default fn to_debug_str(&self, _: TyCtxt<'tcx>) -> String { format!("{:?}", *self) } + + default fn recover(_: TyCtxt<'tcx>, _: &DepNode) -> Option { + None + } } impl<'tcx> DepNodeParams<'tcx> for DefId { @@ -430,6 +414,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefId { fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { tcx.def_path_str(*self) } + + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx) + } } impl<'tcx> DepNodeParams<'tcx> for DefIndex { @@ -442,6 +430,10 @@ impl<'tcx> DepNodeParams<'tcx> for DefIndex { fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { tcx.def_path_str(DefId::local(*self)) } + + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.index) + } } impl<'tcx> DepNodeParams<'tcx> for CrateNum { @@ -455,6 +447,10 @@ impl<'tcx> DepNodeParams<'tcx> for CrateNum { fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { tcx.crate_name(*self).to_string() } + + fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { + dep_node.extract_def_id(tcx).map(|id| id.krate) + } } impl<'tcx> DepNodeParams<'tcx> for (DefId, DefId) { diff --git a/src/librustc/dep_graph/mod.rs b/src/librustc/dep_graph/mod.rs index eb377d20f59..1fbd90743f4 100644 --- a/src/librustc/dep_graph/mod.rs +++ b/src/librustc/dep_graph/mod.rs @@ -6,7 +6,8 @@ mod query; mod safe; mod serialized; -pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, RecoverKey, WorkProductId}; +pub(crate) use self::dep_node::DepNodeParams; +pub use self::dep_node::{label_strs, DepConstructor, DepKind, DepNode, WorkProductId}; pub use self::graph::WorkProductFileKind; pub use self::graph::{hash_result, DepGraph, DepNodeColor, DepNodeIndex, TaskDeps, WorkProduct}; pub use self::prev::PreviousDepGraph; diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index daf89cab8af..c8155005480 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{DepKind, DepNode, RecoverKey, SerializedDepNodeIndex}; +use crate::dep_graph::SerializedDepNodeIndex; use crate::mir; use crate::mir::interpret::{GlobalId, LitToConstInput}; use crate::traits; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index f49c64a7b87..8adb828fbeb 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,4 +1,4 @@ -use crate::dep_graph::{self, DepConstructor, DepNode}; +use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams}; use crate::hir::exports::Export; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; @@ -60,8 +60,8 @@ use std::sync::Arc; #[macro_use] mod plumbing; +pub use self::plumbing::CycleError; use self::plumbing::*; -pub use self::plumbing::{force_from_dep_node, CycleError}; mod stats; pub use self::stats::print_stats; @@ -105,3 +105,104 @@ pub use self::profiling_support::{IntoSelfProfilingString, QueryKeyStringBuilder // as they will raise an fatal error on query cycles instead. rustc_query_append! { [define_queries!][<'tcx>] } + +/// The red/green evaluation system will try to mark a specific DepNode in the +/// dependency graph as green by recursively trying to mark the dependencies of +/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` +/// where we don't know if it is red or green and we therefore actually have +/// to recompute its value in order to find out. Since the only piece of +/// information that we have at that point is the `DepNode` we are trying to +/// re-evaluate, we need some way to re-run a query from just that. This is what +/// `force_from_dep_node()` implements. +/// +/// In the general case, a `DepNode` consists of a `DepKind` and an opaque +/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint +/// is usually constructed by computing a stable hash of the query-key that the +/// `DepNode` corresponds to. Consequently, it is not in general possible to go +/// back from hash to query-key (since hash functions are not reversible). For +/// this reason `force_from_dep_node()` is expected to fail from time to time +/// because we just cannot find out, from the `DepNode` alone, what the +/// corresponding query-key is and therefore cannot re-run the query. +/// +/// The system deals with this case letting `try_mark_green` fail which forces +/// the root query to be re-evaluated. +/// +/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. +/// Fortunately, we can use some contextual information that will allow us to +/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we +/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a +/// valid `DefPathHash`. Since we also always build a huge table that maps every +/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have +/// everything we need to re-run the query. +/// +/// Take the `mir_validated` query as an example. Like many other queries, it +/// just has a single parameter: the `DefId` of the item it will compute the +/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` +/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` +/// is actually a `DefPathHash`, and can therefore just look up the corresponding +/// `DefId` in `tcx.def_path_hash_to_def_id`. +/// +/// When you implement a new query, it will likely have a corresponding new +/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As +/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter, +/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just +/// add it to the "We don't have enough information to reconstruct..." group in +/// the match below. +pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool { + use crate::dep_graph::DepKind; + + // We must avoid ever having to call `force_from_dep_node()` for a + // `DepNode::codegen_unit`: + // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we + // would always end up having to evaluate the first caller of the + // `codegen_unit` query that *is* reconstructible. This might very well be + // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just + // to re-trigger calling the `codegen_unit` query with the right key. At + // that point we would already have re-done all the work we are trying to + // avoid doing in the first place. + // The solution is simple: Just explicitly call the `codegen_unit` query for + // each CGU, right after partitioning. This way `try_mark_green` will always + // hit the cache instead of having to go through `force_from_dep_node`. + // This assertion makes sure, we actually keep applying the solution above. + debug_assert!( + dep_node.kind != DepKind::codegen_unit, + "calling force_from_dep_node() on DepKind::codegen_unit" + ); + + if !dep_node.kind.can_reconstruct_query_key() { + return false; + } + + rustc_dep_node_force!([dep_node, tcx] + // These are inputs that are expected to be pre-allocated and that + // should therefore always be red or green already. + DepKind::AllLocalTraitImpls | + DepKind::CrateMetadata | + DepKind::HirBody | + DepKind::Hir | + + // These are anonymous nodes. + DepKind::TraitSelect | + + // We don't have enough information to reconstruct the query key of + // these. + DepKind::CompileCodegenUnit => { + bug!("force_from_dep_node: encountered {:?}", dep_node) + } + ); + + false +} + +impl DepNode { + /// Check whether the query invocation corresponding to the given + /// DepNode is eligible for on-disk-caching. If so, this is method + /// will execute the query corresponding to the given DepNode. + /// Also, as a sanity check, it expects that the corresponding query + /// invocation has been marked as green already. + pub fn try_load_from_on_disk_cache<'tcx>(&self, tcx: TyCtxt<'tcx>) { + use crate::dep_graph::DepKind; + + rustc_dep_node_try_load_from_on_disk_cache!(self, tcx) + } +} diff --git a/src/librustc/ty/query/plumbing.rs b/src/librustc/ty/query/plumbing.rs index 1769a925ec3..acf67f52dce 100644 --- a/src/librustc/ty/query/plumbing.rs +++ b/src/librustc/ty/query/plumbing.rs @@ -2,7 +2,7 @@ //! generate the actual methods on tcx which find and execute the provider, //! manage the caches, and so forth. -use crate::dep_graph::{DepKind, DepNode, DepNodeIndex, SerializedDepNodeIndex}; +use crate::dep_graph::{DepNode, DepNodeIndex, SerializedDepNodeIndex}; use crate::ty::query::caches::QueryCache; use crate::ty::query::config::{QueryAccessors, QueryDescription}; use crate::ty::query::job::{QueryInfo, QueryJob, QueryJobId, QueryShardJobId}; @@ -720,7 +720,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[allow(dead_code)] - fn force_query + 'tcx>( + pub(super) fn force_query + 'tcx>( self, key: Q::Key, span: Span, @@ -1162,91 +1162,3 @@ macro_rules! define_provider_struct { } }; } - -/// The red/green evaluation system will try to mark a specific DepNode in the -/// dependency graph as green by recursively trying to mark the dependencies of -/// that `DepNode` as green. While doing so, it will sometimes encounter a `DepNode` -/// where we don't know if it is red or green and we therefore actually have -/// to recompute its value in order to find out. Since the only piece of -/// information that we have at that point is the `DepNode` we are trying to -/// re-evaluate, we need some way to re-run a query from just that. This is what -/// `force_from_dep_node()` implements. -/// -/// In the general case, a `DepNode` consists of a `DepKind` and an opaque -/// GUID/fingerprint that will uniquely identify the node. This GUID/fingerprint -/// is usually constructed by computing a stable hash of the query-key that the -/// `DepNode` corresponds to. Consequently, it is not in general possible to go -/// back from hash to query-key (since hash functions are not reversible). For -/// this reason `force_from_dep_node()` is expected to fail from time to time -/// because we just cannot find out, from the `DepNode` alone, what the -/// corresponding query-key is and therefore cannot re-run the query. -/// -/// The system deals with this case letting `try_mark_green` fail which forces -/// the root query to be re-evaluated. -/// -/// Now, if `force_from_dep_node()` would always fail, it would be pretty useless. -/// Fortunately, we can use some contextual information that will allow us to -/// reconstruct query-keys for certain kinds of `DepNode`s. In particular, we -/// enforce by construction that the GUID/fingerprint of certain `DepNode`s is a -/// valid `DefPathHash`. Since we also always build a huge table that maps every -/// `DefPathHash` in the current codebase to the corresponding `DefId`, we have -/// everything we need to re-run the query. -/// -/// Take the `mir_validated` query as an example. Like many other queries, it -/// just has a single parameter: the `DefId` of the item it will compute the -/// validated MIR for. Now, when we call `force_from_dep_node()` on a `DepNode` -/// with kind `MirValidated`, we know that the GUID/fingerprint of the `DepNode` -/// is actually a `DefPathHash`, and can therefore just look up the corresponding -/// `DefId` in `tcx.def_path_hash_to_def_id`. -/// -/// When you implement a new query, it will likely have a corresponding new -/// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As -/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter, -/// then `force_from_dep_node()` should not fail for it. Otherwise, you can just -/// add it to the "We don't have enough information to reconstruct..." group in -/// the match below. -pub fn force_from_dep_node(tcx: TyCtxt<'_>, dep_node: &DepNode) -> bool { - use crate::dep_graph::RecoverKey; - - // We must avoid ever having to call `force_from_dep_node()` for a - // `DepNode::codegen_unit`: - // Since we cannot reconstruct the query key of a `DepNode::codegen_unit`, we - // would always end up having to evaluate the first caller of the - // `codegen_unit` query that *is* reconstructible. This might very well be - // the `compile_codegen_unit` query, thus re-codegenning the whole CGU just - // to re-trigger calling the `codegen_unit` query with the right key. At - // that point we would already have re-done all the work we are trying to - // avoid doing in the first place. - // The solution is simple: Just explicitly call the `codegen_unit` query for - // each CGU, right after partitioning. This way `try_mark_green` will always - // hit the cache instead of having to go through `force_from_dep_node`. - // This assertion makes sure, we actually keep applying the solution above. - debug_assert!( - dep_node.kind != DepKind::codegen_unit, - "calling force_from_dep_node() on DepKind::codegen_unit" - ); - - if !dep_node.kind.can_reconstruct_query_key() { - return false; - } - - rustc_dep_node_force!([dep_node, tcx] - // These are inputs that are expected to be pre-allocated and that - // should therefore always be red or green already. - DepKind::AllLocalTraitImpls | - DepKind::CrateMetadata | - DepKind::HirBody | - DepKind::Hir | - - // These are anonymous nodes. - DepKind::TraitSelect | - - // We don't have enough information to reconstruct the query key of - // these. - DepKind::CompileCodegenUnit => { - bug!("force_from_dep_node: encountered {:?}", dep_node) - } - ); - - true -} diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index 97b800decc5..c23095968fb 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -425,7 +425,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { let mut dep_node_def_stream = quote! {}; let mut dep_node_force_stream = quote! {}; let mut try_load_from_on_disk_cache_stream = quote! {}; - let mut no_force_queries = Vec::new(); let mut cached_queries = quote! {}; for group in groups.0 { @@ -444,19 +443,19 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { cached_queries.extend(quote! { #name, }); - } - if modifiers.cache.is_some() && !modifiers.no_force { try_load_from_on_disk_cache_stream.extend(quote! { DepKind::#name => { - debug_assert!(tcx.dep_graph - .node_color(self) - .map(|c| c.is_green()) - .unwrap_or(false)); - - let key = RecoverKey::recover(tcx, self).unwrap(); - if queries::#name::cache_on_disk(tcx, key, None) { - let _ = tcx.#name(key); + if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY { + debug_assert!($tcx.dep_graph + .node_color($dep_node) + .map(|c| c.is_green()) + .unwrap_or(false)); + + let key = <#arg as DepNodeParams>::recover($tcx, $dep_node).unwrap(); + if queries::#name::cache_on_disk($tcx, key, None) { + let _ = $tcx.#name(key); + } } } }); @@ -501,24 +500,21 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { [#attribute_stream] #name(#arg), }); - if modifiers.no_force { - no_force_queries.push(name.clone()); - } else { - // Add a match arm to force the query given the dep node - dep_node_force_stream.extend(quote! { - DepKind::#name => { - if let Some(key) = RecoverKey::recover($tcx, $dep_node) { + // Add a match arm to force the query given the dep node + dep_node_force_stream.extend(quote! { + DepKind::#name => { + if <#arg as DepNodeParams>::CAN_RECONSTRUCT_QUERY_KEY { + if let Some(key) = <#arg as DepNodeParams>::recover($tcx, $dep_node) { $tcx.force_query::>( key, DUMMY_SP, *$dep_node ); - } else { - return false; + return true; } } - }); - } + } + }); add_query_description_impl(&query, modifiers, &mut query_description_stream); } @@ -528,12 +524,6 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { }); } - // Add an arm for the no force queries to panic when trying to force them - for query in no_force_queries { - dep_node_force_stream.extend(quote! { - DepKind::#query | - }); - } dep_node_force_stream.extend(quote! { DepKind::Null => { bug!("Cannot force dep node: {:?}", $dep_node) @@ -577,14 +567,9 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { #query_description_stream - impl DepNode { - /// Check whether the query invocation corresponding to the given - /// DepNode is eligible for on-disk-caching. If so, this is method - /// will execute the query corresponding to the given DepNode. - /// Also, as a sanity check, it expects that the corresponding query - /// invocation has been marked as green already. - pub fn try_load_from_on_disk_cache(&self, tcx: TyCtxt<'_>) { - match self.kind { + macro_rules! rustc_dep_node_try_load_from_on_disk_cache { + ($dep_node:expr, $tcx:expr) => { + match $dep_node.kind { #try_load_from_on_disk_cache_stream _ => (), } From f4450772ede7bc064d1727430acdb1b2dc851742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 26 Feb 2020 02:39:18 +0100 Subject: [PATCH 0923/1250] Remove the `no_force` query attribute --- src/librustc/query/mod.rs | 38 -------------------------------- src/librustc_macros/src/query.rs | 16 -------------- 2 files changed, 54 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index c8155005480..11e9acf3a39 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -200,7 +200,6 @@ rustc_queries! { // queries). Making it anonymous avoids hashing the result, which // may save a bit of time. anon - no_force desc { "erasing regions from `{:?}`", ty } } @@ -209,7 +208,6 @@ rustc_queries! { } query program_clauses_for_env(_: traits::Environment<'tcx>) -> Clauses<'tcx> { - no_force desc { "generating chalk-style clauses for environment" } } @@ -252,7 +250,6 @@ rustc_queries! { /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. query type_param_predicates(key: (DefId, DefId)) -> ty::GenericPredicates<'tcx> { - no_force desc { |tcx| "computing the bounds for type parameter `{}`", { let id = tcx.hir().as_local_hir_id(key.1).unwrap(); tcx.hir().ty_param_name(id) @@ -508,7 +505,6 @@ rustc_queries! { /// form to be used outside of const eval. query const_eval_raw(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalRawResult<'tcx> { - no_force desc { |tcx| "const-evaluating `{}`", tcx.def_path_str(key.value.instance.def.def_id()) @@ -525,7 +521,6 @@ rustc_queries! { /// `tcx.const_eval_resolve`, `tcx.const_eval_instance`, or `tcx.const_eval_global_id`. query const_eval_validated(key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>) -> ConstEvalResult<'tcx> { - no_force desc { |tcx| "const-evaluating + checking `{}`", tcx.def_path_str(key.value.instance.def.def_id()) @@ -540,7 +535,6 @@ rustc_queries! { query const_field( key: ty::ParamEnvAnd<'tcx, (&'tcx ty::Const<'tcx>, mir::Field)> ) -> ConstValue<'tcx> { - no_force desc { "extract field of const" } } @@ -549,19 +543,16 @@ rustc_queries! { query destructure_const( key: ty::ParamEnvAnd<'tcx, &'tcx ty::Const<'tcx>> ) -> mir::DestructuredConst<'tcx> { - no_force desc { "destructure constant" } } query const_caller_location(key: (rustc_span::Symbol, u32, u32)) -> ConstValue<'tcx> { - no_force desc { "get a &core::panic::Location referring to a span" } } query lit_to_const( key: LitToConstInput<'tcx> ) -> Result<&'tcx ty::Const<'tcx>, LitToConstError> { - no_force desc { "converting literal to const" } } } @@ -592,7 +583,6 @@ rustc_queries! { query region_scope_tree(_: DefId) -> &'tcx region::ScopeTree {} query mir_shims(key: ty::InstanceDef<'tcx>) -> &'tcx mir::BodyAndCache<'tcx> { - no_force desc { |tcx| "generating MIR shim for `{}`", tcx.def_path_str(key.def_id()) } } @@ -600,7 +590,6 @@ rustc_queries! { /// given instance from the local crate. In particular, it will also /// look up the correct symbol name of instances from upstream crates. query symbol_name(key: ty::Instance<'tcx>) -> ty::SymbolName { - no_force desc { "computing the symbol for `{}`", key } cache_on_disk_if { true } } @@ -647,7 +636,6 @@ rustc_queries! { Other { query vtable_methods(key: ty::PolyTraitRef<'tcx>) -> &'tcx [Option<(DefId, SubstsRef<'tcx>)>] { - no_force desc { |tcx| "finding all methods for trait {}", tcx.def_path_str(key.def_id()) } } } @@ -656,7 +644,6 @@ rustc_queries! { query codegen_fulfill_obligation( key: (ty::ParamEnv<'tcx>, ty::PolyTraitRef<'tcx>) ) -> Option> { - no_force cache_on_disk_if { true } desc { |tcx| "checking if `{}` fulfills its obligations", @@ -688,22 +675,18 @@ rustc_queries! { /// Trait selection queries. These are best used by invoking `ty.is_copy_modulo_regions()`, /// `ty.is_copy()`, etc, since that will prune the environment where possible. query is_copy_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - no_force desc { "computing whether `{}` is `Copy`", env.value } } /// Query backing `TyS::is_sized`. query is_sized_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - no_force desc { "computing whether `{}` is `Sized`", env.value } } /// Query backing `TyS::is_freeze`. query is_freeze_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - no_force desc { "computing whether `{}` is freeze", env.value } } /// Query backing `TyS::needs_drop`. query needs_drop_raw(env: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { - no_force desc { "computing whether `{}` needs drop", env.value } } @@ -717,7 +700,6 @@ rustc_queries! { query layout_raw( env: ty::ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Result<&'tcx ty::layout::LayoutDetails, ty::layout::LayoutError<'tcx>> { - no_force desc { "computing layout of `{}`", env.value } } } @@ -773,7 +755,6 @@ rustc_queries! { TypeChecking { query specializes(_: (DefId, DefId)) -> bool { - no_force desc { "computing whether impls specialize one another" } } query in_scope_traits_map(_: DefIndex) @@ -858,7 +839,6 @@ rustc_queries! { /// (like `Clone::clone` for example). query upstream_drop_glue_for(substs: SubstsRef<'tcx>) -> Option { desc { "available upstream drop-glue for `{:?}`", substs } - no_force } } @@ -903,7 +883,6 @@ rustc_queries! { TypeChecking { query implementations_of_trait(_: (CrateNum, DefId)) -> &'tcx [DefId] { - no_force desc { "looking up implementations of a trait in a crate" } } query all_trait_implementations(_: CrateNum) @@ -1070,7 +1049,6 @@ rustc_queries! { } query is_codegened_item(_: DefId) -> bool {} query codegen_unit(_: Symbol) -> Arc> { - no_force desc { "codegen_unit" } } query backend_optimization_level(_: CrateNum) -> OptLevel { @@ -1093,7 +1071,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, NormalizationResult<'tcx>>>, NoSolution, > { - no_force desc { "normalizing `{:?}`", goal } } @@ -1101,7 +1078,6 @@ rustc_queries! { query normalize_ty_after_erasing_regions( goal: ParamEnvAnd<'tcx, Ty<'tcx>> ) -> Ty<'tcx> { - no_force desc { "normalizing `{:?}`", goal } } @@ -1111,7 +1087,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Vec>>>, NoSolution, > { - no_force desc { "computing implied outlives bounds for `{:?}`", goal } } @@ -1122,7 +1097,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, DropckOutlivesResult<'tcx>>>, NoSolution, > { - no_force desc { "computing dropck types for `{:?}`", goal } } @@ -1131,7 +1105,6 @@ rustc_queries! { query evaluate_obligation( goal: CanonicalPredicateGoal<'tcx> ) -> Result { - no_force desc { "evaluating trait selection obligation `{}`", goal.value.value } } @@ -1142,7 +1115,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - no_force desc { "evaluating `type_op_ascribe_user_type` `{:?}`", goal } } @@ -1153,7 +1125,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - no_force desc { "evaluating `type_op_eq` `{:?}`", goal } } @@ -1164,7 +1135,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - no_force desc { "evaluating `type_op_subtype` `{:?}`", goal } } @@ -1175,7 +1145,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ()>>, NoSolution, > { - no_force desc { "evaluating `type_op_prove_predicate` `{:?}`", goal } } @@ -1186,7 +1155,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, Ty<'tcx>>>, NoSolution, > { - no_force desc { "normalizing `{:?}`", goal } } @@ -1197,7 +1165,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::Predicate<'tcx>>>, NoSolution, > { - no_force desc { "normalizing `{:?}`", goal } } @@ -1208,7 +1175,6 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::PolyFnSig<'tcx>>>, NoSolution, > { - no_force desc { "normalizing `{:?}`", goal } } @@ -1219,12 +1185,10 @@ rustc_queries! { &'tcx Canonical<'tcx, canonical::QueryResponse<'tcx, ty::FnSig<'tcx>>>, NoSolution, > { - no_force desc { "normalizing `{:?}`", goal } } query substitute_normalize_and_test_predicates(key: (DefId, SubstsRef<'tcx>)) -> bool { - no_force desc { |tcx| "testing substituted normalized predicates:`{}`", tcx.def_path_str(key.0) @@ -1234,7 +1198,6 @@ rustc_queries! { query method_autoderef_steps( goal: CanonicalTyGoal<'tcx> ) -> MethodAutoderefStepsResult<'tcx> { - no_force desc { "computing autoderef types for `{:?}`", goal } } } @@ -1248,7 +1211,6 @@ rustc_queries! { // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. query instance_def_size_estimate(def: ty::InstanceDef<'tcx>) -> usize { - no_force desc { |tcx| "estimating size for `{}`", tcx.def_path_str(def.def_id()) } } diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs index c23095968fb..56b7be2f7e2 100644 --- a/src/librustc_macros/src/query.rs +++ b/src/librustc_macros/src/query.rs @@ -51,9 +51,6 @@ enum QueryModifier { /// Don't hash the result, instead just mark a query red if it runs NoHash, - /// Don't force the query - NoForce, - /// Generate a dep node based on the dependencies of the query Anon, @@ -118,8 +115,6 @@ impl Parse for QueryModifier { Ok(QueryModifier::CycleDelayBug) } else if modifier == "no_hash" { Ok(QueryModifier::NoHash) - } else if modifier == "no_force" { - Ok(QueryModifier::NoForce) } else if modifier == "anon" { Ok(QueryModifier::Anon) } else if modifier == "eval_always" { @@ -222,9 +217,6 @@ struct QueryModifiers { /// Don't hash the result, instead just mark a query red if it runs no_hash: bool, - /// Don't force the query - no_force: bool, - /// Generate a dep node based on the dependencies of the query anon: bool, @@ -241,7 +233,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut fatal_cycle = false; let mut cycle_delay_bug = false; let mut no_hash = false; - let mut no_force = false; let mut anon = false; let mut eval_always = false; for modifier in query.modifiers.0.drain(..) { @@ -288,12 +279,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } no_hash = true; } - QueryModifier::NoForce => { - if no_force { - panic!("duplicate modifier `no_force` for query `{}`", query.name); - } - no_force = true; - } QueryModifier::Anon => { if anon { panic!("duplicate modifier `anon` for query `{}`", query.name); @@ -316,7 +301,6 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { fatal_cycle, cycle_delay_bug, no_hash, - no_force, anon, eval_always, } From 2f120095b59320d8c0adc3ad8f9294560bdf5c07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 9 Mar 2020 14:50:09 +0100 Subject: [PATCH 0924/1250] Add a comment to `recover`. --- src/librustc/dep_graph/dep_node.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index bcb270ff0a6..156f412e090 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -377,6 +377,12 @@ pub(crate) trait DepNodeParams<'tcx>: fmt::Debug + Sized { format!("{:?}", self) } + /// This method tries to recover the query key from the given `DepNode`, + /// something which is needed when forcing `DepNode`s during red-green + /// evaluation. The query system will only call this method if + /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`. + /// It is always valid to return `None` here, in which case incremental + /// compilation will treat the query as having changed instead of forcing it. fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option; } From 51b60b75e79e39dcbb1fa96d72f4cbb82df7f2ae Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 16:56:45 +0100 Subject: [PATCH 0925/1250] Improve readability --- src/librustc_codegen_ssa/mir/block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index f22c0216a78..6963f1d811a 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -415,8 +415,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { AssertKind::BoundsCheck { ref len, ref index } => { let len = self.codegen_operand(&mut bx, len).immediate(); let index = self.codegen_operand(&mut bx, index).immediate(); - // It's `fn panic_bounds_check(index: usize, len: usize)`, and - // `#[track_caller]` adds an implicit third argument. + // It's `fn panic_bounds_check(index: usize, len: usize)`, + // and `#[track_caller]` adds an implicit third argument. (lang_items::PanicBoundsCheckFnLangItem, vec![index, len, location]) } _ => { From 0605abe3bb7b602cbe70a72797fdd6ca90d76e92 Mon Sep 17 00:00:00 2001 From: Dan Aloni Date: Mon, 9 Mar 2020 17:40:31 +0200 Subject: [PATCH 0926/1250] Use GetSystemTimePreciseAsFileTime if it is available --- src/libstd/sys/windows/c.rs | 4 ++++ src/libstd/sys/windows/time.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index 4d377341be3..ed0b239b9f9 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -1044,6 +1044,10 @@ compat_fn! { _dwBufferSize: DWORD) -> BOOL { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as DWORD); 0 } + pub fn GetSystemTimePreciseAsFileTime(lpSystemTimeAsFileTime: LPFILETIME) + -> () { + GetSystemTimeAsFileTime(lpSystemTimeAsFileTime) + } pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE, SRWLock: PSRWLOCK, dwMilliseconds: DWORD, diff --git a/src/libstd/sys/windows/time.rs b/src/libstd/sys/windows/time.rs index 86667ca7ab2..900260169c7 100644 --- a/src/libstd/sys/windows/time.rs +++ b/src/libstd/sys/windows/time.rs @@ -74,7 +74,7 @@ impl SystemTime { pub fn now() -> SystemTime { unsafe { let mut t: SystemTime = mem::zeroed(); - c::GetSystemTimeAsFileTime(&mut t.t); + c::GetSystemTimePreciseAsFileTime(&mut t.t); t } } From 7c60405dd63a2d5720251c97ec209d8844f56395 Mon Sep 17 00:00:00 2001 From: Dylan Nugent Date: Mon, 9 Mar 2020 12:31:33 -0400 Subject: [PATCH 0927/1250] Add note about localization to std::fmt docs --- src/liballoc/fmt.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/liballoc/fmt.rs b/src/liballoc/fmt.rs index e6162e0f571..13ef2f063f9 100644 --- a/src/liballoc/fmt.rs +++ b/src/liballoc/fmt.rs @@ -247,6 +247,21 @@ //! Hello, ` 123` has 3 right-aligned characters //! ``` //! +//! ## Localization +//! +//! In some programming languages, the behavior of string formatting functions +//! depends on the operating system's locale setting. The format functions +//! provided by Rust's standard library do not have any concept of locale, and +//! will produce the same results on all systems regardless of user +//! configuration. +//! +//! For example, the following code will always print `1.5` even if the system +//! locale uses a decimal separator other than a dot. +//! +//! ``` +//! println!("The value is {}", 1.5); +//! ``` +//! //! # Escaping //! //! The literal characters `{` and `}` may be included in a string by preceding From eafeb9a2676e16ed322e9e0695b5ce9407f5de8d Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 30 Dec 2019 21:38:43 +0300 Subject: [PATCH 0928/1250] expand/builtin_macros: Minor cleanup --- src/librustc_builtin_macros/util.rs | 2 +- src/librustc_expand/base.rs | 13 +++---------- src/librustc_feature/builtin_attrs.rs | 8 +------- 3 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/librustc_builtin_macros/util.rs b/src/librustc_builtin_macros/util.rs index 8ef76a8657e..b486eadd1a8 100644 --- a/src/librustc_builtin_macros/util.rs +++ b/src/librustc_builtin_macros/util.rs @@ -6,7 +6,7 @@ use rustc_span::Symbol; pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. - let template = AttributeTemplate::only_word(); + let template = AttributeTemplate { word: true, ..Default::default() }; let attr = ecx.attribute(meta_item.clone()); validate_attr::check_builtin_attribute(ecx.parse_sess, &attr, name, template); } diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index f15e626c278..55e9c70d637 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -270,10 +270,9 @@ pub trait MultiItemModifier { ) -> Vec; } -impl MultiItemModifier for F +impl MultiItemModifier for F where - F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> T, - T: Into>, + F: Fn(&mut ExtCtxt<'_>, Span, &ast::MetaItem, Annotatable) -> Vec, { fn expand( &self, @@ -282,13 +281,7 @@ where meta_item: &ast::MetaItem, item: Annotatable, ) -> Vec { - (*self)(ecx, span, meta_item, item).into() - } -} - -impl Into> for Annotatable { - fn into(self) -> Vec { - vec![self] + self(ecx, span, meta_item, item) } } diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e9a5364c658..e0e38c2dba9 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -85,19 +85,13 @@ impl AttributeGate { /// A template that the attribute input must match. /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct AttributeTemplate { pub word: bool, pub list: Option<&'static str>, pub name_value_str: Option<&'static str>, } -impl AttributeTemplate { - pub fn only_word() -> Self { - Self { word: true, list: None, name_value_str: None } - } -} - /// A convenience macro for constructing attribute templates. /// E.g., `template!(Word, List: "description")` means that the attribute /// supports forms `#[attr]` and `#[attr(description)]`. From f34e0664a1fa63f89f2257dba7d0d13445f58c02 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 19:58:58 +0100 Subject: [PATCH 0929/1250] remove no-longer needed span from Miri Machine hook --- src/librustc_mir/const_eval/machine.rs | 1 - src/librustc_mir/interpret/machine.rs | 1 - src/librustc_mir/interpret/terminator.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 1 - 4 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index ed802983468..bb661d3d2a3 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -280,7 +280,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, - _span: Span, msg: &AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 6615cc608fb..087517ff4e3 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -165,7 +165,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Called to evaluate `Assert` MIR terminators that trigger a panic. fn assert_panic( ecx: &mut InterpCx<'mir, 'tcx, Self>, - span: Span, msg: &mir::AssertMessage<'tcx>, unwind: Option, ) -> InterpResult<'tcx>; diff --git a/src/librustc_mir/interpret/terminator.rs b/src/librustc_mir/interpret/terminator.rs index ea8378574a3..b5c34daf8a3 100644 --- a/src/librustc_mir/interpret/terminator.rs +++ b/src/librustc_mir/interpret/terminator.rs @@ -95,7 +95,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if expected == cond_val { self.go_to_block(target); } else { - M::assert_panic(self, terminator.source_info.span, msg, cleanup)?; + M::assert_panic(self, msg, cleanup)?; } } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 0560f77f5c9..4c353d1ae22 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -197,7 +197,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { fn assert_panic( _ecx: &mut InterpCx<'mir, 'tcx, Self>, - _span: Span, _msg: &rustc::mir::AssertMessage<'tcx>, _unwind: Option, ) -> InterpResult<'tcx> { From 3ba89e87503e25aece0318a9851f8dba5ccd94a2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 13 Feb 2020 00:11:16 -0800 Subject: [PATCH 0930/1250] Remove quotes around unknown fn placeholder in backtrace --- src/libstd/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index 97db0ff3791..b14486471ff 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -193,7 +193,7 @@ impl fmt::Debug for BacktraceSymbol { if let Some(fn_name) = self.name.as_ref().map(|b| backtrace::SymbolName::new(b)) { write!(fmt, "fn: \"{:#}\"", fn_name)?; } else { - write!(fmt, "fn: \"\"")?; + write!(fmt, "fn: ")?; } if let Some(fname) = self.filename.as_ref() { From db75b6a91f67008ec789d9934f8a73e09fd0d472 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 13 Feb 2020 00:11:52 -0800 Subject: [PATCH 0931/1250] Add quotes around filename in Backtrace debug --- src/libstd/backtrace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index b14486471ff..cc842ebd589 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -197,7 +197,7 @@ impl fmt::Debug for BacktraceSymbol { } if let Some(fname) = self.filename.as_ref() { - write!(fmt, ", file: {:?}", fname)?; + write!(fmt, ", file: \"{:?}\"", fname)?; } if let Some(line) = self.lineno.as_ref() { From 1f1ca877b7002e3ac45916df5415fde1584775ab Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 13 Feb 2020 00:12:26 -0800 Subject: [PATCH 0932/1250] Change disabled and unsupported backtraces to print using placeholder style --- src/libstd/backtrace.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index cc842ebd589..c64eb9f8e40 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -162,8 +162,8 @@ enum BytesOrWide { impl fmt::Debug for Backtrace { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { let mut capture = match &self.inner { - Inner::Unsupported => return fmt.write_str("unsupported backtrace"), - Inner::Disabled => return fmt.write_str("disabled backtrace"), + Inner::Unsupported => return fmt.write_str(""), + Inner::Disabled => return fmt.write_str(""), Inner::Captured(c) => c.lock().unwrap(), }; capture.resolve(); From a9cc010c4883bafba1304f6fd581343f5b1b3ba2 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 13 Feb 2020 00:13:48 -0800 Subject: [PATCH 0933/1250] Make it possible to instantiate hardcoded Backtrace from test --- src/libstd/backtrace.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index c64eb9f8e40..04fd80ecbdb 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -92,6 +92,7 @@ // a backtrace or actually symbolizing it. use crate::env; +use crate::ffi::c_void; use crate::fmt; use crate::sync::atomic::{AtomicUsize, Ordering::SeqCst}; use crate::sync::Mutex; @@ -144,10 +145,16 @@ fn _assert_send_sync() { } struct BacktraceFrame { - frame: backtrace::Frame, + frame: RawFrame, symbols: Vec, } +enum RawFrame { + Actual(backtrace::Frame), + #[cfg(test)] + Fake, +} + struct BacktraceSymbol { name: Option>, filename: Option, @@ -293,7 +300,10 @@ impl Backtrace { let mut actual_start = None; unsafe { backtrace::trace_unsynchronized(|frame| { - frames.push(BacktraceFrame { frame: frame.clone(), symbols: Vec::new() }); + frames.push(BacktraceFrame { + frame: RawFrame::Actual(frame.clone()), + symbols: Vec::new(), + }); if frame.symbol_address() as usize == ip && actual_start.is_none() { actual_start = Some(frames.len()); } @@ -393,8 +403,13 @@ impl Capture { let _lock = lock(); for frame in self.frames.iter_mut() { let symbols = &mut frame.symbols; + let frame = match &frame.frame { + RawFrame::Actual(frame) => frame, + #[cfg(test)] + RawFrame::Fake => unimplemented!(), + }; unsafe { - backtrace::resolve_frame_unsynchronized(&frame.frame, |symbol| { + backtrace::resolve_frame_unsynchronized(frame, |symbol| { symbols.push(BacktraceSymbol { name: symbol.name().map(|m| m.as_bytes().to_vec()), filename: symbol.filename_raw().map(|b| match b { @@ -408,3 +423,13 @@ impl Capture { } } } + +impl RawFrame { + fn ip(&self) -> *mut c_void { + match self { + RawFrame::Actual(frame) => frame.ip(), + #[cfg(test)] + RawFrame::Fake => 1 as *mut c_void, + } + } +} From 33600e4d2d7a61f7dcb1b278bb1ccb8f04690db3 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 13 Feb 2020 00:16:28 -0800 Subject: [PATCH 0934/1250] Add test of Debug representation of Backtrace --- src/libstd/backtrace.rs | 52 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index 04fd80ecbdb..f3dd7a62fcb 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -433,3 +433,55 @@ impl RawFrame { } } } + +#[test] +fn test_debug() { + let backtrace = Backtrace { + inner: Inner::Captured(Mutex::new(Capture { + actual_start: 1, + resolved: true, + frames: vec![ + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![BacktraceSymbol { + name: Some(b"std::backtrace::Backtrace::create".to_vec()), + filename: Some(BytesOrWide::Bytes(b"/rust/backtrace.rs".to_vec())), + lineno: Some(100), + }], + }, + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![BacktraceSymbol { + name: Some(b"__rust_maybe_catch_panic".to_vec()), + filename: None, + lineno: None, + }], + }, + BacktraceFrame { + frame: RawFrame::Fake, + symbols: vec![ + BacktraceSymbol { + name: Some(b"std::rt::lang_start_internal".to_vec()), + filename: Some(BytesOrWide::Bytes(b"/rust/rt.rs".to_vec())), + lineno: Some(300), + }, + BacktraceSymbol { + name: Some(b"std::rt::lang_start".to_vec()), + filename: Some(BytesOrWide::Bytes(b"/rust/rt.rs".to_vec())), + lineno: Some(400), + }, + ], + }, + ], + })), + }; + + #[rustfmt::skip] + let expected = "Backtrace [\ + \n { fn: \"__rust_maybe_catch_panic\" },\ + \n { fn: \"std::rt::lang_start_internal\", file: \"/rust/rt.rs\", line: 300 },\ + \n { fn: \"std::rt::lang_start\", file: \"/rust/rt.rs\", line: 400 },\ + \n]"; + + assert_eq!(format!("{:#?}", backtrace), expected); +} From 911c75ff5f11c28c9f355857a47c5cd2d73767e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 9 Mar 2020 20:18:48 +0100 Subject: [PATCH 0935/1250] also handle abort intrinsic with new machine hook --- src/librustc_mir/interpret/intrinsics.rs | 4 ++++ src/librustc_mir/interpret/machine.rs | 2 +- src/librustc_span/symbol.rs | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs index 891afbf437f..88c6c26c5ba 100644 --- a/src/librustc_mir/interpret/intrinsics.rs +++ b/src/librustc_mir/interpret/intrinsics.rs @@ -103,6 +103,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(location.ptr, dest)?; } + sym::abort => { + M::abort(self)?; + } + sym::min_align_of | sym::pref_align_of | sym::needs_drop diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 64a34fc7dd9..a3c43d7d5d1 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -171,7 +171,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ) -> InterpResult<'tcx>; /// Called to evaluate `Abort` MIR terminator. - fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, !> { throw_unsup_format!("aborting execution is not supported"); } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index c39f9f360c0..4f5c4de8569 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -120,6 +120,7 @@ symbols! { abi_unadjusted, abi_vectorcall, abi_x86_interrupt, + abort, aborts, address, add_with_overflow, From a2364dc85fb505487c272988b8c5073a3f6fef2a Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 9 Mar 2020 12:23:19 -0700 Subject: [PATCH 0936/1250] Write backtrace fmt test using relative paths For some reason the absolute paths were formatted differently on the armhf-gnu target. thread '' panicked at 'assertion failed: `(left == right)` left: `"Backtrace [\n { fn: \"__rust_maybe_catch_panic\" },\n { fn: \"std::rt::lang_start_internal\", file: \"./rust/rt.rs\", line: 300 },\n { fn: \"std::rt::lang_start\", file: \"./rust/rt.rs\", line: 400 },\n]"`, right: `"Backtrace [\n { fn: \"__rust_maybe_catch_panic\" },\n { fn: \"std::rt::lang_start_internal\", file: \"/rust/rt.rs\", line: 300 },\n { fn: \"std::rt::lang_start\", file: \"/rust/rt.rs\", line: 400 },\n]"`', src/libstd/backtrace.rs:486:5 --- src/libstd/backtrace.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libstd/backtrace.rs b/src/libstd/backtrace.rs index f3dd7a62fcb..34317c7a2ee 100644 --- a/src/libstd/backtrace.rs +++ b/src/libstd/backtrace.rs @@ -445,7 +445,7 @@ fn test_debug() { frame: RawFrame::Fake, symbols: vec![BacktraceSymbol { name: Some(b"std::backtrace::Backtrace::create".to_vec()), - filename: Some(BytesOrWide::Bytes(b"/rust/backtrace.rs".to_vec())), + filename: Some(BytesOrWide::Bytes(b"rust/backtrace.rs".to_vec())), lineno: Some(100), }], }, @@ -462,12 +462,12 @@ fn test_debug() { symbols: vec![ BacktraceSymbol { name: Some(b"std::rt::lang_start_internal".to_vec()), - filename: Some(BytesOrWide::Bytes(b"/rust/rt.rs".to_vec())), + filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())), lineno: Some(300), }, BacktraceSymbol { name: Some(b"std::rt::lang_start".to_vec()), - filename: Some(BytesOrWide::Bytes(b"/rust/rt.rs".to_vec())), + filename: Some(BytesOrWide::Bytes(b"rust/rt.rs".to_vec())), lineno: Some(400), }, ], @@ -479,8 +479,8 @@ fn test_debug() { #[rustfmt::skip] let expected = "Backtrace [\ \n { fn: \"__rust_maybe_catch_panic\" },\ - \n { fn: \"std::rt::lang_start_internal\", file: \"/rust/rt.rs\", line: 300 },\ - \n { fn: \"std::rt::lang_start\", file: \"/rust/rt.rs\", line: 400 },\ + \n { fn: \"std::rt::lang_start_internal\", file: \"rust/rt.rs\", line: 300 },\ + \n { fn: \"std::rt::lang_start\", file: \"rust/rt.rs\", line: 400 },\ \n]"; assert_eq!(format!("{:#?}", backtrace), expected); From 7b75c346d56e07634effc56acebac8c0698773b1 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Tue, 10 Mar 2020 02:04:48 +0530 Subject: [PATCH 0937/1250] Add long error explanation for E0628 #61137 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0628.md | 30 +++++++++++++++++++ .../ui/generator/too-many-parameters.stderr | 1 + 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0628.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 11d1209923f..57fb236d9d6 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -349,6 +349,7 @@ E0623: include_str!("./error_codes/E0623.md"), E0624: include_str!("./error_codes/E0624.md"), E0626: include_str!("./error_codes/E0626.md"), E0627: include_str!("./error_codes/E0627.md"), +E0628: include_str!("./error_codes/E0628.md"), E0631: include_str!("./error_codes/E0631.md"), E0633: include_str!("./error_codes/E0633.md"), E0635: include_str!("./error_codes/E0635.md"), @@ -580,7 +581,6 @@ E0748: include_str!("./error_codes/E0748.md"), // E0612, // merged into E0609 // E0613, // Removed (merged with E0609) E0625, // thread-local statics cannot be accessed at compile-time - E0628, // generators cannot have explicit parameters E0629, // missing 'feature' (rustc_const_unstable) // rustc_const_unstable attribute must be paired with stable/unstable // attribute diff --git a/src/librustc_error_codes/error_codes/E0628.md b/src/librustc_error_codes/error_codes/E0628.md new file mode 100644 index 00000000000..8aa0724bac7 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0628.md @@ -0,0 +1,30 @@ +More than one parameter was used for a generator. + +Erroneous code example: + +```compile_fail,E0628 +#![feature(generators, generator_trait)] + +fn main() { + let generator = |a: i32, b: i32| { + // error: too many parameters for a generator + // Allowed only 0 or 1 parameter + yield a; + }; +} +``` + +At present, it is not permitted to pass more than one explicit +parameter for a generator.This can be fixed by using only +0 or 1 parameter for generator. So, for example, we might resolve +the previous example by passing only one parameter. + +``` +#![feature(generators, generator_trait)] + +fn main() { + let generator = |a: i32| { + yield a; + }; +} +``` diff --git a/src/test/ui/generator/too-many-parameters.stderr b/src/test/ui/generator/too-many-parameters.stderr index a297ee43de9..22d40db3f26 100644 --- a/src/test/ui/generator/too-many-parameters.stderr +++ b/src/test/ui/generator/too-many-parameters.stderr @@ -6,3 +6,4 @@ LL | |(), ()| { error: aborting due to previous error +For more information about this error, try `rustc --explain E0628`. From 552a8875bd5520c2e8c01ab05a12c304c730c5b9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 9 Mar 2020 20:50:12 +0300 Subject: [PATCH 0938/1250] expand: Implement support for retrying macro expansions --- src/librustc_builtin_macros/deriving/mod.rs | 6 +- src/librustc_expand/base.rs | 19 ++- src/librustc_expand/expand.rs | 145 ++++++++++++++------ src/librustc_expand/proc_macro.rs | 8 +- 4 files changed, 124 insertions(+), 54 deletions(-) diff --git a/src/librustc_builtin_macros/deriving/mod.rs b/src/librustc_builtin_macros/deriving/mod.rs index 5ba9d3800e1..b5ad67abf62 100644 --- a/src/librustc_builtin_macros/deriving/mod.rs +++ b/src/librustc_builtin_macros/deriving/mod.rs @@ -2,7 +2,7 @@ use rustc_ast::ast::{self, ItemKind, MetaItem}; use rustc_ast::ptr::P; -use rustc_expand::base::{Annotatable, ExtCtxt, MultiItemModifier}; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -48,13 +48,13 @@ impl MultiItemModifier for BuiltinDerive { span: Span, meta_item: &MetaItem, item: Annotatable, - ) -> Vec { + ) -> ExpandResult, Annotatable> { // FIXME: Built-in derives often forget to give spans contexts, // so we are doing it here in a centralized way. let span = ecx.with_def_site_ctxt(span); let mut items = Vec::new(); (self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a)); - items + ExpandResult::Ready(items) } } diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 55e9c70d637..3782746a57d 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -258,8 +258,17 @@ impl Annotatable { } } -// `meta_item` is the annotation, and `item` is the item being modified. -// FIXME Decorators should follow the same pattern too. +/// Result of an expansion that may need to be retried. +/// Consider using this for non-`MultiItemModifier` expanders as well. +pub enum ExpandResult { + /// Expansion produced a result (possibly dummy). + Ready(T), + /// Expansion could not produce a result and needs to be retried. + /// The string is an explanation that will be printed if we are stuck in an infinite retry loop. + Retry(U, String), +} + +// `meta_item` is the attribute, and `item` is the item being modified. pub trait MultiItemModifier { fn expand( &self, @@ -267,7 +276,7 @@ pub trait MultiItemModifier { span: Span, meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec; + ) -> ExpandResult, Annotatable>; } impl MultiItemModifier for F @@ -280,8 +289,8 @@ where span: Span, meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec { - self(ecx, span, meta_item, item) + ) -> ExpandResult, Annotatable> { + ExpandResult::Ready(self(ecx, span, meta_item, item)) } } diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index effa89e8bfb..f2af6755517 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -408,7 +408,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let invoc = if let Some(invoc) = invocations.pop() { + let (invoc, res) = if let Some(invoc) = invocations.pop() { invoc } else { self.resolve_imports(); @@ -420,30 +420,51 @@ impl<'a, 'b> MacroExpander<'a, 'b> { continue; }; - let eager_expansion_root = - if self.monotonic { invoc.expansion_data.id } else { orig_expansion_data.id }; - let res = match self.cx.resolver.resolve_macro_invocation( - &invoc, - eager_expansion_root, - force, - ) { - Ok(res) => res, - Err(Indeterminate) => { - undetermined_invocations.push(invoc); - continue; + let res = match res { + Some(res) => res, + None => { + let eager_expansion_root = if self.monotonic { + invoc.expansion_data.id + } else { + orig_expansion_data.id + }; + match self.cx.resolver.resolve_macro_invocation( + &invoc, + eager_expansion_root, + force, + ) { + Ok(res) => res, + Err(Indeterminate) => { + // Cannot resolve, will retry this invocation later. + undetermined_invocations.push((invoc, None)); + continue; + } + } } }; - progress = true; let ExpansionData { depth, id: expn_id, .. } = invoc.expansion_data; self.cx.current_expansion = invoc.expansion_data.clone(); // FIXME(jseyfried): Refactor out the following logic let (expanded_fragment, new_invocations) = match res { - InvocationRes::Single(ext) => { - let fragment = self.expand_invoc(invoc, &ext.kind); - self.collect_invocations(fragment, &[]) - } + InvocationRes::Single(ext) => match self.expand_invoc(invoc, &ext.kind) { + ExpandResult::Ready(fragment) => self.collect_invocations(fragment, &[]), + ExpandResult::Retry(invoc, explanation) => { + if force { + // We are stuck, stop retrying and produce a dummy fragment. + let span = invoc.span(); + self.cx.span_err(span, &explanation); + let fragment = invoc.fragment_kind.dummy(span); + self.collect_invocations(fragment, &[]) + } else { + // Cannot expand, will retry this invocation later. + undetermined_invocations + .push((invoc, Some(InvocationRes::Single(ext)))); + continue; + } + } + }, InvocationRes::DeriveContainer(_exts) => { // FIXME: Consider using the derive resolutions (`_exts`) immediately, // instead of enqueuing the derives to be resolved again later. @@ -463,14 +484,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { for path in derives { 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, - expansion_data: ExpansionData { - id: expn_id, - ..invoc.expansion_data.clone() + invocations.push(( + Invocation { + kind: InvocationKind::Derive { path, item: item.clone() }, + fragment_kind: invoc.fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + ..invoc.expansion_data.clone() + }, }, - }); + None, + )); } let fragment = invoc.fragment_kind.expect_from_annotatables(::std::iter::once(item)); @@ -478,6 +502,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } }; + progress = true; if expanded_fragments.len() < depth { expanded_fragments.push(Vec::new()); } @@ -535,7 +560,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { &mut self, mut fragment: AstFragment, extra_placeholders: &[NodeId], - ) -> (AstFragment, Vec) { + ) -> (AstFragment, Vec<(Invocation, Option)>) { // Resolve `$crate`s in the fragment for pretty-printing. self.cx.resolver.resolve_dollar_crates(); @@ -635,13 +660,17 @@ impl<'a, 'b> MacroExpander<'a, 'b> { self.cx.trace_macros_diag(); } - fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtensionKind) -> AstFragment { + fn expand_invoc( + &mut self, + invoc: Invocation, + ext: &SyntaxExtensionKind, + ) -> ExpandResult { if self.cx.current_expansion.depth > self.cx.ecfg.recursion_limit { self.error_recursion_limit_reached(); } let (fragment_kind, span) = (invoc.fragment_kind, invoc.span()); - match invoc.kind { + ExpandResult::Ready(match invoc.kind { InvocationKind::Bang { mac, .. } => match ext { SyntaxExtensionKind::Bang(expander) => { self.gate_proc_macro_expansion_kind(span, fragment_kind); @@ -663,7 +692,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } _ => unreachable!(), }, - InvocationKind::Attr { attr, mut item, .. } => match ext { + InvocationKind::Attr { attr, mut item, derives, after_derive } => match ext { SyntaxExtensionKind::Attr(expander) => { self.gate_proc_macro_input(&item); self.gate_proc_macro_attr_item(span, &item); @@ -679,8 +708,25 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::LegacyAttr(expander) => { match validate_attr::parse_meta(self.cx.parse_sess, &attr) { Ok(meta) => { - let item = expander.expand(self.cx, span, &meta, item); - fragment_kind.expect_from_annotatables(item) + let items = match expander.expand(self.cx, span, &meta, item) { + ExpandResult::Ready(items) => items, + ExpandResult::Retry(item, explanation) => { + // Reassemble the original invocation for retrying. + return ExpandResult::Retry( + Invocation { + kind: InvocationKind::Attr { + attr, + item, + derives, + after_derive, + }, + ..invoc + }, + explanation, + ); + } + }; + fragment_kind.expect_from_annotatables(items) } Err(mut err) => { err.emit(); @@ -702,19 +748,31 @@ impl<'a, 'b> MacroExpander<'a, 'b> { SyntaxExtensionKind::Derive(expander) | SyntaxExtensionKind::LegacyDerive(expander) => { if !item.derive_allowed() { - return fragment_kind.dummy(span); + return ExpandResult::Ready(fragment_kind.dummy(span)); } if let SyntaxExtensionKind::Derive(..) = ext { self.gate_proc_macro_input(&item); } let meta = ast::MetaItem { kind: ast::MetaItemKind::Word, span, path }; - let items = expander.expand(self.cx, span, &meta, item); + let items = match expander.expand(self.cx, span, &meta, item) { + ExpandResult::Ready(items) => items, + ExpandResult::Retry(item, explanation) => { + // Reassemble the original invocation for retrying. + return ExpandResult::Retry( + Invocation { + kind: InvocationKind::Derive { path: meta.path, item }, + ..invoc + }, + explanation, + ); + } + }; fragment_kind.expect_from_annotatables(items) } _ => unreachable!(), }, InvocationKind::DeriveContainer { .. } => unreachable!(), - } + }) } fn gate_proc_macro_attr_item(&self, span: Span, item: &Annotatable) { @@ -933,7 +991,7 @@ pub fn ensure_complete_parse<'a>( struct InvocationCollector<'a, 'b> { cx: &'a mut ExtCtxt<'b>, cfg: StripUnconfigured<'a>, - invocations: Vec, + invocations: Vec<(Invocation, Option)>, monotonic: bool, } @@ -955,15 +1013,18 @@ impl<'a, 'b> InvocationCollector<'a, 'b> { }; let expn_id = ExpnId::fresh(expn_data); let vis = kind.placeholder_visibility(); - self.invocations.push(Invocation { - kind, - fragment_kind, - expansion_data: ExpansionData { - id: expn_id, - depth: self.cx.current_expansion.depth + 1, - ..self.cx.current_expansion.clone() + self.invocations.push(( + Invocation { + kind, + fragment_kind, + expansion_data: ExpansionData { + id: expn_id, + depth: self.cx.current_expansion.depth + 1, + ..self.cx.current_expansion.clone() + }, }, - }); + None, + )); placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis) } diff --git a/src/librustc_expand/proc_macro.rs b/src/librustc_expand/proc_macro.rs index 84a546345bb..cb9afa4cd4f 100644 --- a/src/librustc_expand/proc_macro.rs +++ b/src/librustc_expand/proc_macro.rs @@ -79,7 +79,7 @@ impl MultiItemModifier for ProcMacroDerive { span: Span, _meta_item: &ast::MetaItem, item: Annotatable, - ) -> Vec { + ) -> ExpandResult, Annotatable> { let item = match item { Annotatable::Arm(..) | Annotatable::Field(..) @@ -99,7 +99,7 @@ impl MultiItemModifier for ProcMacroDerive { "proc-macro derives may only be \ applied to a struct, enum, or union", ); - return Vec::new(); + return ExpandResult::Ready(Vec::new()); } }; match item.kind { @@ -110,7 +110,7 @@ impl MultiItemModifier for ProcMacroDerive { "proc-macro derives may only be \ applied to a struct, enum, or union", ); - return Vec::new(); + return ExpandResult::Ready(Vec::new()); } } @@ -158,7 +158,7 @@ impl MultiItemModifier for ProcMacroDerive { FatalError.raise(); } - items + ExpandResult::Ready(items) } } From 2e6528961c44a4f3841fd319af71f1d1a6af029c Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 10 Mar 2020 00:56:20 +0300 Subject: [PATCH 0939/1250] builtin_macros: Add attribute macro `#[cfg_accessible(path)]` --- src/libcore/macros/mod.rs | 12 +++++ src/libcore/prelude/v1.rs | 9 ++++ src/librustc_builtin_macros/cfg_accessible.rs | 54 +++++++++++++++++++ src/librustc_builtin_macros/lib.rs | 2 + src/librustc_expand/base.rs | 1 + src/librustc_resolve/macros.rs | 36 +++++++++++++ src/librustc_span/symbol.rs | 1 + src/libstd/lib.rs | 1 + src/libstd/prelude/v1.rs | 9 ++++ .../cfg_accessible-input-validation.rs | 24 +++++++++ .../cfg_accessible-input-validation.stderr | 44 +++++++++++++++ .../cfg_accessible-stuck.rs | 9 ++++ .../cfg_accessible-stuck.stderr | 14 +++++ .../cfg_accessible-unstable.rs | 2 + .../cfg_accessible-unstable.stderr | 12 +++++ .../conditional-compilation/cfg_accessible.rs | 43 +++++++++++++++ .../cfg_accessible.stderr | 38 +++++++++++++ 17 files changed, 311 insertions(+) create mode 100644 src/librustc_builtin_macros/cfg_accessible.rs create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-stuck.rs create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-unstable.rs create mode 100644 src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr create mode 100644 src/test/ui/conditional-compilation/cfg_accessible.rs create mode 100644 src/test/ui/conditional-compilation/cfg_accessible.stderr diff --git a/src/libcore/macros/mod.rs b/src/libcore/macros/mod.rs index 76e58f0cc62..3b615a5246c 100644 --- a/src/libcore/macros/mod.rs +++ b/src/libcore/macros/mod.rs @@ -1383,6 +1383,18 @@ pub(crate) mod builtin { /* compiler built-in */ } + /// Keeps the item it's applied to if the passed path is accessible, and removes it otherwise. + #[cfg(not(bootstrap))] + #[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" + )] + #[rustc_builtin_macro] + pub macro cfg_accessible($item:item) { + /* compiler built-in */ + } + /// Unstable implementation detail of the `rustc` compiler, do not use. #[rustc_builtin_macro] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/prelude/v1.rs b/src/libcore/prelude/v1.rs index 66b5a90b77b..c91370b2719 100644 --- a/src/libcore/prelude/v1.rs +++ b/src/libcore/prelude/v1.rs @@ -67,3 +67,12 @@ pub use crate::{ pub use crate::macros::builtin::{ bench, global_allocator, test, test_case, RustcDecodable, RustcEncodable, }; + +#[cfg(not(bootstrap))] +#[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" +)] +#[doc(no_inline)] +pub use crate::macros::builtin::cfg_accessible; diff --git a/src/librustc_builtin_macros/cfg_accessible.rs b/src/librustc_builtin_macros/cfg_accessible.rs new file mode 100644 index 00000000000..3607a4d0d15 --- /dev/null +++ b/src/librustc_builtin_macros/cfg_accessible.rs @@ -0,0 +1,54 @@ +//! Implementation of the `#[cfg_accessible(path)]` attribute macro. + +use rustc_ast::ast; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; +use rustc_feature::AttributeTemplate; +use rustc_parse::validate_attr; +use rustc_span::symbol::sym; +use rustc_span::Span; + +crate struct Expander; + +fn validate_input<'a>(ecx: &mut ExtCtxt<'_>, mi: &'a ast::MetaItem) -> Option<&'a ast::Path> { + match mi.meta_item_list() { + None => {} + Some([]) => ecx.span_err(mi.span, "`cfg_accessible` path is not specified"), + Some([_, .., l]) => ecx.span_err(l.span(), "multiple `cfg_accessible` paths are specified"), + Some([nmi]) => match nmi.meta_item() { + None => ecx.span_err(nmi.span(), "`cfg_accessible` path cannot be a literal"), + Some(mi) => { + if !mi.is_word() { + ecx.span_err(mi.span, "`cfg_accessible` path cannot accept arguments"); + } + return Some(&mi.path); + } + }, + } + None +} + +impl MultiItemModifier for Expander { + fn expand( + &self, + ecx: &mut ExtCtxt<'_>, + _span: Span, + meta_item: &ast::MetaItem, + item: Annotatable, + ) -> ExpandResult, Annotatable> { + let template = AttributeTemplate { list: Some("path"), ..Default::default() }; + let attr = &ecx.attribute(meta_item.clone()); + validate_attr::check_builtin_attribute(ecx.parse_sess, attr, sym::cfg_accessible, template); + + let path = match validate_input(ecx, meta_item) { + Some(path) => path, + None => return ExpandResult::Ready(Vec::new()), + }; + + let failure_msg = "cannot determine whether the path is accessible or not"; + match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) { + Ok(true) => ExpandResult::Ready(vec![item]), + Ok(false) => ExpandResult::Ready(Vec::new()), + Err(_) => ExpandResult::Retry(item, failure_msg.into()), + } + } +} diff --git a/src/librustc_builtin_macros/lib.rs b/src/librustc_builtin_macros/lib.rs index 9a8b0a87cb7..26a59c6b1be 100644 --- a/src/librustc_builtin_macros/lib.rs +++ b/src/librustc_builtin_macros/lib.rs @@ -22,6 +22,7 @@ use rustc_span::symbol::sym; mod asm; mod assert; mod cfg; +mod cfg_accessible; mod compile_error; mod concat; mod concat_idents; @@ -85,6 +86,7 @@ pub fn register_builtin_macros(resolver: &mut dyn Resolver, edition: Edition) { register_attr! { bench: test::expand_bench, + cfg_accessible: cfg_accessible::Expander, global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 3782746a57d..4839651ac84 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -897,6 +897,7 @@ pub trait Resolver { fn has_derive_copy(&self, expn_id: ExpnId) -> bool; fn add_derive_copy(&mut self, expn_id: ExpnId); + fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result; } #[derive(Clone)] diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e11aec90669..4e41ea82c47 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -339,6 +339,42 @@ impl<'a> base::Resolver for Resolver<'a> { fn add_derive_copy(&mut self, expn_id: ExpnId) { self.containers_deriving_copy.insert(expn_id); } + + // The function that implements the resolution logic of `#[cfg_accessible(path)]`. + // Returns true if the path can certainly be resolved in one of three namespaces, + // returns false if the path certainly cannot be resolved in any of the three namespaces. + // Returns `Indeterminate` if we cannot give a certain answer yet. + fn cfg_accessible(&mut self, expn_id: ExpnId, path: &ast::Path) -> Result { + let span = path.span; + let path = &Segment::from_path(path); + let parent_scope = self.invocation_parent_scopes[&expn_id]; + + let mut indeterminate = false; + for ns in [TypeNS, ValueNS, MacroNS].iter().copied() { + match self.resolve_path(path, Some(ns), &parent_scope, false, span, CrateLint::No) { + PathResult::Module(ModuleOrUniformRoot::Module(_)) => return Ok(true), + PathResult::NonModule(partial_res) if partial_res.unresolved_segments() == 0 => { + return Ok(true); + } + PathResult::Indeterminate => indeterminate = true, + // FIXME: `resolve_path` is not ready to report partially resolved paths + // correctly, so we just report an error if the path was reported as unresolved. + // This needs to be fixed for `cfg_accessible` to be useful. + PathResult::NonModule(..) | PathResult::Failed { .. } => {} + PathResult::Module(_) => panic!("unexpected path resolution"), + } + } + + if indeterminate { + return Err(Indeterminate); + } + + self.session + .struct_span_err(span, "not sure whether the path is accessible or not") + .span_note(span, "`cfg_accessible` is not fully implemented") + .emit(); + Ok(false) + } } impl<'a> Resolver<'a> { diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index c39f9f360c0..55284e73efc 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -181,6 +181,7 @@ symbols! { caller_location, cdylib, cfg, + cfg_accessible, cfg_attr, cfg_attr_multi, cfg_doctest, diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 784868b52e5..9950a813255 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -240,6 +240,7 @@ #![feature(atomic_mut_ptr)] #![feature(box_syntax)] #![feature(c_variadic)] +#![cfg_attr(not(bootstrap), feature(cfg_accessible))] #![feature(cfg_target_has_atomic)] #![feature(cfg_target_thread_local)] #![feature(char_error_internals)] diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index 7c0efe828c2..6712f5ba580 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -53,6 +53,15 @@ pub use core::prelude::v1::{ PartialEq, PartialOrd, RustcDecodable, RustcEncodable, }; +#[cfg(not(bootstrap))] +#[unstable( + feature = "cfg_accessible", + issue = "64797", + reason = "`cfg_accessible` is not fully implemented" +)] +#[doc(hidden)] +pub use core::prelude::v1::cfg_accessible; + // The file so far is equivalent to src/libcore/prelude/v1.rs, // and below to src/liballoc/prelude.rs. // Those files are duplicated rather than using glob imports diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs new file mode 100644 index 00000000000..c51c908a426 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.rs @@ -0,0 +1,24 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible] //~ ERROR malformed `cfg_accessible` attribute input +struct S1; + +#[cfg_accessible = "value"] //~ ERROR malformed `cfg_accessible` attribute input +struct S2; + +#[cfg_accessible()] //~ ERROR `cfg_accessible` path is not specified +struct S3; + +#[cfg_accessible(std, core)] //~ ERROR multiple `cfg_accessible` paths are specified +struct S4; + +#[cfg_accessible("std")] //~ ERROR `cfg_accessible` path cannot be a literal +struct S5; + +#[cfg_accessible(std = "value")] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S6; + +#[cfg_accessible(std(value))] //~ ERROR `cfg_accessible` path cannot accept arguments +struct S7; + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr new file mode 100644 index 00000000000..86706c76635 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-input-validation.stderr @@ -0,0 +1,44 @@ +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:3:1 + | +LL | #[cfg_accessible] + | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: malformed `cfg_accessible` attribute input + --> $DIR/cfg_accessible-input-validation.rs:6:1 + | +LL | #[cfg_accessible = "value"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[cfg_accessible(path)]` + +error: `cfg_accessible` path is not specified + --> $DIR/cfg_accessible-input-validation.rs:9:1 + | +LL | #[cfg_accessible()] + | ^^^^^^^^^^^^^^^^^^^ + +error: multiple `cfg_accessible` paths are specified + --> $DIR/cfg_accessible-input-validation.rs:12:23 + | +LL | #[cfg_accessible(std, core)] + | ^^^^ + +error: `cfg_accessible` path cannot be a literal + --> $DIR/cfg_accessible-input-validation.rs:15:18 + | +LL | #[cfg_accessible("std")] + | ^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:18:18 + | +LL | #[cfg_accessible(std = "value")] + | ^^^^^^^^^^^^^ + +error: `cfg_accessible` path cannot accept arguments + --> $DIR/cfg_accessible-input-validation.rs:21:18 + | +LL | #[cfg_accessible(std(value))] + | ^^^^^^^^^^ + +error: aborting due to 7 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs new file mode 100644 index 00000000000..8bc93fa3243 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.rs @@ -0,0 +1,9 @@ +#![feature(cfg_accessible)] + +#[cfg_accessible(Z)] //~ ERROR cannot determine whether the path is accessible or not +struct S; + +#[cfg_accessible(S)] //~ ERROR cannot determine whether the path is accessible or not +struct Z; + +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr new file mode 100644 index 00000000000..9641441a819 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-stuck.stderr @@ -0,0 +1,14 @@ +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-stuck.rs:6:1 + | +LL | #[cfg_accessible(S)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: cannot determine whether the path is accessible or not + --> $DIR/cfg_accessible-stuck.rs:3:1 + | +LL | #[cfg_accessible(Z)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs new file mode 100644 index 00000000000..e9247e67a2a --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.rs @@ -0,0 +1,2 @@ +#[cfg_accessible(std)] //~ ERROR use of unstable library feature 'cfg_accessible' +fn main() {} diff --git a/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr new file mode 100644 index 00000000000..2f55b9559c7 --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible-unstable.stderr @@ -0,0 +1,12 @@ +error[E0658]: use of unstable library feature 'cfg_accessible': `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible-unstable.rs:1:3 + | +LL | #[cfg_accessible(std)] + | ^^^^^^^^^^^^^^ + | + = note: see issue #64797 for more information + = help: add `#![feature(cfg_accessible)]` 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/conditional-compilation/cfg_accessible.rs b/src/test/ui/conditional-compilation/cfg_accessible.rs new file mode 100644 index 00000000000..07b0be5b1ae --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible.rs @@ -0,0 +1,43 @@ +#![feature(cfg_accessible)] + +mod m { + pub struct ExistingPublic; + struct ExistingPrivate; +} + +#[cfg_accessible(m::ExistingPublic)] +struct ExistingPublic; + +// FIXME: Not implemented yet. +#[cfg_accessible(m::ExistingPrivate)] //~ ERROR not sure whether the path is accessible or not +struct ExistingPrivate; + +// FIXME: Not implemented yet. +#[cfg_accessible(m::NonExistent)] //~ ERROR not sure whether the path is accessible or not +struct ExistingPrivate; + +#[cfg_accessible(n::AccessibleExpanded)] // OK, `cfg_accessible` can wait and retry. +struct AccessibleExpanded; + +macro_rules! generate_accessible_expanded { + () => { + mod n { + pub struct AccessibleExpanded; + } + }; +} + +generate_accessible_expanded!(); + +struct S { + field: u8, +} + +// FIXME: Not implemented yet. +#[cfg_accessible(S::field)] //~ ERROR not sure whether the path is accessible or not +struct Field; + +fn main() { + ExistingPublic; + AccessibleExpanded; +} diff --git a/src/test/ui/conditional-compilation/cfg_accessible.stderr b/src/test/ui/conditional-compilation/cfg_accessible.stderr new file mode 100644 index 00000000000..167765cd66e --- /dev/null +++ b/src/test/ui/conditional-compilation/cfg_accessible.stderr @@ -0,0 +1,38 @@ +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:12:18 + | +LL | #[cfg_accessible(m::ExistingPrivate)] + | ^^^^^^^^^^^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:12:18 + | +LL | #[cfg_accessible(m::ExistingPrivate)] + | ^^^^^^^^^^^^^^^^^^ + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:16:18 + | +LL | #[cfg_accessible(m::NonExistent)] + | ^^^^^^^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:16:18 + | +LL | #[cfg_accessible(m::NonExistent)] + | ^^^^^^^^^^^^^^ + +error: not sure whether the path is accessible or not + --> $DIR/cfg_accessible.rs:37:18 + | +LL | #[cfg_accessible(S::field)] + | ^^^^^^^^ + | +note: `cfg_accessible` is not fully implemented + --> $DIR/cfg_accessible.rs:37:18 + | +LL | #[cfg_accessible(S::field)] + | ^^^^^^^^ + +error: aborting due to 3 previous errors + From 906bb8d0e8bbd026fc933fe3f5b829be5e4ac69e Mon Sep 17 00:00:00 2001 From: YI Date: Tue, 10 Mar 2020 01:51:08 +0800 Subject: [PATCH 0940/1250] fix #62456 --- src/librustc_typeck/check/expr.rs | 18 +++++++++++++----- .../ui/const-generics/issues/issue-62456.rs | 9 +++++++++ .../const-generics/issues/issue-62456.stderr | 16 ++++++++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/test/ui/const-generics/issues/issue-62456.rs create mode 100644 src/test/ui/const-generics/issues/issue-62456.stderr diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 7570d9d4b28..859a219c95a 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -18,6 +18,7 @@ use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; +use rustc::mir::interpret::ErrorHandled; use rustc::ty; use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability}; use rustc::ty::Ty; @@ -1039,11 +1040,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if element_ty.references_error() { - tcx.types.err - } else if let Ok(count) = count { - tcx.mk_ty(ty::Array(t, count)) - } else { - tcx.types.err + return tcx.types.err; + } + match count { + Ok(count) => tcx.mk_ty(ty::Array(t, count)), + Err(ErrorHandled::TooGeneric) => { + self.tcx.sess.span_err( + tcx.def_span(count_def_id), + "array lengths can't depend on generic parameters", + ); + tcx.types.err + } + Err(ErrorHandled::Reported) => tcx.types.err, } } diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs new file mode 100644 index 00000000000..c5e6fe9104b --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -0,0 +1,9 @@ +#![feature(const_generics)] +//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash + +fn foo() { + let _ = [0u64; N + 1]; + //~^ ERROR array lengths can't depend on generic parameters +} + +fn main() {} diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr new file mode 100644 index 00000000000..9cdccf8407c --- /dev/null +++ b/src/test/ui/const-generics/issues/issue-62456.stderr @@ -0,0 +1,16 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/issue-62456.rs:1:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error: array lengths can't depend on generic parameters + --> $DIR/issue-62456.rs:5:20 + | +LL | let _ = [0u64; N + 1]; + | ^^^^^ + +error: aborting due to previous error + From 0982c58edc5b9fe4cfc8b22bc3edaa95e4f5c638 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 21:40:00 -0400 Subject: [PATCH 0941/1250] update tidy documentation to recommend ./x.py test tidy --- src/tools/tidy/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 0b433965051..909529d7307 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -2,7 +2,7 @@ //! //! This program runs all of the various tidy checks for style, cleanliness, //! etc. This is run by default on `./x.py test` and as part of the auto -//! builders. The tidy checks can be executed with `./x.py test src/tools/tidy`. +//! builders. The tidy checks can be executed with `./x.py test tidy`. #![deny(warnings)] From 259b06e33f533096f0b46beca8719fd4afceb78b Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 21:55:56 -0400 Subject: [PATCH 0942/1250] add documentation of x.py tool testing --- src/bootstrap/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md index c501378bff5..87da7327fe6 100644 --- a/src/bootstrap/README.md +++ b/src/bootstrap/README.md @@ -55,6 +55,9 @@ The script accepts commands, flags, and arguments to determine what to do: # run all unit tests ./x.py test + # execute tool tests + ./x.py test tidy + # execute the UI test suite ./x.py test src/test/ui From 9f734c978c4c32eea552d45fef582804c1d2b9bf Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 22:04:59 -0400 Subject: [PATCH 0943/1250] Add documentation of tool testing with x.py script --- src/bootstrap/flags.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 516be6a30c2..a8b76c44f79 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -359,7 +359,7 @@ Arguments: subcommand_help.push_str( "\n Arguments: - This subcommand accepts a number of paths to directories to tests that + This subcommand accepts a number of paths to test directories that should be compiled and run. For example: ./x.py test src/test/ui @@ -367,11 +367,15 @@ Arguments: ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll - + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; just like `build src/libstd --stage N` it tests the compiler produced by the previous stage. + Execute tool tests with a tool name argument: + + ./x.py test tidy + If no arguments are passed then the complete artifacts for that stage are compiled and tested. From 4922b683de170c70260b73426ccf16172fa63b7f Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 22:15:41 -0400 Subject: [PATCH 0944/1250] remove trailing whitespace (tidy) --- src/bootstrap/flags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a8b76c44f79..4b04ee84c31 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -367,7 +367,7 @@ Arguments: ./x.py test src/libstd --stage 0 --no-doc ./x.py test src/test/ui --bless ./x.py test src/test/ui --compare-mode nll - + Note that `test src/test/* --stage N` does NOT depend on `build src/rustc --stage N`; just like `build src/libstd --stage N` it tests the compiler produced by the previous stage. From 0a0c850d732666b1205a6f567c38e05239c65848 Mon Sep 17 00:00:00 2001 From: YI Date: Tue, 10 Mar 2020 10:54:48 +0800 Subject: [PATCH 0945/1250] fix test failure due to earlier emitted error --- .../ui/issues/issue-69602-type-err-during-codegen-ice.rs | 1 + .../issues/issue-69602-type-err-during-codegen-ice.stderr | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs index 2c5257ce063..d060f26fb2a 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.rs @@ -19,4 +19,5 @@ impl TraitB for B { //~ ERROR not all trait items implemented, missing: `MyA` fn main() { let _ = [0; B::VALUE]; + //~^ ERROR array lengths can't depend on generic parameters } diff --git a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr index 8ae0f8b804c..c6b2b4d27a2 100644 --- a/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr +++ b/src/test/ui/issues/issue-69602-type-err-during-codegen-ice.stderr @@ -13,7 +13,13 @@ LL | type MyA: TraitA; LL | impl TraitB for B { | ^^^^^^^^^^^^^^^^^ missing `MyA` in implementation -error: aborting due to 2 previous errors +error: array lengths can't depend on generic parameters + --> $DIR/issue-69602-type-err-during-codegen-ice.rs:21:17 + | +LL | let _ = [0; B::VALUE]; + | ^^^^^^^^ + +error: aborting due to 3 previous errors Some errors have detailed explanations: E0046, E0437. For more information about an error, try `rustc --explain E0046`. From c60d581eb15d6fbe17a657da7c1de4dc82b70b68 Mon Sep 17 00:00:00 2001 From: Chris Simpkins Date: Mon, 9 Mar 2020 23:00:41 -0400 Subject: [PATCH 0946/1250] update x.py tidy testing command --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d6840b20c89..a58d4f2a7c6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -142,7 +142,7 @@ the issue in question. Please make sure your pull request is in compliance with Rust's style guidelines by running - $ python x.py test src/tools/tidy + $ python x.py test tidy Make this check before every pull request (and every new commit in a pull request); you can add [git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) From 6f2c01bcfbdcaa9686ceb37cce29564a2d662828 Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Tue, 10 Mar 2020 08:33:14 +0530 Subject: [PATCH 0947/1250] Add long error explanation for E0739 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0739.md | 13 +++++++++++++ .../ui/rfc-2091-track-caller/only-for-fns.stderr | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/librustc_error_codes/error_codes/E0739.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 11d1209923f..0e14e2196ca 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -411,6 +411,7 @@ E0735: include_str!("./error_codes/E0735.md"), E0736: include_str!("./error_codes/E0736.md"), E0737: include_str!("./error_codes/E0737.md"), E0738: include_str!("./error_codes/E0738.md"), +E0739: include_str!("./error_codes/E0739.md"), E0740: include_str!("./error_codes/E0740.md"), E0741: include_str!("./error_codes/E0741.md"), E0742: include_str!("./error_codes/E0742.md"), @@ -610,5 +611,4 @@ E0748: include_str!("./error_codes/E0748.md"), E0722, // Malformed `#[optimize]` attribute E0724, // `#[ffi_returns_twice]` is only allowed in foreign functions E0726, // non-explicit (not `'_`) elided lifetime in unsupported position - E0739, // invalid track_caller application/syntax } diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md new file mode 100644 index 00000000000..d3016f53a94 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -0,0 +1,13 @@ +`#[track_caller]` can not be applied on struct. + +Erroneous code example: + +```compile_fail,E0739 +#![feature(track_caller)] +#[track_caller] +struct Bar { + a: u8, +} +``` + +[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md diff --git a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr index 7becb9c5b60..c2fb8fa1eb6 100644 --- a/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr +++ b/src/test/ui/rfc-2091-track-caller/only-for-fns.stderr @@ -8,3 +8,4 @@ LL | struct S; error: aborting due to previous error +For more information about this error, try `rustc --explain E0739`. From a56196205b1919bee851bdfd7e76e9b3ae5090db Mon Sep 17 00:00:00 2001 From: Christopher Durham Date: Mon, 9 Mar 2020 23:07:04 -0400 Subject: [PATCH 0948/1250] Vec::new is const tstable in 1.39 not 1.32 --- src/liballoc/vec.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 61416f2b906..f661b830428 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -317,7 +317,7 @@ impl Vec { /// let mut vec: Vec = Vec::new(); /// ``` #[inline] - #[rustc_const_stable(feature = "const_vec_new", since = "1.32.0")] + #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")] #[stable(feature = "rust1", since = "1.0.0")] pub const fn new() -> Vec { Vec { buf: RawVec::NEW, len: 0 } From 761c8c1eefa8cecb1a55628674690c53cc8c473b Mon Sep 17 00:00:00 2001 From: Ayush Kumar Mishra Date: Tue, 10 Mar 2020 09:07:29 +0530 Subject: [PATCH 0949/1250] Removed trailing whitespace --- src/librustc_error_codes/error_codes/E0739.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0739.md b/src/librustc_error_codes/error_codes/E0739.md index d3016f53a94..707751066ed 100644 --- a/src/librustc_error_codes/error_codes/E0739.md +++ b/src/librustc_error_codes/error_codes/E0739.md @@ -1,4 +1,4 @@ -`#[track_caller]` can not be applied on struct. +`#[track_caller]` can not be applied on struct. Erroneous code example: From fd302f46dcf80cc23358f0f31744d6083a6997c1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 13 Nov 2019 13:01:43 +0100 Subject: [PATCH 0950/1250] Store `TokenStream` in `rmeta::MacroDef`. This removes a hack from `load_macro_untracked` in which parsing is used. --- Cargo.lock | 2 - src/librustc/dep_graph/dep_node.rs | 2 + src/librustc/lint.rs | 11 +---- src/librustc/middle/stability.rs | 2 +- src/librustc_errors/emitter.rs | 16 ++++---- src/librustc_expand/mbe/macro_rules.rs | 6 +-- src/librustc_macros/src/symbols.rs | 4 ++ src/librustc_metadata/Cargo.toml | 2 - src/librustc_metadata/rmeta/decoder.rs | 4 +- .../rmeta/decoder/cstore_impl.rs | 41 +++++++------------ src/librustc_metadata/rmeta/encoder.rs | 3 +- src/librustc_metadata/rmeta/mod.rs | 3 +- src/librustc_span/lib.rs | 22 +--------- src/librustc_span/source_map.rs | 6 +++ src/librustc_typeck/check/demand.rs | 6 +-- src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/sources.rs | 2 +- 17 files changed, 51 insertions(+), 83 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8505470a663..aefd40bfaa5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3891,14 +3891,12 @@ dependencies = [ "memmap", "rustc", "rustc_ast", - "rustc_ast_pretty", "rustc_attr", "rustc_data_structures", "rustc_errors", "rustc_expand", "rustc_hir", "rustc_index", - "rustc_parse", "rustc_span", "rustc_target", "serialize", diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index eb7e2871bfc..3f0730169ec 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -111,6 +111,7 @@ macro_rules! define_dep_nodes { ) => ( #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] + #[allow(non_camel_case_types)] pub enum DepKind { $($variant),* } @@ -173,6 +174,7 @@ macro_rules! define_dep_nodes { pub struct DepConstructor; + #[allow(non_camel_case_types)] impl DepConstructor { $( #[inline(always)] diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index 004835b230a..dcc8dcbf219 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -344,15 +344,8 @@ pub fn in_external_macro(sess: &Session, span: Span) -> bool { ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop) => false, ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external" ExpnKind::Macro(MacroKind::Bang, _) => { - 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(expn_data.def_site) { - Ok(code) => !code.starts_with("macro_rules"), - // No snippet means external macro or compiler-builtin expansion. - Err(_) => true, - } + // Dummy span for the `def_site` means it's an external macro. + expn_data.def_site.is_dummy() || sess.source_map().is_imported(expn_data.def_site) } ExpnKind::Macro(..) => true, // definitely a plugin } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 9d3df9623bd..cf917daef83 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -110,7 +110,7 @@ pub fn report_unstable( let span_key = msp.primary_span().and_then(|sp: Span| { if !sp.is_dummy() { let file = sm.lookup_char_pos(sp.lo()).file; - if file.name.is_macros() { None } else { Some(span) } + if file.is_imported() { None } else { Some(span) } } else { None } diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index eb9d4b887ad..b38ea6b4241 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -414,8 +414,8 @@ pub trait Emitter { } // This does a small "fix" for multispans by looking to see if it can find any that - // point directly at <*macros>. Since these are often difficult to read, this - // will change the span to point at the use site. + // point directly at external macros. Since these are often difficult to read, + // this will change the span to point at the use site. fn fix_multispans_in_extern_macros( &self, source_map: &Option>, @@ -427,9 +427,9 @@ pub trait Emitter { } } - // This "fixes" MultiSpans that contain Spans that are pointing to locations inside of - // <*macros>. Since these locations are often difficult to read, we move these Spans from - // <*macros> to their corresponding use site. + // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. + // Since these locations are often difficult to read, + // we move these spans from the external macros to their corresponding use site. fn fix_multispan_in_extern_macros( &self, source_map: &Option>, @@ -440,14 +440,14 @@ pub trait Emitter { None => return, }; - // First, find all the spans in <*macros> and point instead at their use site + // First, find all the spans in external macros and point instead at their use site. let replacements: Vec<(Span, Span)> = span .primary_spans() .iter() .copied() .chain(span.span_labels().iter().map(|sp_label| sp_label.span)) .filter_map(|sp| { - if !sp.is_dummy() && sm.span_to_filename(sp).is_macros() { + if !sp.is_dummy() && sm.is_imported(sp) { let maybe_callsite = sp.source_callsite(); if sp != maybe_callsite { return Some((sp, maybe_callsite)); @@ -457,7 +457,7 @@ pub trait Emitter { }) .collect(); - // After we have them, make sure we replace these 'bad' def sites with their use sites + // After we have them, make sure we replace these 'bad' def sites with their use sites. for (from, to) in replacements { span.replace(from, to); } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 51b172a2114..3040a9aefbb 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -105,10 +105,10 @@ impl<'a> ParserAnyMacro<'a> { if e.span.is_dummy() { // Get around lack of span in error (#30128) e.replace_span_with(site_span); - if parser.sess.source_map().span_to_filename(arm_span).is_real() { + if !parser.sess.source_map().is_imported(arm_span) { e.span_label(arm_span, "in this macro arm"); } - } else if !parser.sess.source_map().span_to_filename(parser.token.span).is_real() { + } else if parser.sess.source_map().is_imported(parser.token.span) { e.span_label(site_span, "in this macro invocation"); } match kind { @@ -297,7 +297,7 @@ fn generic_extension<'cx>( let span = token.span.substitute_dummy(sp); let mut err = cx.struct_span_err(span, &parse_failure_msg(&token)); err.span_label(span, label); - if !def_span.is_dummy() && cx.source_map().span_to_filename(def_span).is_real() { + if !def_span.is_dummy() && !cx.source_map().is_imported(def_span) { err.span_label(cx.source_map().def_span(def_span), "when calling this macro"); } diff --git a/src/librustc_macros/src/symbols.rs b/src/librustc_macros/src/symbols.rs index feddcd5f994..0f8bc432307 100644 --- a/src/librustc_macros/src/symbols.rs +++ b/src/librustc_macros/src/symbols.rs @@ -103,6 +103,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { #value, }); keyword_stream.extend(quote! { + #[allow(non_upper_case_globals)] pub const #name: Symbol = Symbol::new(#counter); }); counter += 1; @@ -120,6 +121,8 @@ pub fn symbols(input: TokenStream) -> TokenStream { #value, }); symbols_stream.extend(quote! { + #[allow(rustc::default_hash_types)] + #[allow(non_upper_case_globals)] pub const #name: Symbol = Symbol::new(#counter); }); counter += 1; @@ -149,6 +152,7 @@ pub fn symbols(input: TokenStream) -> TokenStream { () => { #symbols_stream + #[allow(non_upper_case_globals)] pub const digits_array: &[Symbol; 10] = &[ #digits_stream ]; diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index 8abfb20965e..a8e308c5c9e 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -15,7 +15,6 @@ log = "0.4" memmap = "0.7" smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc = { path = "../librustc" } -rustc_ast_pretty = { path = "../librustc_ast_pretty" } rustc_attr = { path = "../librustc_attr" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } @@ -26,7 +25,6 @@ rustc_serialize = { path = "../libserialize", package = "serialize" } stable_deref_trait = "1.0.0" rustc_ast = { path = "../librustc_ast" } rustc_expand = { path = "../librustc_expand" } -rustc_parse = { path = "../librustc_parse" } rustc_span = { path = "../librustc_span" } [target.'cfg(windows)'.dependencies] diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index a72ee0cbe47..c2a306a0a0c 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -1333,9 +1333,9 @@ impl<'a, 'tcx> CrateMetadata { } } - fn get_macro(&self, id: DefIndex) -> MacroDef { + fn get_macro(&self, id: DefIndex, sess: &Session) -> MacroDef { match self.kind(id) { - EntryKind::MacroDef(macro_def) => macro_def.decode(self), + EntryKind::MacroDef(macro_def) => macro_def.decode((self, sess)), _ => bug!(), } } diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index be229350f3b..8062252df96 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -14,27 +14,22 @@ use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::query::Providers; use rustc::ty::query::QueryConfig; use rustc::ty::{self, TyCtxt}; +use rustc_ast::ast; +use rustc_ast::attr; +use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::ptr::P; +use rustc_ast::tokenstream::DelimSpan; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; -use rustc_parse::parser::emit_unclosed_delims; -use rustc_parse::source_file_to_stream; +use rustc_span::source_map::{self, Span, Spanned}; +use rustc_span::symbol::Symbol; use rustc_data_structures::sync::Lrc; use smallvec::SmallVec; use std::any::Any; use std::sync::Arc; -use rustc_ast::ast; -use rustc_ast::attr; -use rustc_ast::expand::allocator::AllocatorKind; -use rustc_ast::ptr::P; -use rustc_ast::tokenstream::DelimSpan; -use rustc_span::source_map; -use rustc_span::source_map::Spanned; -use rustc_span::symbol::Symbol; -use rustc_span::{FileName, Span}; - macro_rules! provide { (<$lt:tt> $tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $($name:ident => $compute:block)*) => { @@ -419,15 +414,9 @@ impl CStore { return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess)); } - let def = data.get_macro(id.index); - let macro_full_name = data.def_path(id.index).to_string_friendly(|_| data.root.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::with_root_ctxt(source_file.start_pos, source_file.end_pos); - let dspan = DelimSpan::from_single(local_span); - let (body, mut errors) = source_file_to_stream(&sess.parse_sess, source_file, None); - emit_unclosed_delims(&mut errors, &sess.parse_sess); + let span = data.get_span(id.index, sess); + let dspan = DelimSpan::from_single(span); + let rmeta::MacroDef { body, legacy } = data.get_macro(id.index, sess); // Mark the attrs as used let attrs = data.get_item_attrs(id.index, sess); @@ -441,22 +430,20 @@ impl CStore { .data .get_opt_name() .expect("no name in load_macro"); - sess.imported_macro_spans - .borrow_mut() - .insert(local_span, (name.to_string(), data.get_span(id.index, sess))); + sess.imported_macro_spans.borrow_mut().insert(span, (name.to_string(), span)); LoadedMacro::MacroDef( ast::Item { // FIXME: cross-crate hygiene ident: ast::Ident::with_dummy_span(name), id: ast::DUMMY_NODE_ID, - span: local_span, + span, attrs: attrs.iter().cloned().collect(), kind: ast::ItemKind::MacroDef(ast::MacroDef { body: P(ast::MacArgs::Delimited(dspan, ast::MacDelimiter::Brace, body)), - legacy: def.legacy, + legacy, }), - vis: source_map::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited), + vis: source_map::respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited), tokens: None, }, data.root.edition, diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 7624b1d562f..2b04918296d 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1235,10 +1235,9 @@ impl EncodeContext<'tcx> { /// Serialize the text of exported macros fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef<'_>) { - use rustc_ast_pretty::pprust; let def_id = self.tcx.hir().local_def_id(macro_def.hir_id); record!(self.per_def.kind[def_id] <- EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(macro_def.body.clone()), + body: macro_def.body.clone(), legacy: macro_def.legacy, }))); record!(self.per_def.visibility[def_id] <- ty::Visibility::Public); diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 1553b6cf0af..89e26b15d50 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -11,6 +11,7 @@ use rustc::session::config::SymbolManglingVersion; use rustc::session::CrateDisambiguator; use rustc::ty::{self, ReprOptions, Ty}; use rustc_ast::ast; +use rustc_ast::tokenstream::TokenStream; use rustc_attr as attr; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; @@ -324,7 +325,7 @@ struct ModData { #[derive(RustcEncodable, RustcDecodable)] struct MacroDef { - body: String, + body: TokenStream, legacy: bool, } diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 502ea64aab9..1d493da9e5b 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -83,8 +83,6 @@ scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals); )] pub enum FileName { Real(PathBuf), - /// A macro. This includes the full name of the macro, so that there are no clashes. - Macros(String), /// Call to `quote!`. QuoteExpansion(u64), /// Command line. @@ -107,7 +105,6 @@ impl std::fmt::Display for FileName { use FileName::*; match *self { Real(ref path) => write!(fmt, "{}", path.display()), - Macros(ref name) => write!(fmt, "<{} macros>", name), QuoteExpansion(_) => write!(fmt, ""), MacroExpansion(_) => write!(fmt, ""), Anon(_) => write!(fmt, ""), @@ -132,8 +129,7 @@ impl FileName { use FileName::*; match *self { Real(_) => true, - Macros(_) - | Anon(_) + Anon(_) | MacroExpansion(_) | ProcMacroSourceCode(_) | CfgSpec(_) @@ -144,22 +140,6 @@ impl FileName { } } - pub fn is_macros(&self) -> bool { - use FileName::*; - match *self { - Real(_) - | Anon(_) - | MacroExpansion(_) - | ProcMacroSourceCode(_) - | CfgSpec(_) - | CliCrateAttr(_) - | Custom(_) - | QuoteExpansion(_) - | DocTest(_, _) => false, - Macros(_) => true, - } - } - pub fn quote_expansion_source_code(src: &str) -> FileName { let mut hasher = StableHasher::new(); src.hash(&mut hasher); diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index cd2d2c4c3d7..65095c6f131 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -975,6 +975,12 @@ impl SourceMap { _ => None, }) } + + pub fn is_imported(&self, sp: Span) -> bool { + let source_file_index = self.lookup_source_file_idx(sp.lo()); + let source_file = &self.files()[source_file_index]; + source_file.is_imported() + } } #[derive(Clone)] diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 3a2a315a102..6df9d054195 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -373,7 +373,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) -> Option<(Span, &'static str, String)> { let sm = self.sess().source_map(); let sp = expr.span; - if !sm.span_to_filename(sp).is_real() { + if sm.is_imported(sp) { // Ignore if span is from within a macro #41858, #58298. We previously used the macro // call span, but that breaks down when the type error comes from multiple calls down. return None; @@ -523,7 +523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { // We have `&T`, check if what was expected was `T`. If so, // we may want to suggest removing a `&`. - if !sm.span_to_filename(expr.span).is_real() { + if sm.is_imported(expr.span) { if let Ok(code) = sm.span_to_snippet(sp) { if code.starts_with('&') { return Some(( @@ -601,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // 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() { + if self.tcx.sess.source_map().is_imported(expr.span) { // Ignore if span is from within a macro. return false; } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index c64c4769708..31e91dac4d1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1565,7 +1565,7 @@ impl Context { let mut path = String::new(); - // We can safely ignore macros from other libraries + // We can safely ignore synthetic `SourceFile`s. let file = match item.source.filename { FileName::Real(ref path) => path, _ => return None, diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index 79e7d3d783b..86f46b2d7e1 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -35,7 +35,7 @@ impl<'a> DocFolder for SourceCollector<'a> { // If we're including source files, and we haven't seen this file yet, // then we need to render it out to the filesystem. if self.scx.include_sources - // skip all invalid or macro spans + // skip all synthetic "files" && item.source.filename.is_real() // skip non-local items && item.def_id.is_local() From 192d134e804e7d1c0cb9cb7a87c89de55f662f2f Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 14 Nov 2019 11:40:01 +0100 Subject: [PATCH 0951/1250] pacify rustdoc by using better url --- src/test/rustdoc/issue-26606.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/rustdoc/issue-26606.rs b/src/test/rustdoc/issue-26606.rs index 6de419ec571..d2aa4bbbd12 100644 --- a/src/test/rustdoc/issue-26606.rs +++ b/src/test/rustdoc/issue-26606.rs @@ -7,5 +7,5 @@ extern crate issue_26606_macro; // @has issue_26606/constant.FOO.html -// @!has - '//a/@href' '../src/' +// @has - '//a/@href' '../src/issue_26606/auxiliary/issue-26606-macro.rs.html#3' make_item!(FOO); From b3bc4272287f1d245236d92fe1ab3c1f41e967de Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 10 Feb 2020 17:38:51 +0100 Subject: [PATCH 0952/1250] adjust span-api-tests.rs --- src/test/ui/proc-macro/span-api-tests.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs index 3667e14c9e0..cbceea1b4f3 100644 --- a/src/test/ui/proc-macro/span-api-tests.rs +++ b/src/test/ui/proc-macro/span-api-tests.rs @@ -11,7 +11,7 @@ extern crate span_test_macros; extern crate span_api_tests; -use span_api_tests::{reemit, assert_fake_source_file, assert_source_file, macro_stringify}; +use span_api_tests::{reemit, assert_source_file, macro_stringify}; macro_rules! say_hello { ($macname:ident) => ( $macname! { "Hello, world!" }) @@ -25,7 +25,7 @@ reemit_legacy! { assert_source_file! { "Hello, world!" } } -say_hello_extern! { assert_fake_source_file } +say_hello_extern! { assert_source_file } reemit! { assert_source_file! { "Hello, world!" } From cf2d4236eb311b80407678b0527b810ecdd335b7 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 10 Feb 2020 17:37:12 +0100 Subject: [PATCH 0953/1250] --bless some tests --- ...dition-keywords-2015-2018-expansion.stderr | 4 +- .../edition-keywords-2018-2015-parsing.stderr | 6 +- ...dition-keywords-2018-2018-expansion.stderr | 4 +- .../edition-keywords-2018-2018-parsing.stderr | 6 +- .../main.-Zmacro-backtrace.stderr | 104 +++++++------- src/test/ui/macros/unknown-builtin.stderr | 10 +- .../method-on-ambiguous-numeric-type.stderr | 7 +- src/test/ui/proc-macro/mixed-site-span.stderr | 19 +-- src/test/ui/proc-macro/multispan.stderr | 133 ++++-------------- src/test/ui/proc-macro/three-equals.stderr | 19 +-- 10 files changed, 112 insertions(+), 200 deletions(-) diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index f44f81fce71..46db5dbc8b3 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -7,8 +7,8 @@ LL | produces_async! {} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers | -LL | () => (pub fn r#async () { }) - | ^^^^^^^ +LL | r#async + | error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr index 22a7495ca23..e12d1a48463 100644 --- a/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -33,10 +33,10 @@ LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` - --> <::edition_kw_macro_2015::passes_ident macros>:1:22 + --> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23 | -LL | ($ i : ident) => ($ i) - | ^ expected one of `move`, `|`, or `||` +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` | ::: $DIR/edition-keywords-2018-2015-parsing.rs:16:8 | diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index a8fc58fc0cb..2de383d0bca 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -7,8 +7,8 @@ LL | produces_async! {} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers | -LL | () => (pub fn r#async () { }) - | ^^^^^^^ +LL | r#async + | error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr index 7488fcc2e58..110165fc077 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -33,10 +33,10 @@ LL | r#async = consumes_async_raw!(async); | ^^^^^ no rules expected this token in macro call error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` - --> <::edition_kw_macro_2018::passes_ident macros>:1:22 + --> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23 | -LL | ($ i : ident) => ($ i) - | ^ expected one of `move`, `|`, or `||` +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` | ::: $DIR/edition-keywords-2018-2018-parsing.rs:16:8 | diff --git a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr index 41ed545cf16..2f3d48bf039 100644 --- a/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr +++ b/src/test/ui/macro_backtrace/main.-Zmacro-backtrace.stderr @@ -13,66 +13,70 @@ LL | pong!(); error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:10:20 | -LL | / macro_rules! pong { -LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens -LL | | } - | |_- in this expansion of `pong!` +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |__- in this expansion of `pong!` ... -LL | ping!(); - | -------- in this macro invocation +LL | ping!(); + | -------- in this macro invocation | - ::: <::ping::ping macros>:1:1 + ::: $DIR/auxiliary/ping.rs:5:1 | -LL | () => { pong ! () ; } - | --------------------- - | | | - | | in this macro invocation - | in this expansion of `ping!` +LL | / macro_rules! ping { +LL | | () => { +LL | | pong!(); + | | -------- in this macro invocation +LL | | } +LL | | } + | |_- in this expansion of `ping!` error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:10:20 | -LL | / macro_rules! pong { -LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens -LL | | } - | |_- in this expansion of `pong!` (#5) +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |__- in this expansion of `pong!` (#5) ... -LL | deep!(); - | -------- in this macro invocation (#1) +LL | deep!(); + | -------- in this macro invocation (#1) | - ::: <::ping::deep macros>:1:1 + ::: $DIR/auxiliary/ping.rs:5:1 | -LL | () => { foo ! () ; } - | -------------------- - | | | - | | in this macro invocation (#2) - | in this expansion of `deep!` (#1) - | - ::: <::ping::foo macros>:1:1 - | -LL | () => { bar ! () ; } - | -------------------- - | | | - | | in this macro invocation (#3) - | in this expansion of `foo!` (#2) - | - ::: <::ping::bar macros>:1:1 - | -LL | () => { ping ! () ; } - | --------------------- - | | | - | | in this macro invocation (#4) - | in this expansion of `bar!` (#3) - | - ::: <::ping::ping macros>:1:1 - | -LL | () => { pong ! () ; } - | --------------------- - | | | - | | in this macro invocation (#5) - | in this expansion of `ping!` (#4) +LL | / macro_rules! ping { +LL | | () => { +LL | | pong!(); + | | -------- in this macro invocation (#5) +LL | | } +LL | | } + | |_- in this expansion of `ping!` (#4) +... +LL | / macro_rules! deep { +LL | | () => { +LL | | foo!(); + | | ------- in this macro invocation (#2) +LL | | } +LL | | } + | |__- in this expansion of `deep!` (#1) +... +LL | / macro_rules! foo { +LL | | () => { +LL | | bar!(); + | | ------- in this macro invocation (#3) +LL | | } +LL | | } + | |__- in this expansion of `foo!` (#2) +... +LL | / macro_rules! bar { +LL | | () => { +LL | | ping!(); + | | -------- in this macro invocation (#4) +LL | | } +LL | | } + | |__- in this expansion of `bar!` (#3) error: aborting due to 3 previous errors diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr index f1e828a46d8..665e92f2424 100644 --- a/src/test/ui/macros/unknown-builtin.stderr +++ b/src/test/ui/macros/unknown-builtin.stderr @@ -5,10 +5,14 @@ LL | macro_rules! unknown { () => () } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: cannot find a built-in macro with name `line` - --> <::core::macros::builtin::line macros>:1:1 + --> $SRC_DIR/libcore/macros/mod.rs:LL:COL | -LL | () => { } ; - | ^^^^^^^^^^^ +LL | / macro_rules! line { +LL | | () => { +LL | | /* compiler built-in */ +LL | | }; +LL | | } + | |_____^ error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr index 10950834ad3..c6dde67cfeb 100644 --- a/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr +++ b/src/test/ui/methods/method-on-ambiguous-numeric-type.stderr @@ -42,10 +42,13 @@ LL | ($ident:ident) => { let $ident: i32 = 42; } error[E0689]: can't call method `pow` on ambiguous numeric type `{integer}` --> $DIR/method-on-ambiguous-numeric-type.rs:30:9 | -LL | mac!(bar); - | ---------- you must specify a type for this binding, like `i32` LL | bar.pow(2); | ^^^ + | +help: you must specify a type for this binding, like `i32` + | +LL | ($ident:ident) => { let $ident: i32 = 42; } + | ^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/proc-macro/mixed-site-span.stderr b/src/test/ui/proc-macro/mixed-site-span.stderr index c344147ed93..30a4cd7c116 100644 --- a/src/test/ui/proc-macro/mixed-site-span.stderr +++ b/src/test/ui/proc-macro/mixed-site-span.stderr @@ -21,21 +21,10 @@ LL | local_def; | ^^^^^^^^^ not found in this scope error[E0412]: cannot find type `ItemUse` in crate `$crate` - --> $DIR/auxiliary/mixed-site-span.rs:14:1 - | -LL | / pub fn proc_macro_rules(input: TokenStream) -> TokenStream { -LL | | if input.is_empty() { -LL | | let id = |s| TokenTree::from(Ident::new(s, Span::mixed_site())); -LL | | let item_def = id("ItemDef"); -... | -LL | | } -LL | | } - | |_^ not found in `$crate` - | - ::: $DIR/mixed-site-span.rs:26:1 - | -LL | pass_dollar_crate!(); - | --------------------- in this macro invocation + --> $DIR/mixed-site-span.rs:26:1 + | +LL | pass_dollar_crate!(); + | ^^^^^^^^^^^^^^^^^^^^^ not found in `$crate` | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: possible candidate is found in another module, you can import it into scope diff --git a/src/test/ui/proc-macro/multispan.stderr b/src/test/ui/proc-macro/multispan.stderr index c9390a04b9e..4405278528e 100644 --- a/src/test/ui/proc-macro/multispan.stderr +++ b/src/test/ui/proc-macro/multispan.stderr @@ -1,19 +1,8 @@ error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:14:5 - | -LL | hello!(hi); - | ----------- in this macro invocation + --> $DIR/multispan.rs:14:5 + | +LL | hello!(hi); + | ^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:14:12 @@ -23,21 +12,10 @@ LL | hello!(hi); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:17:5 - | -LL | hello!(hi hi); - | -------------- in this macro invocation + --> $DIR/multispan.rs:17:5 + | +LL | hello!(hi hi); + | ^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:17:12 @@ -47,21 +25,10 @@ LL | hello!(hi hi); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:20:5 - | -LL | hello!(hi hi hi); - | ----------------- in this macro invocation + --> $DIR/multispan.rs:20:5 + | +LL | hello!(hi hi hi); + | ^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:20:12 @@ -71,21 +38,10 @@ LL | hello!(hi hi hi); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:23:5 - | -LL | hello!(hi hey hi yo hi beep beep hi hi); - | ---------------------------------------- in this macro invocation + --> $DIR/multispan.rs:23:5 + | +LL | hello!(hi hey hi yo hi beep beep hi hi); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:23:12 @@ -95,21 +51,10 @@ LL | hello!(hi hey hi yo hi beep beep hi hi); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:24:5 - | -LL | hello!(hi there, hi how are you? hi... hi.); - | -------------------------------------------- in this macro invocation + --> $DIR/multispan.rs:24:5 + | +LL | hello!(hi there, hi how are you? hi... hi.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:24:12 @@ -119,21 +64,10 @@ LL | hello!(hi there, hi how are you? hi... hi.); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:25:5 - | -LL | hello!(whoah. hi di hi di ho); - | ------------------------------ in this macro invocation + --> $DIR/multispan.rs:25:5 + | +LL | hello!(whoah. hi di hi di ho); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:25:19 @@ -143,21 +77,10 @@ LL | hello!(whoah. hi di hi di ho); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: hello to you, too! - --> $DIR/auxiliary/multispan.rs:31:1 - | -LL | / pub fn hello(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | } -LL | | -LL | | TokenStream::new() -LL | | } - | |_^ - | - ::: $DIR/multispan.rs:26:5 - | -LL | hello!(hi good hi and good bye); - | -------------------------------- in this macro invocation + --> $DIR/multispan.rs:26:5 + | +LL | hello!(hi good hi and good bye); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: found these 'hi's --> $DIR/multispan.rs:26:12 diff --git a/src/test/ui/proc-macro/three-equals.stderr b/src/test/ui/proc-macro/three-equals.stderr index 82c4167262f..ca82a345345 100644 --- a/src/test/ui/proc-macro/three-equals.stderr +++ b/src/test/ui/proc-macro/three-equals.stderr @@ -1,19 +1,8 @@ error: found 2 equal signs, need exactly 3 - --> $DIR/auxiliary/three-equals.rs:42:1 - | -LL | / pub fn three_equals(input: TokenStream) -> TokenStream { -LL | | if let Err(diag) = parse(input) { -LL | | diag.emit(); -LL | | return TokenStream::new(); -... | -LL | | "3".parse().unwrap() -LL | | } - | |_^ - | - ::: $DIR/three-equals.rs:15:5 - | -LL | three_equals!(==); - | ------------------ in this macro invocation + --> $DIR/three-equals.rs:15:5 + | +LL | three_equals!(==); + | ^^^^^^^^^^^^^^^^^^ | = help: input must be: `===` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) From 4809be0137d86a1a6a74848640ab5c08eeba8515 Mon Sep 17 00:00:00 2001 From: Ana-Maria Mihalache Date: Thu, 5 Mar 2020 15:31:11 +0000 Subject: [PATCH 0954/1250] rustc_errors: Use ensure_source_file_source_present where necessary. --- src/librustc_errors/emitter.rs | 6 +++++- src/librustc_errors/json.rs | 5 +++++ src/librustc_errors/lib.rs | 5 +++++ src/test/ui/consts/miri_unleashed/mutable_const2.stderr | 2 +- .../ui/editions/edition-keywords-2015-2018-expansion.stderr | 4 ++-- .../ui/editions/edition-keywords-2018-2018-expansion.stderr | 4 ++-- 6 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index b38ea6b4241..03f83e61636 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -422,9 +422,11 @@ pub trait Emitter { span: &mut MultiSpan, children: &mut Vec, ) { - for span in iter::once(span).chain(children.iter_mut().map(|child| &mut child.span)) { + debug!("fix_multispans_in_extern_macros: before: span={:?} children={:?}", span, children); + for span in iter::once(&mut *span).chain(children.iter_mut().map(|child| &mut child.span)) { self.fix_multispan_in_extern_macros(source_map, span); } + debug!("fix_multispans_in_extern_macros: after: span={:?} children={:?}", span, children); } // This "fixes" MultiSpans that contain `Span`s pointing to locations inside of external macros. @@ -472,6 +474,7 @@ impl Emitter for EmitterWriter { fn emit_diagnostic(&mut self, diag: &Diagnostic) { let mut children = diag.children.clone(); let (mut primary_span, suggestions) = self.primary_span_formatted(&diag); + debug!("emit_diagnostic: suggestions={:?}", suggestions); self.fix_multispans_in_extern_macros_and_render_macro_backtrace( &self.sm, @@ -1533,6 +1536,7 @@ impl EmitterWriter { // Render the replacements for each suggestion let suggestions = suggestion.splice_lines(&**sm); + debug!("emit_suggestion_default: suggestions={:?}", suggestions); if suggestions.is_empty() { // Suggestions coming from macros can have malformed spans. This is a heavy handed diff --git a/src/librustc_errors/json.rs b/src/librustc_errors/json.rs index 0767b8dda9b..1382825922b 100644 --- a/src/librustc_errors/json.rs +++ b/src/librustc_errors/json.rs @@ -394,6 +394,11 @@ impl DiagnosticSpanLine { je.sm .span_to_lines(span) .map(|lines| { + // We can't get any lines if the source is unavailable. + if !je.sm.ensure_source_file_source_present(lines.file.clone()) { + return vec![]; + } + let sf = &*lines.file; lines .lines diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index f0e388a597b..bed26c3736b 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -196,6 +196,11 @@ impl CodeSuggestion { let lines = sm.span_to_lines(bounding_span).ok()?; assert!(!lines.lines.is_empty()); + // We can't splice anything if the source is unavailable. + if !sm.ensure_source_file_source_present(lines.file.clone()) { + return None; + } + // To build up the result, we do this for each span: // - push the line segment trailing the previous span // (at the beginning a "phantom" span pointing at the start of the line) diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr index 3eb8e0ec182..dda9ddf1f48 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr @@ -10,7 +10,7 @@ error: internal compiler error: mutable allocation in constant LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:355:17 +thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:360:17 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace error: internal compiler error: unexpected panic diff --git a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr index 46db5dbc8b3..88a1f5dc673 100644 --- a/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2015-2018-expansion.stderr @@ -7,8 +7,8 @@ LL | produces_async! {} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers | -LL | r#async - | +LL | () => (pub fn r#async() {}) + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr index 2de383d0bca..5eaa1d03a4a 100644 --- a/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr +++ b/src/test/ui/editions/edition-keywords-2018-2018-expansion.stderr @@ -7,8 +7,8 @@ LL | produces_async! {} = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) help: you can escape reserved keywords to use them as identifiers | -LL | r#async - | +LL | () => (pub fn r#async() {}) + | ^^^^^^^ error: aborting due to previous error From 87b6bc35181ac7ae36128585fbfdc42966a04ed1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 6 Mar 2020 14:35:21 +0100 Subject: [PATCH 0955/1250] span-api-tests: leave FIXME --- src/test/ui/proc-macro/span-api-tests.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/ui/proc-macro/span-api-tests.rs b/src/test/ui/proc-macro/span-api-tests.rs index cbceea1b4f3..5c0cbd77a8d 100644 --- a/src/test/ui/proc-macro/span-api-tests.rs +++ b/src/test/ui/proc-macro/span-api-tests.rs @@ -11,6 +11,8 @@ extern crate span_test_macros; extern crate span_api_tests; +// FIXME(69775): Investigate `assert_fake_source_file`. + use span_api_tests::{reemit, assert_source_file, macro_stringify}; macro_rules! say_hello { From bafa5cc9ba35228115560b0b6f3038eb83f161e8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 10 Mar 2020 08:30:07 +0100 Subject: [PATCH 0956/1250] macros/unknown-builtin: use hack for musl problems --- src/test/ui/macros/unknown-builtin.rs | 5 +++++ src/test/ui/macros/unknown-builtin.stderr | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/test/ui/macros/unknown-builtin.rs b/src/test/ui/macros/unknown-builtin.rs index a96b99ae4ff..716a0005ba3 100644 --- a/src/test/ui/macros/unknown-builtin.rs +++ b/src/test/ui/macros/unknown-builtin.rs @@ -1,3 +1,8 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl + // error-pattern: cannot find a built-in macro with name `line` #![feature(rustc_attrs)] diff --git a/src/test/ui/macros/unknown-builtin.stderr b/src/test/ui/macros/unknown-builtin.stderr index 665e92f2424..ed163750a6e 100644 --- a/src/test/ui/macros/unknown-builtin.stderr +++ b/src/test/ui/macros/unknown-builtin.stderr @@ -1,5 +1,5 @@ error: cannot find a built-in macro with name `unknown` - --> $DIR/unknown-builtin.rs:6:1 + --> $DIR/unknown-builtin.rs:11:1 | LL | macro_rules! unknown { () => () } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 9596dc2a47861d73996a550cba7caf55b2737c17 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 01:47:15 +0100 Subject: [PATCH 0957/1250] parse_labeled_expr: simplify --- src/librustc_parse/parser/expr.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 16ea2773b20..e0e6fd5eed6 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1069,24 +1069,22 @@ impl<'a> Parser<'a> { fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P> { let lo = label.ident.span; + let label = Some(label); self.expect(&token::Colon)?; if self.eat_keyword(kw::While) { - return self.parse_while_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::For) { - return self.parse_for_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::Loop) { - return self.parse_loop_expr(Some(label), lo, attrs); - } - if self.token == token::OpenDelim(token::Brace) { - return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs); + self.parse_while_expr(label, lo, attrs) + } else if self.eat_keyword(kw::For) { + self.parse_for_expr(label, lo, attrs) + } else if self.eat_keyword(kw::Loop) { + self.parse_loop_expr(label, lo, attrs) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) + } else { + let msg = "expected `while`, `for`, `loop` or `{` after a label"; + self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); + // Continue as an expression in an effort to recover on `'label: non_block_expr`. + self.parse_expr() } - - let msg = "expected `while`, `for`, `loop` or `{` after a label"; - self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); - // Continue as an expression in an effort to recover on `'label: non_block_expr`. - self.parse_expr() } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. From c303c4463cd3530c634dac8614feac7723ab0c58 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 02:46:13 +0100 Subject: [PATCH 0958/1250] use error_block_no_opening_brace more --- src/librustc_parse/parser/stmt.rs | 6 ++- src/test/ui/parser/block-no-opening-brace.rs | 30 +++++++++++ .../ui/parser/block-no-opening-brace.stderr | 53 +++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/block-no-opening-brace.rs create mode 100644 src/test/ui/parser/block-no-opening-brace.stderr diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 3864ec3aaa1..511d4bfccd2 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -304,7 +304,11 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.token.span; - self.expect(&token::OpenDelim(token::Brace))?; + + if !self.eat(&token::OpenDelim(token::Brace)) { + return self.error_block_no_opening_brace(); + } + Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?)) } diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs new file mode 100644 index 00000000000..169625bf897 --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.rs @@ -0,0 +1,30 @@ +// edition:2018 + +#![feature(try_blocks)] + +fn main() {} + +fn f1() { + loop + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f2() { + while true + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f3() { + for x in 0..1 + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f4() { + try //~ ERROR expected expression, found reserved keyword `try` + let x = 0; + } + +fn f5() { + async //~ ERROR async closures are unstable + let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let` + } diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr new file mode 100644 index 00000000000..56db1147360 --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.stderr @@ -0,0 +1,53 @@ +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:9:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:14:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:19:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected expression, found reserved keyword `try` + --> $DIR/block-no-opening-brace.rs:23:4 + | +LL | try + | ^^^ expected expression + +error: expected one of `move`, `|`, or `||`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:29:6 + | +LL | async + | - expected one of `move`, `|`, or `||` +LL | let x = 0; + | ^^^ unexpected token + +error[E0658]: async closures are unstable + --> $DIR/block-no-opening-brace.rs:28:4 + | +LL | async + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. From 883e90dd81b207cc5d9e85c02f628432b7f8d65d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 03:24:58 +0100 Subject: [PATCH 0959/1250] simplify parse_inner_attributes --- src/librustc_parse/parser/attr.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index bdd78e671a8..1e7f5b662f3 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -201,12 +201,8 @@ impl<'a> Parser<'a> { let mut attrs: Vec = vec![]; loop { match self.token.kind { - token::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !self.look_ahead(1, |t| t == &token::Not) { - break; - } - + // Only try to parse if it is an inner attribute (has `!`). + token::Pound if self.look_ahead(1, |t| t == &token::Not) => { let attr = self.parse_attribute(true)?; assert_eq!(attr.style, ast::AttrStyle::Inner); attrs.push(attr); From 8ee220c447911c519ebbd118e1415d961317b18d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 05:49:30 +0100 Subject: [PATCH 0960/1250] more reuse in block parsing & improve diagnostics. --- src/librustc_ast/token.rs | 10 +++++ src/librustc_parse/parser/expr.rs | 16 ++++---- src/librustc_parse/parser/stmt.rs | 17 +++++--- .../label_break_value_illegal_uses.stderr | 5 ++- src/test/ui/parser/bad-interpolated-block.rs | 15 +++++++ .../ui/parser/bad-interpolated-block.stderr | 39 +++++++++++++++++++ src/test/ui/parser/closure-return-syntax.rs | 2 +- .../ui/parser/closure-return-syntax.stderr | 7 +++- .../unsafe/unsafe-block-without-braces.stderr | 7 ++-- 9 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/bad-interpolated-block.rs create mode 100644 src/test/ui/parser/bad-interpolated-block.stderr diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index b67b7d346f7..3fc6444168e 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -535,6 +535,16 @@ impl Token { false } + // Is the token an interpolated block (`$b:block`)? + pub fn is_whole_block(&self) -> bool { + if let Interpolated(ref nt) = self.kind { + if let NtBlock(..) = **nt { + return true; + } + } + false + } + /// Returns `true` if the token is either the `mut` or `const` keyword. pub fn is_mutability(&self) -> bool { self.is_keyword(kw::Mut) || self.is_keyword(kw::Const) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index e0e6fd5eed6..b1c5eaf8973 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1077,7 +1077,7 @@ impl<'a> Parser<'a> { self.parse_for_expr(label, lo, attrs) } else if self.eat_keyword(kw::Loop) { self.parse_loop_expr(label, lo, attrs) - } else if self.check(&token::OpenDelim(token::Brace)) { + } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else { let msg = "expected `while`, `for`, `loop` or `{` after a label"; @@ -1361,18 +1361,20 @@ impl<'a> Parser<'a> { opt_label: Option

(&self, value: P) -> Obligation<'tcx, P> { + Obligation { + cause: self.cause.clone(), + param_env: self.param_env, + recursion_depth: self.recursion_depth, + predicate: value, + } + } +} + +impl<'tcx> FulfillmentError<'tcx> { + pub fn new( + obligation: PredicateObligation<'tcx>, + code: FulfillmentErrorCode<'tcx>, + ) -> FulfillmentError<'tcx> { + FulfillmentError { obligation, code, points_at_arg_span: false } + } +} + +impl<'tcx> TraitObligation<'tcx> { + pub fn self_ty(&self) -> ty::Binder> { + self.predicate.map_bound(|p| p.self_ty()) + } +} diff --git a/src/librustc_trait_selection/traits/projection_cache.rs b/src/librustc_infer/traits/project.rs similarity index 97% rename from src/librustc_trait_selection/traits/projection_cache.rs rename to src/librustc_infer/traits/project.rs index fb7b5fdb8ea..183e4be1890 100644 --- a/src/librustc_trait_selection/traits/projection_cache.rs +++ b/src/librustc_infer/traits/project.rs @@ -65,7 +65,13 @@ pub struct ProjectionCache<'tcx> { #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)] pub struct ProjectionCacheKey<'tcx> { - pub ty: ty::ProjectionTy<'tcx>, + ty: ty::ProjectionTy<'tcx>, +} + +impl ProjectionCacheKey<'tcx> { + pub fn new(ty: ty::ProjectionTy<'tcx>) -> Self { + Self { ty } + } } #[derive(Clone, Debug)] diff --git a/src/librustc_trait_selection/traits/structural_impls.rs b/src/librustc_infer/traits/structural_impls.rs similarity index 98% rename from src/librustc_trait_selection/traits/structural_impls.rs rename to src/librustc_infer/traits/structural_impls.rs index a164995255a..6630f664f96 100644 --- a/src/librustc_trait_selection/traits/structural_impls.rs +++ b/src/librustc_infer/traits/structural_impls.rs @@ -1,5 +1,5 @@ use crate::traits; -use crate::traits::Normalized; +use crate::traits::project::Normalized; use rustc::ty; use rustc::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs new file mode 100644 index 00000000000..a7c02671115 --- /dev/null +++ b/src/librustc_infer/traits/util.rs @@ -0,0 +1,225 @@ +use smallvec::smallvec; + +use rustc::ty::outlives::Component; +use rustc::ty::{self, ToPolyTraitRef, TyCtxt}; +use rustc_data_structures::fx::FxHashSet; + +fn anonymize_predicate<'tcx>(tcx: TyCtxt<'tcx>, pred: &ty::Predicate<'tcx>) -> ty::Predicate<'tcx> { + match *pred { + ty::Predicate::Trait(ref data, constness) => { + ty::Predicate::Trait(tcx.anonymize_late_bound_regions(data), constness) + } + + ty::Predicate::RegionOutlives(ref data) => { + ty::Predicate::RegionOutlives(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::TypeOutlives(ref data) => { + ty::Predicate::TypeOutlives(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::Projection(ref data) => { + ty::Predicate::Projection(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::WellFormed(data) => ty::Predicate::WellFormed(data), + + ty::Predicate::ObjectSafe(data) => ty::Predicate::ObjectSafe(data), + + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) + } + + ty::Predicate::Subtype(ref data) => { + ty::Predicate::Subtype(tcx.anonymize_late_bound_regions(data)) + } + + ty::Predicate::ConstEvaluatable(def_id, substs) => { + ty::Predicate::ConstEvaluatable(def_id, substs) + } + } +} + +struct PredicateSet<'tcx> { + tcx: TyCtxt<'tcx>, + set: FxHashSet>, +} + +impl PredicateSet<'tcx> { + fn new(tcx: TyCtxt<'tcx>) -> Self { + Self { tcx: tcx, set: Default::default() } + } + + fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { + // We have to be careful here because we want + // + // for<'a> Foo<&'a int> + // + // and + // + // for<'b> Foo<&'b int> + // + // to be considered equivalent. So normalize all late-bound + // regions before we throw things into the underlying set. + self.set.insert(anonymize_predicate(self.tcx, pred)) + } +} + +impl>> Extend for PredicateSet<'tcx> { + fn extend>(&mut self, iter: I) { + for pred in iter { + self.insert(pred.as_ref()); + } + } +} + +/////////////////////////////////////////////////////////////////////////// +// `Elaboration` iterator +/////////////////////////////////////////////////////////////////////////// + +/// "Elaboration" is the process of identifying all the predicates that +/// are implied by a source predicate. Currently, this basically means +/// walking the "supertraits" and other similar assumptions. For example, +/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` +/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that +/// `T: Foo`, then we know that `T: 'static`. +pub struct Elaborator<'tcx> { + stack: Vec>, + visited: PredicateSet<'tcx>, +} + +pub fn elaborate_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + mut predicates: Vec>, +) -> Elaborator<'tcx> { + let mut visited = PredicateSet::new(tcx); + predicates.retain(|pred| visited.insert(pred)); + Elaborator { stack: predicates, visited } +} + +impl Elaborator<'tcx> { + fn elaborate(&mut self, predicate: &ty::Predicate<'tcx>) { + let tcx = self.visited.tcx; + match *predicate { + ty::Predicate::Trait(ref data, _) => { + // Get predicates declared on the trait. + let predicates = tcx.super_predicates_of(data.def_id()); + + let predicates = predicates + .predicates + .iter() + .map(|(pred, _)| pred.subst_supertrait(tcx, &data.to_poly_trait_ref())); + debug!("super_predicates: data={:?} predicates={:?}", data, predicates.clone()); + + // Only keep those bounds that we haven't already seen. + // This is necessary to prevent infinite recursion in some + // cases. One common case is when people define + // `trait Sized: Sized { }` rather than `trait Sized { }`. + let visited = &mut self.visited; + let predicates = predicates.filter(|pred| visited.insert(pred)); + + self.stack.extend(predicates); + } + ty::Predicate::WellFormed(..) => { + // Currently, we do not elaborate WF predicates, + // although we easily could. + } + ty::Predicate::ObjectSafe(..) => { + // Currently, we do not elaborate object-safe + // predicates. + } + ty::Predicate::Subtype(..) => { + // Currently, we do not "elaborate" predicates like `X <: Y`, + // though conceivably we might. + } + ty::Predicate::Projection(..) => { + // Nothing to elaborate in a projection predicate. + } + ty::Predicate::ClosureKind(..) => { + // Nothing to elaborate when waiting for a closure's kind to be inferred. + } + ty::Predicate::ConstEvaluatable(..) => { + // Currently, we do not elaborate const-evaluatable + // predicates. + } + ty::Predicate::RegionOutlives(..) => { + // Nothing to elaborate from `'a: 'b`. + } + ty::Predicate::TypeOutlives(ref data) => { + // We know that `T: 'a` for some type `T`. We can + // often elaborate this. For example, if we know that + // `[U]: 'a`, that implies that `U: 'a`. Similarly, if + // we know `&'a U: 'b`, then we know that `'a: 'b` and + // `U: 'b`. + // + // We can basically ignore bound regions here. So for + // example `for<'c> Foo<'a,'c>: 'b` can be elaborated to + // `'a: 'b`. + + // Ignore `for<'a> T: 'a` -- we might in the future + // consider this as evidence that `T: 'static`, but + // I'm a bit wary of such constructions and so for now + // I want to be conservative. --nmatsakis + let ty_max = data.skip_binder().0; + let r_min = data.skip_binder().1; + if r_min.is_late_bound() { + return; + } + + let visited = &mut self.visited; + let mut components = smallvec![]; + tcx.push_outlives_components(ty_max, &mut components); + self.stack.extend( + components + .into_iter() + .filter_map(|component| match component { + Component::Region(r) => { + if r.is_late_bound() { + None + } else { + Some(ty::Predicate::RegionOutlives(ty::Binder::dummy( + ty::OutlivesPredicate(r, r_min), + ))) + } + } + + Component::Param(p) => { + let ty = tcx.mk_ty_param(p.index, p.name); + Some(ty::Predicate::TypeOutlives(ty::Binder::dummy( + ty::OutlivesPredicate(ty, r_min), + ))) + } + + Component::UnresolvedInferenceVariable(_) => None, + + Component::Projection(_) | Component::EscapingProjection(_) => { + // We can probably do more here. This + // corresponds to a case like `>::U: 'b`. + None + } + }) + .filter(|p| visited.insert(p)), + ); + } + } + } +} + +impl Iterator for Elaborator<'tcx> { + type Item = ty::Predicate<'tcx>; + + fn size_hint(&self) -> (usize, Option) { + (self.stack.len(), None) + } + + fn next(&mut self) -> Option> { + // Extract next item from top-most stack frame, if any. + if let Some(pred) = self.stack.pop() { + self.elaborate(&pred); + Some(pred) + } else { + None + } + } +} diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml index 5b2da41d066..c7f2cc34b84 100644 --- a/src/librustc_trait_selection/Cargo.toml +++ b/src/librustc_trait_selection/Cargo.toml @@ -11,12 +11,14 @@ doctest = false [dependencies] fmt_macros = { path = "../libfmt_macros" } +graphviz = { path = "../libgraphviz" } log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc_attr = { path = "../librustc_attr" } rustc = { path = "../librustc" } rustc_ast = { path = "../librustc_ast" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } +rustc_error_codes = { path = "../librustc_error_codes" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs new file mode 100644 index 00000000000..7abcbf45277 --- /dev/null +++ b/src/librustc_trait_selection/infer.rs @@ -0,0 +1,182 @@ +use crate::traits::query::outlives_bounds::InferCtxtExt as _; +use crate::traits::{self, TraitEngine, TraitEngineExt}; + +use rustc::arena::ArenaAllocatable; +use rustc::infer::canonical::{Canonical, CanonicalizedQueryResponse, QueryResponse}; +use rustc::middle::lang_items; +use rustc::traits::query::Fallible; +use rustc::ty::{self, Ty, TypeFoldable}; +use rustc_hir as hir; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::traits::ObligationCause; +use rustc_span::{Span, DUMMY_SP}; + +use std::fmt::Debug; + +pub use rustc_infer::infer::*; + +pub trait InferCtxtExt<'tcx> { + fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool; + + fn partially_normalize_associated_types_in( + &self, + span: Span, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, T> + where + T: TypeFoldable<'tcx>; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { + fn type_is_copy_modulo_regions( + &self, + param_env: ty::ParamEnv<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) -> bool { + let ty = self.resolve_vars_if_possible(&ty); + + if !(param_env, ty).has_local_value() { + return ty.is_copy_modulo_regions(self.tcx, param_env, span); + } + + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem, None); + + // This can get called from typeck (by euv), and `moves_by_default` + // rightly refuses to work with inference variables, but + // moves_by_default has a cache, which we want to use in other + // cases. + traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id, span) + } + + /// Normalizes associated types in `value`, potentially returning + /// new obligations that must further be processed. + fn partially_normalize_associated_types_in( + &self, + span: Span, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + ) -> InferOk<'tcx, T> + where + T: TypeFoldable<'tcx>, + { + debug!("partially_normalize_associated_types_in(value={:?})", value); + let mut selcx = traits::SelectionContext::new(self); + let cause = ObligationCause::misc(span, body_id); + let traits::Normalized { value, obligations } = + traits::normalize(&mut selcx, param_env, cause, value); + debug!( + "partially_normalize_associated_types_in: result={:?} predicates={:?}", + value, obligations + ); + InferOk { value, obligations } + } +} + +pub trait InferCtxtBuilderExt<'tcx> { + fn enter_canonical_trait_query( + &mut self, + canonical_key: &Canonical<'tcx, K>, + operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible, + ) -> Fallible> + where + K: TypeFoldable<'tcx>, + R: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable; +} + +impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> { + /// The "main method" for a canonicalized trait query. Given the + /// canonical key `canonical_key`, this method will create a new + /// inference context, instantiate the key, and run your operation + /// `op`. The operation should yield up a result (of type `R`) as + /// well as a set of trait obligations that must be fully + /// satisfied. These obligations will be processed and the + /// canonical result created. + /// + /// Returns `NoSolution` in the event of any error. + /// + /// (It might be mildly nicer to implement this on `TyCtxt`, and + /// not `InferCtxtBuilder`, but that is a bit tricky right now. + /// In part because we would need a `for<'tcx>` sort of + /// bound for the closure and in part because it is convenient to + /// have `'tcx` be free on this function so that we can talk about + /// `K: TypeFoldable<'tcx>`.) + fn enter_canonical_trait_query( + &mut self, + canonical_key: &Canonical<'tcx, K>, + operation: impl FnOnce(&InferCtxt<'_, 'tcx>, &mut dyn TraitEngine<'tcx>, K) -> Fallible, + ) -> Fallible> + where + K: TypeFoldable<'tcx>, + R: Debug + TypeFoldable<'tcx>, + Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable, + { + self.enter_with_canonical( + DUMMY_SP, + canonical_key, + |ref infcx, key, canonical_inference_vars| { + let mut fulfill_cx = TraitEngine::new(infcx.tcx); + let value = operation(infcx, &mut *fulfill_cx, key)?; + infcx.make_canonicalized_query_response( + canonical_inference_vars, + value, + &mut *fulfill_cx, + ) + }, + ) + } +} + +pub trait OutlivesEnvironmentExt<'tcx> { + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: &[Ty<'tcx>], + body_id: hir::HirId, + span: Span, + ); +} + +impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> { + /// This method adds "implied bounds" into the outlives environment. + /// Implied bounds are outlives relationships that we can deduce + /// on the basis that certain types must be well-formed -- these are + /// either the types that appear in the function signature or else + /// the input types to an impl. For example, if you have a function + /// like + /// + /// ``` + /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { } + /// ``` + /// + /// we can assume in the caller's body that `'b: 'a` and that `T: + /// 'b` (and hence, transitively, that `T: 'a`). This method would + /// add those assumptions into the outlives-environment. + /// + /// Tests: `src/test/compile-fail/regions-free-region-ordering-*.rs` + fn add_implied_bounds( + &mut self, + infcx: &InferCtxt<'a, 'tcx>, + fn_sig_tys: &[Ty<'tcx>], + body_id: hir::HirId, + span: Span, + ) { + debug!("add_implied_bounds()"); + + for &ty in fn_sig_tys { + let ty = infcx.resolve_vars_if_possible(&ty); + debug!("add_implied_bounds: ty = {}", ty); + let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty, span); + self.add_outlives_bounds(Some(infcx), implied_bounds) + } + } +} diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs new file mode 100644 index 00000000000..8b5cf223826 --- /dev/null +++ b/src/librustc_trait_selection/lib.rs @@ -0,0 +1,39 @@ +//! This crates defines the trait resolution method and the type inference engine. +//! +//! - **Traits.** Trait resolution is implemented in the `traits` module. +//! - **Type inference.** The type inference code can be found in the `infer` module; +//! this code handles low-level equality and subtyping operations. The +//! type check pass in the compiler is found in the `librustc_typeck` crate. +//! +//! For more information about how rustc works, see the [rustc guide]. +//! +//! [rustc guide]: https://rust-lang.github.io/rustc-guide/ +//! +//! # Note +//! +//! This API is completely unstable and subject to change. + +#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] +#![feature(bool_to_option)] +#![feature(box_patterns)] +#![feature(box_syntax)] +#![feature(drain_filter)] +#![feature(never_type)] +#![feature(range_is_empty)] +#![feature(in_band_lifetimes)] +#![feature(crate_visibility_modifier)] +#![recursion_limit = "512"] + +#[macro_use] +extern crate rustc_macros; +#[cfg(target_arch = "x86_64")] +#[macro_use] +extern crate rustc_data_structures; +#[macro_use] +extern crate log; +#[macro_use] +extern crate rustc; + +pub mod infer; +pub mod opaque_types; +pub mod traits; diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index c18c2755281..6cf1302783c 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -1,5 +1,4 @@ -use crate::infer::error_reporting::unexpected_hidden_region_diagnostic; -use crate::infer::{self, InferCtxt, InferOk, TypeVariableOrigin, TypeVariableOriginKind}; +use crate::infer::InferCtxtExt as _; use crate::traits::{self, PredicateObligation}; use rustc::session::config::nightly_options; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; @@ -11,6 +10,9 @@ use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_hir::Node; +use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; +use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; +use rustc_infer::infer::{self, InferCtxt, InferOk}; use rustc_span::Span; pub type OpaqueTypeMap<'tcx> = DefIdMap>; @@ -103,7 +105,58 @@ pub enum GenerateMemberConstraints { IfNoStaticBound, } -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn instantiate_opaque_types>( + &self, + parent_def_id: DefId, + body_id: hir::HirId, + param_env: ty::ParamEnv<'tcx>, + value: &T, + value_span: Span, + ) -> InferOk<'tcx, (T, OpaqueTypeMap<'tcx>)>; + + fn constrain_opaque_types>( + &self, + opaque_types: &OpaqueTypeMap<'tcx>, + free_region_relations: &FRR, + ); + + fn constrain_opaque_type>( + &self, + def_id: DefId, + opaque_defn: &OpaqueTypeDecl<'tcx>, + mode: GenerateMemberConstraints, + free_region_relations: &FRR, + ); + + /*private*/ + fn generate_member_constraint( + &self, + concrete_ty: Ty<'tcx>, + opaque_type_generics: &ty::Generics, + opaque_defn: &OpaqueTypeDecl<'tcx>, + opaque_type_def_id: DefId, + ); + + /*private*/ + fn member_constraint_feature_gate( + &self, + opaque_defn: &OpaqueTypeDecl<'tcx>, + opaque_type_def_id: DefId, + conflict1: ty::Region<'tcx>, + conflict2: ty::Region<'tcx>, + ) -> bool; + + fn infer_opaque_definition_from_instantiation( + &self, + def_id: DefId, + substs: SubstsRef<'tcx>, + instantiated_ty: Ty<'tcx>, + span: Span, + ) -> Ty<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { /// Replaces all opaque types in `value` with fresh inference variables /// and creates appropriate obligations. For example, given the input: /// @@ -129,7 +182,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// obligations /// - `value` -- the value within which we are instantiating opaque types /// - `value_span` -- the span where the value came from, used in error reporting - pub fn instantiate_opaque_types>( + fn instantiate_opaque_types>( &self, parent_def_id: DefId, body_id: hir::HirId, @@ -317,7 +370,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `opaque_types` -- the map produced by `instantiate_opaque_types` /// - `free_region_relations` -- something that can be used to relate /// the free regions (`'a`) that appear in the impl trait. - pub fn constrain_opaque_types>( + fn constrain_opaque_types>( &self, opaque_types: &OpaqueTypeMap<'tcx>, free_region_relations: &FRR, @@ -335,7 +388,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } /// See `constrain_opaque_types` for documentation. - pub fn constrain_opaque_type>( + fn constrain_opaque_type>( &self, def_id: DefId, opaque_defn: &OpaqueTypeDecl<'tcx>, @@ -577,7 +630,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// - `substs`, the substs used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` - pub fn infer_opaque_definition_from_instantiation( + fn infer_opaque_definition_from_instantiation( &self, def_id: DefId, substs: SubstsRef<'tcx>, diff --git a/src/librustc_trait_selection/traits/codegen/mod.rs b/src/librustc_trait_selection/traits/codegen/mod.rs index f499565e919..5c2fc3f305c 100644 --- a/src/librustc_trait_selection/traits/codegen/mod.rs +++ b/src/librustc_trait_selection/traits/codegen/mod.rs @@ -72,7 +72,7 @@ pub fn codegen_fulfill_obligation<'tcx>( debug!("fulfill_obligation: register_predicate_obligation {:?}", predicate); fulfill_cx.register_predicate_obligation(&infcx, predicate); }); - let vtable = infcx.drain_fulfillment_cx_or_panic(&mut fulfill_cx, &vtable); + let vtable = drain_fulfillment_cx_or_panic(&infcx, &mut fulfill_cx, &vtable); info!("Cache miss: {:?} => {:?}", trait_ref, vtable); Some(vtable) @@ -81,34 +81,32 @@ pub fn codegen_fulfill_obligation<'tcx>( // # Global Cache -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - /// Finishes processes any obligations that remain in the - /// fulfillment context, and then returns the result with all type - /// variables removed and regions erased. Because this is intended - /// for use after type-check has completed, if any errors occur, - /// it will panic. It is used during normalization and other cases - /// where processing the obligations in `fulfill_cx` may cause - /// type inference variables that appear in `result` to be - /// unified, and hence we need to process those obligations to get - /// the complete picture of the type. - fn drain_fulfillment_cx_or_panic( - &self, - fulfill_cx: &mut FulfillmentContext<'tcx>, - result: &T, - ) -> T - where - T: TypeFoldable<'tcx>, - { - debug!("drain_fulfillment_cx_or_panic()"); +/// Finishes processes any obligations that remain in the +/// fulfillment context, and then returns the result with all type +/// variables removed and regions erased. Because this is intended +/// for use after type-check has completed, if any errors occur, +/// it will panic. It is used during normalization and other cases +/// where processing the obligations in `fulfill_cx` may cause +/// type inference variables that appear in `result` to be +/// unified, and hence we need to process those obligations to get +/// the complete picture of the type. +fn drain_fulfillment_cx_or_panic( + infcx: &InferCtxt<'_, 'tcx>, + fulfill_cx: &mut FulfillmentContext<'tcx>, + result: &T, +) -> T +where + T: TypeFoldable<'tcx>, +{ + debug!("drain_fulfillment_cx_or_panic()"); - // In principle, we only need to do this so long as `result` - // contains unbound type parameters. It could be a slight - // optimization to stop iterating early. - if let Err(errors) = fulfill_cx.select_all_or_error(self) { - bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors); - } - - let result = self.resolve_vars_if_possible(result); - self.tcx.erase_regions(&result) + // In principle, we only need to do this so long as `result` + // contains unbound type parameters. It could be a slight + // optimization to stop iterating early. + if let Err(errors) = fulfill_cx.select_all_or_error(infcx) { + bug!("Encountered errors `{:?}` resolving bounds after type-checking", errors); } + + let result = infcx.resolve_vars_if_possible(result); + infcx.tcx.erase_regions(&result) } diff --git a/src/librustc_trait_selection/traits/engine.rs b/src/librustc_trait_selection/traits/engine.rs index e23810dd161..ee4715e0c20 100644 --- a/src/librustc_trait_selection/traits/engine.rs +++ b/src/librustc_trait_selection/traits/engine.rs @@ -1,84 +1,14 @@ -use crate::infer::InferCtxt; -use crate::traits::Obligation; -use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; -use rustc_hir::def_id::DefId; +use rustc::ty::TyCtxt; -use super::{FulfillmentContext, FulfillmentError}; -use super::{ObligationCause, PredicateObligation}; - -pub trait TraitEngine<'tcx>: 'tcx { - fn normalize_projection_type( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - projection_ty: ty::ProjectionTy<'tcx>, - cause: ObligationCause<'tcx>, - ) -> Ty<'tcx>; - - /// Requires that `ty` must implement the trait with `def_id` in - /// the given environment. This trait must not have any type - /// parameters (except for `Self`). - fn register_bound( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - param_env: ty::ParamEnv<'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - cause: ObligationCause<'tcx>, - ) { - let trait_ref = ty::TraitRef { def_id, substs: infcx.tcx.mk_substs_trait(ty, &[]) }; - self.register_predicate_obligation( - infcx, - Obligation { - cause, - recursion_depth: 0, - param_env, - predicate: trait_ref.without_const().to_predicate(), - }, - ); - } - - fn register_predicate_obligation( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - obligation: PredicateObligation<'tcx>, - ); - - fn select_all_or_error( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; - - fn select_where_possible( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - ) -> Result<(), Vec>>; - - fn pending_obligations(&self) -> Vec>; -} +use super::FulfillmentContext; +use super::TraitEngine; pub trait TraitEngineExt<'tcx> { - fn register_predicate_obligations( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - obligations: impl IntoIterator>, - ); -} - -impl> TraitEngineExt<'tcx> for T { - fn register_predicate_obligations( - &mut self, - infcx: &InferCtxt<'_, 'tcx>, - obligations: impl IntoIterator>, - ) { - for obligation in obligations { - self.register_predicate_obligation(infcx, obligation); - } - } + fn new(tcx: TyCtxt<'tcx>) -> Box; } -impl dyn TraitEngine<'tcx> { - pub fn new(_tcx: TyCtxt<'tcx>) -> Box { +impl<'tcx> TraitEngineExt<'tcx> for dyn TraitEngine<'tcx> { + fn new(_tcx: TyCtxt<'tcx>) -> Box { Box::new(FulfillmentContext::new()) } } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 10143ae015f..abd9638bfa7 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -3,10 +3,9 @@ pub mod suggestions; use super::{ ConstEvalFailure, EvaluationResult, FulfillmentError, FulfillmentErrorCode, - MismatchedProjectionTypes, ObjectSafetyViolation, Obligation, ObligationCause, - ObligationCauseCode, OnUnimplementedDirective, OnUnimplementedNote, - OutputTypeParameterMismatch, Overflow, PredicateObligation, SelectionContext, SelectionError, - TraitNotObjectSafe, + MismatchedProjectionTypes, Obligation, ObligationCause, ObligationCauseCode, + OnUnimplementedDirective, OnUnimplementedNote, OutputTypeParameterMismatch, Overflow, + PredicateObligation, SelectionContext, SelectionError, TraitNotObjectSafe, }; use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCode}; @@ -21,18 +20,69 @@ use rustc::ty::SubtypePredicate; use rustc::ty::{ self, AdtKind, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; -use rustc_ast::ast; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_data_structures::fx::FxHashMap; +use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate}; use rustc_span::source_map::SourceMap; use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - pub fn report_fulfillment_errors( +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; +use crate::traits::query::normalize::AtExt as _; +use on_unimplemented::InferCtxtExt as _; +use suggestions::InferCtxtExt as _; + +pub use rustc_infer::traits::error_reporting::*; + +pub trait InferCtxtExt<'tcx> { + fn report_fulfillment_errors( + &self, + errors: &[FulfillmentError<'tcx>], + body_id: Option, + fallback_has_occurred: bool, + ); + + fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: fmt::Display + TypeFoldable<'tcx>; + + fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> !; + + fn report_selection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &SelectionError<'tcx>, + fallback_has_occurred: bool, + points_at_arg: bool, + ); + + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec); + + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( + &self, + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + ) -> DiagnosticBuilder<'tcx>; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + fn report_fulfillment_errors( &self, errors: &[FulfillmentError<'tcx>], body_id: Option, @@ -118,827 +168,1106 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - // returns if `cond` not occurring implies that `error` does not occur - i.e., that - // `error` occurring implies that `cond` occurs. - fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool { - if cond == error { - return true; - } - - let (cond, error) = match (cond, error) { - (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error), - _ => { - // FIXME: make this work in other cases too. - return false; - } - }; + /// Reports that an overflow has occurred and halts compilation. We + /// halt compilation unconditionally because it is important that + /// overflows never be masked -- they basically represent computations + /// whose result could not be truly determined and thus we can't say + /// if the program type checks or not -- and they are unusual + /// occurrences in any case. + fn report_overflow_error( + &self, + obligation: &Obligation<'tcx, T>, + suggest_increasing_limit: bool, + ) -> ! + where + T: fmt::Display + TypeFoldable<'tcx>, + { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + let mut err = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0275, + "overflow evaluating the requirement `{}`", + predicate + ); - for implication in super::elaborate_predicates(self.tcx, vec![*cond]) { - if let ty::Predicate::Trait(implication, _) = implication { - let error = error.to_poly_trait_ref(); - let implication = implication.to_poly_trait_ref(); - // FIXME: I'm just not taking associated types at all here. - // Eventually I'll need to implement param-env-aware - // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. - let param_env = ty::ParamEnv::empty(); - if self.can_sub(param_env, error, implication).is_ok() { - debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); - return true; - } - } + if suggest_increasing_limit { + self.suggest_new_overflow_limit(&mut err); } - false + self.note_obligation_cause_code( + &mut err, + &obligation.predicate, + &obligation.cause.code, + &mut vec![], + ); + + err.emit(); + self.tcx.sess.abort_if_errors(); + bug!(); } - fn report_fulfillment_error( - &self, - error: &FulfillmentError<'tcx>, - body_id: Option, - fallback_has_occurred: bool, - ) { - debug!("report_fulfillment_error({:?})", error); - match error.code { - FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { - self.report_selection_error( - &error.obligation, - selection_error, - fallback_has_occurred, - error.points_at_arg_span, - ); - } - FulfillmentErrorCode::CodeProjectionError(ref e) => { - self.report_projection_error(&error.obligation, e); - } - FulfillmentErrorCode::CodeAmbiguity => { - self.maybe_report_ambiguity(&error.obligation, body_id); - } - FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { - self.report_mismatched_types( - &error.obligation.cause, - expected_found.expected, - expected_found.found, - err.clone(), - ) - .emit(); - } - } + /// Reports that a cycle was detected which led to overflow and halts + /// compilation. This is equivalent to `report_overflow_error` except + /// that we can give a more helpful error message (and, in particular, + /// we do not suggest increasing the overflow limit, which is not + /// going to help). + fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { + let cycle = self.resolve_vars_if_possible(&cycle.to_owned()); + assert!(!cycle.is_empty()); + + debug!("report_overflow_error_cycle: cycle={:?}", cycle); + + self.report_overflow_error(&cycle[0], false); } - fn report_projection_error( + fn report_selection_error( &self, obligation: &PredicateObligation<'tcx>, - error: &MismatchedProjectionTypes<'tcx>, + error: &SelectionError<'tcx>, + fallback_has_occurred: bool, + points_at_arg: bool, ) { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - - if predicate.references_error() { - return; - } + let tcx = self.tcx; + let span = obligation.cause.span; - self.probe(|_| { - let err_buf; - let mut err = &error.err; - let mut values = None; + let mut err = match *error { + SelectionError::Unimplemented => { + if let ObligationCauseCode::CompareImplMethodObligation { + item_name, + impl_item_def_id, + trait_item_def_id, + } + | ObligationCauseCode::CompareImplTypeObligation { + item_name, + impl_item_def_id, + trait_item_def_id, + } = obligation.cause.code + { + self.report_extra_impl_obligation( + span, + item_name, + impl_item_def_id, + trait_item_def_id, + &format!("`{}`", obligation.predicate), + ) + .emit(); + return; + } + match obligation.predicate { + ty::Predicate::Trait(ref trait_predicate, _) => { + let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - // try to find the mismatched types to report the error with. - // - // this can fail if the problem was higher-ranked, in which - // cause I have no idea for a good error message. - if let ty::Predicate::Projection(ref data) = predicate { - let mut selcx = SelectionContext::new(self); - let (data, _) = self.replace_bound_vars_with_fresh_vars( - obligation.cause.span, - infer::LateBoundRegionConversionTime::HigherRankedType, - data, - ); - let mut obligations = vec![]; - let normalized_ty = super::normalize_projection_type( - &mut selcx, - obligation.param_env, - data.projection_ty, - obligation.cause.clone(), - 0, - &mut obligations, - ); + if self.tcx.sess.has_errors() && trait_predicate.references_error() { + return; + } + let trait_ref = trait_predicate.to_poly_trait_ref(); + let (post_message, pre_message, type_def) = self + .get_parent_trait_ref(&obligation.cause.code) + .map(|(t, s)| { + ( + format!(" in `{}`", t), + format!("within `{}`, ", t), + s.map(|s| (format!("within this `{}`", t), s)), + ) + }) + .unwrap_or_default(); - debug!( - "report_projection_error obligation.cause={:?} obligation.param_env={:?}", - obligation.cause, obligation.param_env - ); + let OnUnimplementedNote { message, label, note, enclosing_scope } = + self.on_unimplemented_note(trait_ref, obligation); + let have_alt_message = message.is_some() || label.is_some(); + let is_try = self + .tcx + .sess + .source_map() + .span_to_snippet(span) + .map(|s| &s == "?") + .unwrap_or(false); + let is_from = format!("{}", trait_ref.print_only_trait_path()) + .starts_with("std::convert::From<"); + let (message, note) = if is_try && is_from { + ( + Some(format!( + "`?` couldn't convert the error to `{}`", + trait_ref.self_ty(), + )), + Some( + "the question mark operation (`?`) implicitly performs a \ + conversion on the error value using the `From` trait" + .to_owned(), + ), + ) + } else { + (message, note) + }; - debug!( - "report_projection_error normalized_ty={:?} data.ty={:?}", - normalized_ty, data.ty - ); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0277, + "{}", + message.unwrap_or_else(|| format!( + "the trait bound `{}` is not satisfied{}", + trait_ref.without_const().to_predicate(), + post_message, + )) + ); - let is_normalized_ty_expected = match &obligation.cause.code { - ObligationCauseCode::ItemObligation(_) - | ObligationCauseCode::BindingObligation(_, _) - | ObligationCauseCode::ObjectCastObligation(_) => false, - _ => true, + let explanation = + if obligation.cause.code == ObligationCauseCode::MainFunctionType { + "consider using `()`, or a `Result`".to_owned() + } else { + format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_ref.print_only_trait_path(), + trait_ref.self_ty(), + ) + }; + + if self.suggest_add_reference_to_arg( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + have_alt_message, + ) { + self.note_obligation_cause(&mut err, obligation); + err.emit(); + return; + } + if let Some(ref s) = label { + // If it has a custom `#[rustc_on_unimplemented]` + // error message, let's display it as the label! + err.span_label(span, s.as_str()); + err.help(&explanation); + } else { + err.span_label(span, explanation); + } + if let Some((msg, span)) = type_def { + err.span_label(span, &msg); + } + if let Some(ref s) = note { + // If it has a custom `#[rustc_on_unimplemented]` note, let's display it + err.note(s.as_str()); + } + if let Some(ref s) = enclosing_scope { + let enclosing_scope_span = tcx.def_span( + tcx.hir() + .opt_local_def_id(obligation.cause.body_id) + .unwrap_or_else(|| { + tcx.hir().body_owner_def_id(hir::BodyId { + hir_id: obligation.cause.body_id, + }) + }), + ); + + err.span_label(enclosing_scope_span, s.as_str()); + } + + self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); + self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); + self.suggest_remove_reference(&obligation, &mut err, &trait_ref); + self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); + self.note_version_mismatch(&mut err, &trait_ref); + if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { + err.emit(); + return; + } + + // Try to report a help message + if !trait_ref.has_infer_types_or_consts() + && self.predicate_can_apply(obligation.param_env, trait_ref) + { + // If a where-clause may be useful, remind the + // user that they can add it. + // + // don't display an on-unimplemented note, as + // these notes will often be of the form + // "the type `T` can't be frobnicated" + // which is somewhat confusing. + self.suggest_restricting_param_bound( + &mut err, + &trait_ref, + obligation.cause.body_id, + ); + } else { + if !have_alt_message { + // Can't show anything else useful, try to find similar impls. + let impl_candidates = self.find_similar_impl_candidates(trait_ref); + self.report_similar_impl_candidates(impl_candidates, &mut err); + } + self.suggest_change_mut( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + ); + } + + // If this error is due to `!: Trait` not implemented but `(): Trait` is + // implemented, and fallback has occurred, then it could be due to a + // variable that used to fallback to `()` now falling back to `!`. Issue a + // note informing about the change in behaviour. + if trait_predicate.skip_binder().self_ty().is_never() + && fallback_has_occurred + { + let predicate = trait_predicate.map_bound(|mut trait_pred| { + trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( + self.tcx.mk_unit(), + &trait_pred.trait_ref.substs[1..], + ); + trait_pred + }); + let unit_obligation = Obligation { + predicate: ty::Predicate::Trait( + predicate, + hir::Constness::NotConst, + ), + ..obligation.clone() + }; + if self.predicate_may_hold(&unit_obligation) { + err.note( + "the trait is implemented for `()`. \ + Possibly this error has been caused by changes to \ + Rust's type-inference algorithm (see issue #48950 \ + \ + for more information). Consider whether you meant to use \ + the type `()` here instead.", + ); + } + } + + err + } + + ty::Predicate::Subtype(ref predicate) => { + // Errors for Subtype predicates show up as + // `FulfillmentErrorCode::CodeSubtypeError`, + // not selection error. + span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) + } + + ty::Predicate::RegionOutlives(ref predicate) => { + let predicate = self.resolve_vars_if_possible(predicate); + let err = self + .region_outlives_predicate(&obligation.cause, &predicate) + .err() + .unwrap(); + struct_span_err!( + self.tcx.sess, + span, + E0279, + "the requirement `{}` is not satisfied (`{}`)", + predicate, + err, + ) + } + + ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); + struct_span_err!( + self.tcx.sess, + span, + E0280, + "the requirement `{}` is not satisfied", + predicate + ) + } + + ty::Predicate::ObjectSafe(trait_def_id) => { + let violations = self.tcx.object_safety_violations(trait_def_id); + report_object_safety_error(self.tcx, span, trait_def_id, violations) + } + + ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { + let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap(); + let closure_span = self + .tcx + .sess + .source_map() + .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap()); + let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap(); + let mut err = struct_span_err!( + self.tcx.sess, + closure_span, + E0525, + "expected a closure that implements the `{}` trait, \ + but this closure only implements `{}`", + kind, + found_kind + ); + + err.span_label( + closure_span, + format!("this closure implements `{}`, not `{}`", found_kind, kind), + ); + err.span_label( + obligation.cause.span, + format!("the requirement to implement `{}` derives from here", kind), + ); + + // Additional context information explaining why the closure only implements + // a particular trait. + if let Some(tables) = self.in_progress_tables { + let tables = tables.borrow(); + match (found_kind, tables.closure_kind_origins().get(hir_id)) { + (ty::ClosureKind::FnOnce, Some((span, name))) => { + err.span_label( + *span, + format!( + "closure is `FnOnce` because it moves the \ + variable `{}` out of its environment", + name + ), + ); + } + (ty::ClosureKind::FnMut, Some((span, name))) => { + err.span_label( + *span, + format!( + "closure is `FnMut` because it mutates the \ + variable `{}` here", + name + ), + ); + } + _ => {} + } + } + + err.emit(); + return; + } + + ty::Predicate::WellFormed(ty) => { + // WF predicates cannot themselves make + // errors. They can only block due to + // ambiguity; otherwise, they always + // degenerate into other obligations + // (which may fail). + span_bug!(span, "WF predicate not satisfied for {:?}", ty); + } + + ty::Predicate::ConstEvaluatable(..) => { + // Errors for `ConstEvaluatable` predicates show up as + // `SelectionError::ConstEvalFailure`, + // not `Unimplemented`. + span_bug!( + span, + "const-evaluatable requirement gave wrong error: `{:?}`", + obligation + ) + } + } + } + + OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { + let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref); + let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref); + + if expected_trait_ref.self_ty().references_error() { + return; + } + + let found_trait_ty = found_trait_ref.self_ty(); + + let found_did = match found_trait_ty.kind { + ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), + ty::Adt(def, _) => Some(def.did), + _ => None, }; - if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( - is_normalized_ty_expected, - normalized_ty, - data.ty, - ) { - values = Some(infer::ValuePairs::Types(ExpectedFound::new( - is_normalized_ty_expected, - normalized_ty, - data.ty, - ))); + let found_span = found_did + .and_then(|did| self.tcx.hir().span_if_local(did)) + .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def - err_buf = error; - err = &err_buf; + if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + // We check closures twice, with obligations flowing in different directions, + // but we want to complain about them only once. + return; + } + + self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + + let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { + ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], + _ => vec![ArgKind::empty()], + }; + + let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); + let expected = match expected_ty.kind { + ty::Tuple(ref tys) => tys + .iter() + .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) + .collect(), + _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], + }; + + if found.len() == expected.len() { + self.report_closure_arg_mismatch( + span, + found_span, + found_trait_ref, + expected_trait_ref, + ) + } else { + let (closure_span, found) = found_did + .and_then(|did| self.tcx.hir().get_if_local(did)) + .map(|node| { + let (found_span, found) = self.get_fn_like_arguments(node); + (Some(found_span), found) + }) + .unwrap_or((found_span, found)); + + self.report_arg_count_mismatch( + span, + closure_span, + expected, + found, + found_trait_ty.is_closure(), + ) } } - let msg = format!("type mismatch resolving `{}`", predicate); - let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg); - let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); - if fresh { - let mut diag = struct_span_err!( - self.tcx.sess, - obligation.cause.span, - E0271, - "type mismatch resolving `{}`", - predicate - ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); - self.note_obligation_cause(&mut diag, obligation); - diag.emit(); + TraitNotObjectSafe(did) => { + let violations = self.tcx.object_safety_violations(did); + report_object_safety_error(self.tcx, span, did, violations) + } + + ConstEvalFailure(ErrorHandled::TooGeneric) => { + // In this instance, we have a const expression containing an unevaluated + // generic parameter. We have no idea whether this expression is valid or + // not (e.g. it might result in an error), but we don't want to just assume + // that it's okay, because that might result in post-monomorphisation time + // errors. The onus is really on the caller to provide values that it can + // prove are well-formed. + let mut err = self + .tcx + .sess + .struct_span_err(span, "constant expression depends on a generic parameter"); + // FIXME(const_generics): we should suggest to the user how they can resolve this + // issue. However, this is currently not actually possible + // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). + err.note("this may fail depending on what value the parameter takes"); + err + } + + // Already reported in the query. + ConstEvalFailure(ErrorHandled::Reported) => { + self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); + return; } - }); - } - fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { - /// returns the fuzzy category of a given type, or None - /// if the type can be equated to any type. - fn type_category(t: Ty<'_>) -> Option { - match t.kind { - ty::Bool => Some(0), - ty::Char => Some(1), - ty::Str => Some(2), - ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3), - ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4), - ty::Ref(..) | ty::RawPtr(..) => Some(5), - ty::Array(..) | ty::Slice(..) => Some(6), - ty::FnDef(..) | ty::FnPtr(..) => Some(7), - ty::Dynamic(..) => Some(8), - ty::Closure(..) => Some(9), - ty::Tuple(..) => Some(10), - ty::Projection(..) => Some(11), - ty::Param(..) => Some(12), - ty::Opaque(..) => Some(13), - ty::Never => Some(14), - ty::Adt(adt, ..) => match adt.adt_kind() { - AdtKind::Struct => Some(15), - AdtKind::Union => Some(16), - AdtKind::Enum => Some(17), - }, - ty::Generator(..) => Some(18), - ty::Foreign(..) => Some(19), - ty::GeneratorWitness(..) => Some(20), - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + Overflow => { + bug!("overflow should be handled before the `report_selection_error` path"); } - } + }; - match (type_category(a), type_category(b)) { - (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) { - (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, - _ => cat_a == cat_b, - }, - // infer and error can be equated to all types - _ => true, - } - } + self.note_obligation_cause(&mut err, obligation); + self.point_at_returns_when_relevant(&mut err, &obligation); - fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { - self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { - hir::GeneratorKind::Gen => "a generator", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", - hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", - }) + err.emit(); } - fn find_similar_impl_candidates( - &self, - trait_ref: ty::PolyTraitRef<'tcx>, - ) -> Vec> { - let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); - let all_impls = self.tcx.all_impls(trait_ref.def_id()); - - match simp { - Some(simp) => all_impls - .iter() - .filter_map(|&def_id| { - let imp = self.tcx.impl_trait_ref(def_id).unwrap(); - let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); - if let Some(imp_simp) = imp_simp { - if simp != imp_simp { - return None; + /// Given some node representing a fn-like thing in the HIR map, + /// returns a span and `ArgKind` information that describes the + /// arguments it expects. This can be supplied to + /// `report_arg_count_mismatch`. + fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec) { + match node { + Node::Expr(&hir::Expr { + kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), + .. + }) => ( + self.tcx.sess.source_map().def_span(span), + self.tcx + .hir() + .body(id) + .params + .iter() + .map(|arg| { + if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = + *arg.pat + { + ArgKind::Tuple( + Some(span), + args.iter() + .map(|pat| { + let snippet = self + .tcx + .sess + .source_map() + .span_to_snippet(pat.span) + .unwrap(); + (snippet, "_".to_owned()) + }) + .collect::>(), + ) + } else { + let name = + self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap(); + ArgKind::Arg(name, "_".to_owned()) } - } - - Some(imp) - }) - .collect(), - None => { - all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() + }) + .collect::>(), + ), + Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) + | Node::ImplItem(&hir::ImplItem { + span, + kind: hir::ImplItemKind::Method(ref sig, _), + .. + }) + | Node::TraitItem(&hir::TraitItem { + span, + kind: hir::TraitItemKind::Fn(ref sig, _), + .. + }) => ( + self.tcx.sess.source_map().def_span(span), + sig.decl + .inputs + .iter() + .map(|arg| match arg.clone().kind { + hir::TyKind::Tup(ref tys) => ArgKind::Tuple( + Some(arg.span), + vec![("_".to_owned(), "_".to_owned()); tys.len()], + ), + _ => ArgKind::empty(), + }) + .collect::>(), + ), + Node::Ctor(ref variant_data) => { + let span = variant_data + .ctor_hir_id() + .map(|hir_id| self.tcx.hir().span(hir_id)) + .unwrap_or(DUMMY_SP); + let span = self.tcx.sess.source_map().def_span(span); + + (span, vec![ArgKind::empty(); variant_data.fields().len()]) } + _ => panic!("non-FnLike node found: {:?}", node), } } - fn report_similar_impl_candidates( + /// Reports an error when the number of arguments needed by a + /// trait match doesn't match the number that the expression + /// provides. + fn report_arg_count_mismatch( &self, - impl_candidates: Vec>, - err: &mut DiagnosticBuilder<'_>, - ) { - if impl_candidates.is_empty() { - return; - } - - let len = impl_candidates.len(); - let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; + span: Span, + found_span: Option, + expected_args: Vec, + found_args: Vec, + is_closure: bool, + ) -> DiagnosticBuilder<'tcx> { + let kind = if is_closure { "closure" } else { "function" }; - let normalize = |candidate| { - self.tcx.infer_ctxt().enter(|ref infcx| { - let normalized = infcx - .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) - .normalize(candidate) - .ok(); - match normalized { - Some(normalized) => format!("\n {:?}", normalized.value), - None => format!("\n {:?}", candidate), + let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { + let arg_length = arguments.len(); + let distinct = match &other[..] { + &[ArgKind::Tuple(..)] => true, + _ => false, + }; + match (arg_length, arguments.get(0)) { + (1, Some(&ArgKind::Tuple(_, ref fields))) => { + format!("a single {}-tuple as argument", fields.len()) } - }) + _ => format!( + "{} {}argument{}", + arg_length, + if distinct && arg_length > 1 { "distinct " } else { "" }, + pluralize!(arg_length) + ), + } }; - // Sort impl candidates so that ordering is consistent for UI tests. - let mut normalized_impl_candidates = - impl_candidates.iter().map(normalize).collect::>(); - - // Sort before taking the `..end` range, - // because the ordering of `impl_candidates` may not be deterministic: - // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 - normalized_impl_candidates.sort(); - - err.help(&format!( - "the following implementations were found:{}{}", - normalized_impl_candidates[..end].join(""), - if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } - )); - } + let expected_str = args_str(&expected_args, &found_args); + let found_str = args_str(&found_args, &expected_args); - /// Reports that an overflow has occurred and halts compilation. We - /// halt compilation unconditionally because it is important that - /// overflows never be masked -- they basically represent computations - /// whose result could not be truly determined and thus we can't say - /// if the program type checks or not -- and they are unusual - /// occurrences in any case. - pub fn report_overflow_error( - &self, - obligation: &Obligation<'tcx, T>, - suggest_increasing_limit: bool, - ) -> ! - where - T: fmt::Display + TypeFoldable<'tcx>, - { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); let mut err = struct_span_err!( self.tcx.sess, - obligation.cause.span, - E0275, - "overflow evaluating the requirement `{}`", - predicate + span, + E0593, + "{} is expected to take {}, but it takes {}", + kind, + expected_str, + found_str, ); - if suggest_increasing_limit { - self.suggest_new_overflow_limit(&mut err); - } - - self.note_obligation_cause_code( - &mut err, - &obligation.predicate, - &obligation.cause.code, - &mut vec![], - ); + err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); - err.emit(); - self.tcx.sess.abort_if_errors(); - bug!(); - } + if let Some(found_span) = found_span { + err.span_label(found_span, format!("takes {}", found_str)); - /// Reports that a cycle was detected which led to overflow and halts - /// compilation. This is equivalent to `report_overflow_error` except - /// that we can give a more helpful error message (and, in particular, - /// we do not suggest increasing the overflow limit, which is not - /// going to help). - pub fn report_overflow_error_cycle(&self, cycle: &[PredicateObligation<'tcx>]) -> ! { - let cycle = self.resolve_vars_if_possible(&cycle.to_owned()); - assert!(!cycle.is_empty()); + // move |_| { ... } + // ^^^^^^^^-- def_span + // + // move |_| { ... } + // ^^^^^-- prefix + let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); + // move |_| { ... } + // ^^^-- pipe_span + let pipe_span = + if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span }; + + // Suggest to take and ignore the arguments with expected_args_length `_`s if + // found arguments is empty (assume the user just wants to ignore args in this case). + // For example, if `expected_args_length` is 2, suggest `|_, _|`. + if found_args.is_empty() && is_closure { + let underscores = vec!["_"; expected_args.len()].join(", "); + err.span_suggestion( + pipe_span, + &format!( + "consider changing the closure to take and ignore the expected argument{}", + if expected_args.len() < 2 { "" } else { "s" } + ), + format!("|{}|", underscores), + Applicability::MachineApplicable, + ); + } - debug!("report_overflow_error_cycle: cycle={:?}", cycle); + if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { + if fields.len() == expected_args.len() { + let sugg = fields + .iter() + .map(|(name, _)| name.to_owned()) + .collect::>() + .join(", "); + err.span_suggestion( + found_span, + "change the closure to take multiple arguments instead of a single tuple", + format!("|{}|", sugg), + Applicability::MachineApplicable, + ); + } + } + if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { + if fields.len() == found_args.len() && is_closure { + let sugg = format!( + "|({}){}|", + found_args + .iter() + .map(|arg| match arg { + ArgKind::Arg(name, _) => name.to_owned(), + _ => "_".to_owned(), + }) + .collect::>() + .join(", "), + // add type annotations if available + if found_args.iter().any(|arg| match arg { + ArgKind::Arg(_, ty) => ty != "_", + _ => false, + }) { + format!( + ": ({})", + fields + .iter() + .map(|(_, ty)| ty.to_owned()) + .collect::>() + .join(", ") + ) + } else { + String::new() + }, + ); + err.span_suggestion( + found_span, + "change the closure to accept a tuple instead of individual arguments", + sugg, + Applicability::MachineApplicable, + ); + } + } + } - self.report_overflow_error(&cycle[0], false); + err } +} + +trait InferCtxtPrivExt<'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool; - pub fn report_extra_impl_obligation( + fn report_fulfillment_error( &self, - error_span: Span, - item_name: ast::Name, - _impl_item_def_id: DefId, - trait_item_def_id: DefId, - requirement: &dyn fmt::Display, - ) -> DiagnosticBuilder<'tcx> { - let msg = "impl has stricter requirements than trait"; - let sp = self.tcx.sess.source_map().def_span(error_span); + error: &FulfillmentError<'tcx>, + body_id: Option, + fallback_has_occurred: bool, + ); + + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ); - let mut err = struct_span_err!(self.tcx.sess, sp, E0276, "{}", msg); + fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool; - if let Some(trait_item_span) = self.tcx.hir().span_if_local(trait_item_def_id) { - let span = self.tcx.sess.source_map().def_span(trait_item_span); - err.span_label(span, format!("definition of `{}` from trait", item_name)); - } + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str>; - err.span_label(sp, format!("impl has extra requirement {}", requirement)); + fn find_similar_impl_candidates( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Vec>; - err - } + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ); /// Gets the parent trait chain start fn get_parent_trait_ref( &self, code: &ObligationCauseCode<'tcx>, - ) -> Option<(String, Option)> { - match code { - &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { - let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); - match self.get_parent_trait_ref(&data.parent_code) { - Some(t) => Some(t), - None => { - let ty = parent_trait_ref.skip_binder().self_ty(); - let span = - TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); - Some((ty.to_string(), span)) - } - } - } - _ => None, - } - } + ) -> Option<(String, Option)>; + + /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait + /// with the same path as `trait_ref`, a help message about + /// a probable version mismatch is added to `err` + fn note_version_mismatch( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'tcx>, + ); + + fn mk_obligation_for_def_id( + &self, + def_id: DefId, + output_ty: Ty<'tcx>, + cause: ObligationCause<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> PredicateObligation<'tcx>; - pub fn report_selection_error( + fn maybe_report_ambiguity( &self, obligation: &PredicateObligation<'tcx>, - error: &SelectionError<'tcx>, - fallback_has_occurred: bool, - points_at_arg: bool, - ) { - let tcx = self.tcx; - let span = obligation.cause.span; - - let mut err = match *error { - SelectionError::Unimplemented => { - if let ObligationCauseCode::CompareImplMethodObligation { - item_name, - impl_item_def_id, - trait_item_def_id, - } - | ObligationCauseCode::CompareImplTypeObligation { - item_name, - impl_item_def_id, - trait_item_def_id, - } = obligation.cause.code - { - self.report_extra_impl_obligation( - span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}`", obligation.predicate), - ) - .emit(); - return; - } - match obligation.predicate { - ty::Predicate::Trait(ref trait_predicate, _) => { - let trait_predicate = self.resolve_vars_if_possible(trait_predicate); - - if self.tcx.sess.has_errors() && trait_predicate.references_error() { - return; - } - let trait_ref = trait_predicate.to_poly_trait_ref(); - let (post_message, pre_message, type_def) = self - .get_parent_trait_ref(&obligation.cause.code) - .map(|(t, s)| { - ( - format!(" in `{}`", t), - format!("within `{}`, ", t), - s.map(|s| (format!("within this `{}`", t), s)), - ) - }) - .unwrap_or_default(); - - let OnUnimplementedNote { message, label, note, enclosing_scope } = - self.on_unimplemented_note(trait_ref, obligation); - let have_alt_message = message.is_some() || label.is_some(); - let is_try = self - .tcx - .sess - .source_map() - .span_to_snippet(span) - .map(|s| &s == "?") - .unwrap_or(false); - let is_from = format!("{}", trait_ref.print_only_trait_path()) - .starts_with("std::convert::From<"); - let (message, note) = if is_try && is_from { - ( - Some(format!( - "`?` couldn't convert the error to `{}`", - trait_ref.self_ty(), - )), - Some( - "the question mark operation (`?`) implicitly performs a \ - conversion on the error value using the `From` trait" - .to_owned(), - ), - ) - } else { - (message, note) - }; + body_id: Option, + ); - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0277, - "{}", - message.unwrap_or_else(|| format!( - "the trait bound `{}` is not satisfied{}", - trait_ref.without_const().to_predicate(), - post_message, - )) - ); + fn predicate_can_apply( + &self, + param_env: ty::ParamEnv<'tcx>, + pred: ty::PolyTraitRef<'tcx>, + ) -> bool; - let explanation = - if obligation.cause.code == ObligationCauseCode::MainFunctionType { - "consider using `()`, or a `Result`".to_owned() - } else { - format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_ref.print_only_trait_path(), - trait_ref.self_ty(), - ) - }; + fn note_obligation_cause( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ); - if self.suggest_add_reference_to_arg( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - have_alt_message, - ) { - self.note_obligation_cause(&mut err, obligation); - err.emit(); - return; - } - if let Some(ref s) = label { - // If it has a custom `#[rustc_on_unimplemented]` - // error message, let's display it as the label! - err.span_label(span, s.as_str()); - err.help(&explanation); - } else { - err.span_label(span, explanation); - } - if let Some((msg, span)) = type_def { - err.span_label(span, &msg); - } - if let Some(ref s) = note { - // If it has a custom `#[rustc_on_unimplemented]` note, let's display it - err.note(s.as_str()); - } - if let Some(ref s) = enclosing_scope { - let enclosing_scope_span = tcx.def_span( - tcx.hir() - .opt_local_def_id(obligation.cause.body_id) - .unwrap_or_else(|| { - tcx.hir().body_owner_def_id(hir::BodyId { - hir_id: obligation.cause.body_id, - }) - }), - ); + fn suggest_unsized_bound_if_applicable( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ); - err.span_label(enclosing_scope_span, s.as_str()); - } + fn is_recursive_obligation( + &self, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + cause_code: &ObligationCauseCode<'tcx>, + ) -> bool; +} - self.suggest_borrow_on_unsized_slice(&obligation.cause.code, &mut err); - self.suggest_fn_call(&obligation, &mut err, &trait_ref, points_at_arg); - self.suggest_remove_reference(&obligation, &mut err, &trait_ref); - self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); - self.note_version_mismatch(&mut err, &trait_ref); - if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { - err.emit(); - return; - } +impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { + // returns if `cond` not occurring implies that `error` does not occur - i.e., that + // `error` occurring implies that `cond` occurs. + fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool { + if cond == error { + return true; + } - // Try to report a help message - if !trait_ref.has_infer_types_or_consts() - && self.predicate_can_apply(obligation.param_env, trait_ref) - { - // If a where-clause may be useful, remind the - // user that they can add it. - // - // don't display an on-unimplemented note, as - // these notes will often be of the form - // "the type `T` can't be frobnicated" - // which is somewhat confusing. - self.suggest_restricting_param_bound( - &mut err, - &trait_ref, - obligation.cause.body_id, - ); - } else { - if !have_alt_message { - // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_ref); - self.report_similar_impl_candidates(impl_candidates, &mut err); - } - self.suggest_change_mut( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - ); - } + let (cond, error) = match (cond, error) { + (&ty::Predicate::Trait(..), &ty::Predicate::Trait(ref error, _)) => (cond, error), + _ => { + // FIXME: make this work in other cases too. + return false; + } + }; - // If this error is due to `!: Trait` not implemented but `(): Trait` is - // implemented, and fallback has occurred, then it could be due to a - // variable that used to fallback to `()` now falling back to `!`. Issue a - // note informing about the change in behaviour. - if trait_predicate.skip_binder().self_ty().is_never() - && fallback_has_occurred - { - let predicate = trait_predicate.map_bound(|mut trait_pred| { - trait_pred.trait_ref.substs = self.tcx.mk_substs_trait( - self.tcx.mk_unit(), - &trait_pred.trait_ref.substs[1..], - ); - trait_pred - }); - let unit_obligation = Obligation { - predicate: ty::Predicate::Trait( - predicate, - hir::Constness::NotConst, - ), - ..obligation.clone() - }; - if self.predicate_may_hold(&unit_obligation) { - err.note( - "the trait is implemented for `()`. \ - Possibly this error has been caused by changes to \ - Rust's type-inference algorithm (see issue #48950 \ - \ - for more information). Consider whether you meant to use \ - the type `()` here instead.", - ); - } - } + for implication in super::elaborate_predicates(self.tcx, vec![*cond]) { + if let ty::Predicate::Trait(implication, _) = implication { + let error = error.to_poly_trait_ref(); + let implication = implication.to_poly_trait_ref(); + // FIXME: I'm just not taking associated types at all here. + // Eventually I'll need to implement param-env-aware + // `Γ₁ ⊦ φ₁ => Γ₂ ⊦ φ₂` logic. + let param_env = ty::ParamEnv::empty(); + if self.can_sub(param_env, error, implication).is_ok() { + debug!("error_implies: {:?} -> {:?} -> {:?}", cond, error, implication); + return true; + } + } + } - err - } + false + } - ty::Predicate::Subtype(ref predicate) => { - // Errors for Subtype predicates show up as - // `FulfillmentErrorCode::CodeSubtypeError`, - // not selection error. - span_bug!(span, "subtype requirement gave wrong error: `{:?}`", predicate) - } + fn report_fulfillment_error( + &self, + error: &FulfillmentError<'tcx>, + body_id: Option, + fallback_has_occurred: bool, + ) { + debug!("report_fulfillment_error({:?})", error); + match error.code { + FulfillmentErrorCode::CodeSelectionError(ref selection_error) => { + self.report_selection_error( + &error.obligation, + selection_error, + fallback_has_occurred, + error.points_at_arg_span, + ); + } + FulfillmentErrorCode::CodeProjectionError(ref e) => { + self.report_projection_error(&error.obligation, e); + } + FulfillmentErrorCode::CodeAmbiguity => { + self.maybe_report_ambiguity(&error.obligation, body_id); + } + FulfillmentErrorCode::CodeSubtypeError(ref expected_found, ref err) => { + self.report_mismatched_types( + &error.obligation.cause, + expected_found.expected, + expected_found.found, + err.clone(), + ) + .emit(); + } + } + } - ty::Predicate::RegionOutlives(ref predicate) => { - let predicate = self.resolve_vars_if_possible(predicate); - let err = self - .region_outlives_predicate(&obligation.cause, &predicate) - .err() - .unwrap(); - struct_span_err!( - self.tcx.sess, - span, - E0279, - "the requirement `{}` is not satisfied (`{}`)", - predicate, - err, - ) - } + fn report_projection_error( + &self, + obligation: &PredicateObligation<'tcx>, + error: &MismatchedProjectionTypes<'tcx>, + ) { + let predicate = self.resolve_vars_if_possible(&obligation.predicate); - ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => { - let predicate = self.resolve_vars_if_possible(&obligation.predicate); - struct_span_err!( - self.tcx.sess, - span, - E0280, - "the requirement `{}` is not satisfied", - predicate - ) - } + if predicate.references_error() { + return; + } - ty::Predicate::ObjectSafe(trait_def_id) => { - let violations = self.tcx.object_safety_violations(trait_def_id); - report_object_safety_error(self.tcx, span, trait_def_id, violations) - } + self.probe(|_| { + let err_buf; + let mut err = &error.err; + let mut values = None; - ty::Predicate::ClosureKind(closure_def_id, closure_substs, kind) => { - let found_kind = self.closure_kind(closure_def_id, closure_substs).unwrap(); - let closure_span = self - .tcx - .sess - .source_map() - .def_span(self.tcx.hir().span_if_local(closure_def_id).unwrap()); - let hir_id = self.tcx.hir().as_local_hir_id(closure_def_id).unwrap(); - let mut err = struct_span_err!( - self.tcx.sess, - closure_span, - E0525, - "expected a closure that implements the `{}` trait, \ - but this closure only implements `{}`", - kind, - found_kind - ); + // try to find the mismatched types to report the error with. + // + // this can fail if the problem was higher-ranked, in which + // cause I have no idea for a good error message. + if let ty::Predicate::Projection(ref data) = predicate { + let mut selcx = SelectionContext::new(self); + let (data, _) = self.replace_bound_vars_with_fresh_vars( + obligation.cause.span, + infer::LateBoundRegionConversionTime::HigherRankedType, + data, + ); + let mut obligations = vec![]; + let normalized_ty = super::normalize_projection_type( + &mut selcx, + obligation.param_env, + data.projection_ty, + obligation.cause.clone(), + 0, + &mut obligations, + ); - err.span_label( - closure_span, - format!("this closure implements `{}`, not `{}`", found_kind, kind), - ); - err.span_label( - obligation.cause.span, - format!("the requirement to implement `{}` derives from here", kind), - ); + debug!( + "report_projection_error obligation.cause={:?} obligation.param_env={:?}", + obligation.cause, obligation.param_env + ); - // Additional context information explaining why the closure only implements - // a particular trait. - if let Some(tables) = self.in_progress_tables { - let tables = tables.borrow(); - match (found_kind, tables.closure_kind_origins().get(hir_id)) { - (ty::ClosureKind::FnOnce, Some((span, name))) => { - err.span_label( - *span, - format!( - "closure is `FnOnce` because it moves the \ - variable `{}` out of its environment", - name - ), - ); - } - (ty::ClosureKind::FnMut, Some((span, name))) => { - err.span_label( - *span, - format!( - "closure is `FnMut` because it mutates the \ - variable `{}` here", - name - ), - ); - } - _ => {} - } - } + debug!( + "report_projection_error normalized_ty={:?} data.ty={:?}", + normalized_ty, data.ty + ); - err.emit(); - return; - } + let is_normalized_ty_expected = match &obligation.cause.code { + ObligationCauseCode::ItemObligation(_) + | ObligationCauseCode::BindingObligation(_, _) + | ObligationCauseCode::ObjectCastObligation(_) => false, + _ => true, + }; - ty::Predicate::WellFormed(ty) => { - // WF predicates cannot themselves make - // errors. They can only block due to - // ambiguity; otherwise, they always - // degenerate into other obligations - // (which may fail). - span_bug!(span, "WF predicate not satisfied for {:?}", ty); - } + if let Err(error) = self.at(&obligation.cause, obligation.param_env).eq_exp( + is_normalized_ty_expected, + normalized_ty, + data.ty, + ) { + values = Some(infer::ValuePairs::Types(ExpectedFound::new( + is_normalized_ty_expected, + normalized_ty, + data.ty, + ))); - ty::Predicate::ConstEvaluatable(..) => { - // Errors for `ConstEvaluatable` predicates show up as - // `SelectionError::ConstEvalFailure`, - // not `Unimplemented`. - span_bug!( - span, - "const-evaluatable requirement gave wrong error: `{:?}`", - obligation - ) - } + err_buf = error; + err = &err_buf; } } - OutputTypeParameterMismatch(ref found_trait_ref, ref expected_trait_ref, _) => { - let found_trait_ref = self.resolve_vars_if_possible(&*found_trait_ref); - let expected_trait_ref = self.resolve_vars_if_possible(&*expected_trait_ref); - - if expected_trait_ref.self_ty().references_error() { - return; - } + let msg = format!("type mismatch resolving `{}`", predicate); + let error_id = (DiagnosticMessageId::ErrorId(271), Some(obligation.cause.span), msg); + let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + let mut diag = struct_span_err!( + self.tcx.sess, + obligation.cause.span, + E0271, + "type mismatch resolving `{}`", + predicate + ); + self.note_type_err(&mut diag, &obligation.cause, None, values, err); + self.note_obligation_cause(&mut diag, obligation); + diag.emit(); + } + }); + } - let found_trait_ty = found_trait_ref.self_ty(); + fn fuzzy_match_tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool { + /// returns the fuzzy category of a given type, or None + /// if the type can be equated to any type. + fn type_category(t: Ty<'_>) -> Option { + match t.kind { + ty::Bool => Some(0), + ty::Char => Some(1), + ty::Str => Some(2), + ty::Int(..) | ty::Uint(..) | ty::Infer(ty::IntVar(..)) => Some(3), + ty::Float(..) | ty::Infer(ty::FloatVar(..)) => Some(4), + ty::Ref(..) | ty::RawPtr(..) => Some(5), + ty::Array(..) | ty::Slice(..) => Some(6), + ty::FnDef(..) | ty::FnPtr(..) => Some(7), + ty::Dynamic(..) => Some(8), + ty::Closure(..) => Some(9), + ty::Tuple(..) => Some(10), + ty::Projection(..) => Some(11), + ty::Param(..) => Some(12), + ty::Opaque(..) => Some(13), + ty::Never => Some(14), + ty::Adt(adt, ..) => match adt.adt_kind() { + AdtKind::Struct => Some(15), + AdtKind::Union => Some(16), + AdtKind::Enum => Some(17), + }, + ty::Generator(..) => Some(18), + ty::Foreign(..) => Some(19), + ty::GeneratorWitness(..) => Some(20), + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, + ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), + } + } - let found_did = match found_trait_ty.kind { - ty::Closure(did, _) | ty::Foreign(did) | ty::FnDef(did, _) => Some(did), - ty::Adt(def, _) => Some(def.did), - _ => None, - }; + match (type_category(a), type_category(b)) { + (Some(cat_a), Some(cat_b)) => match (&a.kind, &b.kind) { + (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => def_a == def_b, + _ => cat_a == cat_b, + }, + // infer and error can be equated to all types + _ => true, + } + } - let found_span = found_did - .and_then(|did| self.tcx.hir().span_if_local(did)) - .map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def + fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> { + self.tcx.hir().body(body_id).generator_kind.map(|gen_kind| match gen_kind { + hir::GeneratorKind::Gen => "a generator", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Block) => "an async block", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Fn) => "an async function", + hir::GeneratorKind::Async(hir::AsyncGeneratorKind::Closure) => "an async closure", + }) + } - if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { - // We check closures twice, with obligations flowing in different directions, - // but we want to complain about them only once. - return; - } + fn find_similar_impl_candidates( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + ) -> Vec> { + let simp = fast_reject::simplify_type(self.tcx, trait_ref.skip_binder().self_ty(), true); + let all_impls = self.tcx.all_impls(trait_ref.def_id()); - self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + match simp { + Some(simp) => all_impls + .iter() + .filter_map(|&def_id| { + let imp = self.tcx.impl_trait_ref(def_id).unwrap(); + let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true); + if let Some(imp_simp) = imp_simp { + if simp != imp_simp { + return None; + } + } - let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { - ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], - _ => vec![ArgKind::empty()], - }; + Some(imp) + }) + .collect(), + None => { + all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect() + } + } + } - let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1); - let expected = match expected_ty.kind { - ty::Tuple(ref tys) => tys - .iter() - .map(|t| ArgKind::from_expected_ty(t.expect_ty(), Some(span))) - .collect(), - _ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())], - }; + fn report_similar_impl_candidates( + &self, + impl_candidates: Vec>, + err: &mut DiagnosticBuilder<'_>, + ) { + if impl_candidates.is_empty() { + return; + } - if found.len() == expected.len() { - self.report_closure_arg_mismatch( - span, - found_span, - found_trait_ref, - expected_trait_ref, - ) - } else { - let (closure_span, found) = found_did - .and_then(|did| self.tcx.hir().get_if_local(did)) - .map(|node| { - let (found_span, found) = self.get_fn_like_arguments(node); - (Some(found_span), found) - }) - .unwrap_or((found_span, found)); + let len = impl_candidates.len(); + let end = if impl_candidates.len() <= 5 { impl_candidates.len() } else { 4 }; - self.report_arg_count_mismatch( - span, - closure_span, - expected, - found, - found_trait_ty.is_closure(), - ) + let normalize = |candidate| { + self.tcx.infer_ctxt().enter(|ref infcx| { + let normalized = infcx + .at(&ObligationCause::dummy(), ty::ParamEnv::empty()) + .normalize(candidate) + .ok(); + match normalized { + Some(normalized) => format!("\n {:?}", normalized.value), + None => format!("\n {:?}", candidate), } - } + }) + }; - TraitNotObjectSafe(did) => { - let violations = self.tcx.object_safety_violations(did); - report_object_safety_error(self.tcx, span, did, violations) - } + // Sort impl candidates so that ordering is consistent for UI tests. + let mut normalized_impl_candidates = + impl_candidates.iter().map(normalize).collect::>(); - ConstEvalFailure(ErrorHandled::TooGeneric) => { - // In this instance, we have a const expression containing an unevaluated - // generic parameter. We have no idea whether this expression is valid or - // not (e.g. it might result in an error), but we don't want to just assume - // that it's okay, because that might result in post-monomorphisation time - // errors. The onus is really on the caller to provide values that it can - // prove are well-formed. - let mut err = self - .tcx - .sess - .struct_span_err(span, "constant expression depends on a generic parameter"); - // FIXME(const_generics): we should suggest to the user how they can resolve this - // issue. However, this is currently not actually possible - // (see https://github.com/rust-lang/rust/issues/66962#issuecomment-575907083). - err.note("this may fail depending on what value the parameter takes"); - err - } + // Sort before taking the `..end` range, + // because the ordering of `impl_candidates` may not be deterministic: + // https://github.com/rust-lang/rust/pull/57475#issuecomment-455519507 + normalized_impl_candidates.sort(); - // Already reported in the query. - ConstEvalFailure(ErrorHandled::Reported) => { - self.tcx.sess.delay_span_bug(span, "constant in type had an ignored error"); - return; - } + err.help(&format!( + "the following implementations were found:{}{}", + normalized_impl_candidates[..end].join(""), + if len > 5 { format!("\nand {} others", len - 4) } else { String::new() } + )); + } - Overflow => { - bug!("overflow should be handled before the `report_selection_error` path"); + /// Gets the parent trait chain start + fn get_parent_trait_ref( + &self, + code: &ObligationCauseCode<'tcx>, + ) -> Option<(String, Option)> { + match code { + &ObligationCauseCode::BuiltinDerivedObligation(ref data) => { + let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); + match self.get_parent_trait_ref(&data.parent_code) { + Some(t) => Some(t), + None => { + let ty = parent_trait_ref.skip_binder().self_ty(); + let span = + TyCategory::from_ty(ty).map(|(_, def_id)| self.tcx.def_span(def_id)); + Some((ty.to_string(), span)) + } + } } - }; - - self.note_obligation_cause(&mut err, obligation); - self.point_at_returns_when_relevant(&mut err, &obligation); - - err.emit(); + _ => None, + } } /// If the `Self` type of the unsatisfied trait `trait_ref` implements a trait @@ -990,102 +1319,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::TraitRef { def_id, substs: self.tcx.mk_substs_trait(output_ty, &[]) }; Obligation::new(cause, param_env, new_trait_ref.without_const().to_predicate()) } -} - -pub fn recursive_type_with_infinite_size_error( - tcx: TyCtxt<'tcx>, - type_def_id: DefId, -) -> DiagnosticBuilder<'tcx> { - assert!(type_def_id.is_local()); - let span = tcx.hir().span_if_local(type_def_id).unwrap(); - let span = tcx.sess.source_map().def_span(span); - let mut err = struct_span_err!( - tcx.sess, - span, - E0072, - "recursive type `{}` has infinite size", - tcx.def_path_str(type_def_id) - ); - err.span_label(span, "recursive type has infinite size"); - err.help(&format!( - "insert indirection (e.g., a `Box`, `Rc`, or `&`) \ - at some point to make `{}` representable", - tcx.def_path_str(type_def_id) - )); - err -} - -pub fn report_object_safety_error( - tcx: TyCtxt<'tcx>, - span: Span, - trait_def_id: DefId, - violations: Vec, -) -> DiagnosticBuilder<'tcx> { - let trait_str = tcx.def_path_str(trait_def_id); - let trait_span = tcx.hir().get_if_local(trait_def_id).and_then(|node| match node { - hir::Node::Item(item) => Some(item.ident.span), - _ => None, - }); - let span = tcx.sess.source_map().def_span(span); - let mut err = struct_span_err!( - tcx.sess, - span, - E0038, - "the trait `{}` cannot be made into an object", - trait_str - ); - err.span_label(span, format!("the trait `{}` cannot be made into an object", trait_str)); - - let mut reported_violations = FxHashSet::default(); - let mut had_span_label = false; - for violation in violations { - if let ObjectSafetyViolation::SizedSelf(sp) = &violation { - if !sp.is_empty() { - // Do not report `SizedSelf` without spans pointing at `SizedSelf` obligations - // with a `Span`. - reported_violations.insert(ObjectSafetyViolation::SizedSelf(vec![].into())); - } - } - if reported_violations.insert(violation.clone()) { - let spans = violation.spans(); - let msg = if trait_span.is_none() || spans.is_empty() { - format!("the trait cannot be made into an object because {}", violation.error_msg()) - } else { - had_span_label = true; - format!("...because {}", violation.error_msg()) - }; - if spans.is_empty() { - err.note(&msg); - } else { - for span in spans { - err.span_label(span, &msg); - } - } - match (trait_span, violation.solution()) { - (Some(_), Some((note, None))) => { - err.help(¬e); - } - (Some(_), Some((note, Some((sugg, span))))) => { - err.span_suggestion(span, ¬e, sugg, Applicability::MachineApplicable); - } - // Only provide the help if its a local trait, otherwise it's not actionable. - _ => {} - } - } - } - if let (Some(trait_span), true) = (trait_span, had_span_label) { - err.span_label(trait_span, "this trait cannot be made into an object..."); - } - - if tcx.sess.trait_methods_not_found.borrow().contains(&span) { - // Avoid emitting error caused by non-existing method (#58734) - err.cancel(); - } - - err -} -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { fn maybe_report_ambiguity( &self, obligation: &PredicateObligation<'tcx>, @@ -1385,6 +1619,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } +pub fn recursive_type_with_infinite_size_error( + tcx: TyCtxt<'tcx>, + type_def_id: DefId, +) -> DiagnosticBuilder<'tcx> { + assert!(type_def_id.is_local()); + let span = tcx.hir().span_if_local(type_def_id).unwrap(); + let span = tcx.sess.source_map().def_span(span); + let mut err = struct_span_err!( + tcx.sess, + span, + E0072, + "recursive type `{}` has infinite size", + tcx.def_path_str(type_def_id) + ); + err.span_label(span, "recursive type has infinite size"); + err.help(&format!( + "insert indirection (e.g., a `Box`, `Rc`, or `&`) \ + at some point to make `{}` representable", + tcx.def_path_str(type_def_id) + )); + err +} + /// Summarizes information #[derive(Clone)] pub enum ArgKind { diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index eb34a487596..6e3074cd3ca 100644 --- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -8,7 +8,27 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { +use super::InferCtxtPrivExt; + +crate trait InferCtxtExt<'tcx> { + /*private*/ + fn impl_similar_to( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> Option; + + /*private*/ + fn describe_enclosure(&self, hir_id: hir::HirId) -> Option<&'static str>; + + fn on_unimplemented_note( + &self, + trait_ref: ty::PolyTraitRef<'tcx>, + obligation: &PredicateObligation<'tcx>, + ) -> OnUnimplementedNote; +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { fn impl_similar_to( &self, trait_ref: ty::PolyTraitRef<'tcx>, @@ -101,7 +121,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn on_unimplemented_note( + fn on_unimplemented_note( &self, trait_ref: ty::PolyTraitRef<'tcx>, obligation: &PredicateObligation<'tcx>, diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 228747c3f89..351e557d40b 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1,6 +1,5 @@ use super::{ - ArgKind, EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, - PredicateObligation, + EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, }; use crate::infer::InferCtxt; @@ -8,9 +7,7 @@ use crate::traits::error_reporting::suggest_constraining_type_param; use rustc::ty::TypeckTables; use rustc::ty::{self, AdtKind, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; -use rustc_errors::{ - error_code, pluralize, struct_span_err, Applicability, DiagnosticBuilder, Style, -}; +use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -20,8 +17,136 @@ use rustc_span::symbol::{kw, sym}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - crate fn suggest_restricting_param_bound( +use super::InferCtxtPrivExt; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; + +crate trait InferCtxtExt<'tcx> { + fn suggest_restricting_param_bound( + &self, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::PolyTraitRef<'_>, + body_id: hir::HirId, + ); + + fn suggest_borrow_on_unsized_slice( + &self, + code: &ObligationCauseCode<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + ); + + fn get_closure_name( + &self, + def_id: DefId, + err: &mut DiagnosticBuilder<'_>, + msg: &str, + ) -> Option; + + fn suggest_fn_call( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'_>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ); + + fn suggest_add_reference_to_arg( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + has_custom_message: bool, + ) -> bool; + + fn suggest_remove_reference( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + ); + + fn suggest_change_mut( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + trait_ref: &ty::Binder>, + points_at_arg: bool, + ); + + fn suggest_semicolon_removal( + &self, + obligation: &PredicateObligation<'tcx>, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + trait_ref: &ty::Binder>, + ); + + fn suggest_impl_trait( + &self, + err: &mut DiagnosticBuilder<'tcx>, + span: Span, + obligation: &PredicateObligation<'tcx>, + trait_ref: &ty::Binder>, + ) -> bool; + + fn point_at_returns_when_relevant( + &self, + err: &mut DiagnosticBuilder<'tcx>, + obligation: &PredicateObligation<'tcx>, + ); + + fn report_closure_arg_mismatch( + &self, + span: Span, + found_span: Option, + expected_ref: ty::PolyTraitRef<'tcx>, + found: ty::PolyTraitRef<'tcx>, + ) -> DiagnosticBuilder<'tcx>; + + fn suggest_fully_qualified_path( + &self, + err: &mut DiagnosticBuilder<'_>, + def_id: DefId, + span: Span, + trait_ref: DefId, + ); + + fn maybe_note_obligation_cause_for_async_await( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ) -> bool; + + fn note_obligation_cause_for_async_await( + &self, + err: &mut DiagnosticBuilder<'_>, + target_span: Span, + scope_span: &Option, + expr: Option, + snippet: String, + first_generator: DefId, + last_generator: Option, + trait_ref: ty::TraitRef<'_>, + target_ty: Ty<'tcx>, + tables: &ty::TypeckTables<'_>, + obligation: &PredicateObligation<'tcx>, + next_code: Option<&ObligationCauseCode<'tcx>>, + ); + + fn note_obligation_cause_code( + &self, + err: &mut DiagnosticBuilder<'_>, + predicate: &T, + cause_code: &ObligationCauseCode<'tcx>, + obligated_types: &mut Vec<&ty::TyS<'tcx>>, + ) where + T: fmt::Display; + + fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>); +} + +impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { + fn suggest_restricting_param_bound( &self, mut err: &mut DiagnosticBuilder<'_>, trait_ref: &ty::PolyTraitRef<'_>, @@ -168,7 +293,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// When encountering an assignment of an unsized trait, like `let x = ""[..];`, provide a /// suggestion to borrow the initializer in order to use have a slice instead. - crate fn suggest_borrow_on_unsized_slice( + fn suggest_borrow_on_unsized_slice( &self, code: &ObligationCauseCode<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -195,7 +320,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Given a closure's `DefId`, return the given name of the closure. /// /// This doesn't account for reassignments, but it's only used for suggestions. - crate fn get_closure_name( + fn get_closure_name( &self, def_id: DefId, err: &mut DiagnosticBuilder<'_>, @@ -233,7 +358,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// We tried to apply the bound to an `fn` or closure. Check whether calling it would /// evaluate to a type that *would* satisfy the trait binding. If it would, suggest calling /// it: `bar(foo)` → `bar(foo())`. This case is *very* likely to be hit if `foo` is `async`. - crate fn suggest_fn_call( + fn suggest_fn_call( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'_>, @@ -317,7 +442,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_add_reference_to_arg( + fn suggest_add_reference_to_arg( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -389,7 +514,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Whenever references are used by mistake, like `for (i, e) in &vec.iter().enumerate()`, /// suggest removing these references until we reach a type that implements the trait. - crate fn suggest_remove_reference( + fn suggest_remove_reference( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -451,7 +576,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Check if the trait bound is implemented for a different mutability and note it in the /// final error. - crate fn suggest_change_mut( + fn suggest_change_mut( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -513,7 +638,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_semicolon_removal( + fn suggest_semicolon_removal( &self, obligation: &PredicateObligation<'tcx>, err: &mut DiagnosticBuilder<'tcx>, @@ -549,7 +674,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// If all conditions are met to identify a returned `dyn Trait`, suggest using `impl Trait` if /// applicable and signal that the error has been expanded appropriately and needs to be /// emitted. - crate fn suggest_impl_trait( + fn suggest_impl_trait( &self, err: &mut DiagnosticBuilder<'tcx>, span: Span, @@ -723,7 +848,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { true } - crate fn point_at_returns_when_relevant( + fn point_at_returns_when_relevant( &self, err: &mut DiagnosticBuilder<'tcx>, obligation: &PredicateObligation<'tcx>, @@ -753,220 +878,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - /// Given some node representing a fn-like thing in the HIR map, - /// returns a span and `ArgKind` information that describes the - /// arguments it expects. This can be supplied to - /// `report_arg_count_mismatch`. - pub fn get_fn_like_arguments(&self, node: Node<'_>) -> (Span, Vec) { - match node { - Node::Expr(&hir::Expr { - kind: hir::ExprKind::Closure(_, ref _decl, id, span, _), - .. - }) => ( - self.tcx.sess.source_map().def_span(span), - self.tcx - .hir() - .body(id) - .params - .iter() - .map(|arg| { - if let hir::Pat { kind: hir::PatKind::Tuple(ref args, _), span, .. } = - *arg.pat - { - ArgKind::Tuple( - Some(span), - args.iter() - .map(|pat| { - let snippet = self - .tcx - .sess - .source_map() - .span_to_snippet(pat.span) - .unwrap(); - (snippet, "_".to_owned()) - }) - .collect::>(), - ) - } else { - let name = - self.tcx.sess.source_map().span_to_snippet(arg.pat.span).unwrap(); - ArgKind::Arg(name, "_".to_owned()) - } - }) - .collect::>(), - ), - Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) - | Node::ImplItem(&hir::ImplItem { - span, - kind: hir::ImplItemKind::Method(ref sig, _), - .. - }) - | Node::TraitItem(&hir::TraitItem { - span, - kind: hir::TraitItemKind::Fn(ref sig, _), - .. - }) => ( - self.tcx.sess.source_map().def_span(span), - sig.decl - .inputs - .iter() - .map(|arg| match arg.clone().kind { - hir::TyKind::Tup(ref tys) => ArgKind::Tuple( - Some(arg.span), - vec![("_".to_owned(), "_".to_owned()); tys.len()], - ), - _ => ArgKind::empty(), - }) - .collect::>(), - ), - Node::Ctor(ref variant_data) => { - let span = variant_data - .ctor_hir_id() - .map(|hir_id| self.tcx.hir().span(hir_id)) - .unwrap_or(DUMMY_SP); - let span = self.tcx.sess.source_map().def_span(span); - - (span, vec![ArgKind::empty(); variant_data.fields().len()]) - } - _ => panic!("non-FnLike node found: {:?}", node), - } - } - - /// Reports an error when the number of arguments needed by a - /// trait match doesn't match the number that the expression - /// provides. - pub fn report_arg_count_mismatch( - &self, - span: Span, - found_span: Option, - expected_args: Vec, - found_args: Vec, - is_closure: bool, - ) -> DiagnosticBuilder<'tcx> { - let kind = if is_closure { "closure" } else { "function" }; - - let args_str = |arguments: &[ArgKind], other: &[ArgKind]| { - let arg_length = arguments.len(); - let distinct = match &other[..] { - &[ArgKind::Tuple(..)] => true, - _ => false, - }; - match (arg_length, arguments.get(0)) { - (1, Some(&ArgKind::Tuple(_, ref fields))) => { - format!("a single {}-tuple as argument", fields.len()) - } - _ => format!( - "{} {}argument{}", - arg_length, - if distinct && arg_length > 1 { "distinct " } else { "" }, - pluralize!(arg_length) - ), - } - }; - - let expected_str = args_str(&expected_args, &found_args); - let found_str = args_str(&found_args, &expected_args); - - let mut err = struct_span_err!( - self.tcx.sess, - span, - E0593, - "{} is expected to take {}, but it takes {}", - kind, - expected_str, - found_str, - ); - - err.span_label(span, format!("expected {} that takes {}", kind, expected_str)); - - if let Some(found_span) = found_span { - err.span_label(found_span, format!("takes {}", found_str)); - - // move |_| { ... } - // ^^^^^^^^-- def_span - // - // move |_| { ... } - // ^^^^^-- prefix - let prefix_span = self.tcx.sess.source_map().span_until_non_whitespace(found_span); - // move |_| { ... } - // ^^^-- pipe_span - let pipe_span = - if let Some(span) = found_span.trim_start(prefix_span) { span } else { found_span }; - - // Suggest to take and ignore the arguments with expected_args_length `_`s if - // found arguments is empty (assume the user just wants to ignore args in this case). - // For example, if `expected_args_length` is 2, suggest `|_, _|`. - if found_args.is_empty() && is_closure { - let underscores = vec!["_"; expected_args.len()].join(", "); - err.span_suggestion( - pipe_span, - &format!( - "consider changing the closure to take and ignore the expected argument{}", - if expected_args.len() < 2 { "" } else { "s" } - ), - format!("|{}|", underscores), - Applicability::MachineApplicable, - ); - } - - if let &[ArgKind::Tuple(_, ref fields)] = &found_args[..] { - if fields.len() == expected_args.len() { - let sugg = fields - .iter() - .map(|(name, _)| name.to_owned()) - .collect::>() - .join(", "); - err.span_suggestion( - found_span, - "change the closure to take multiple arguments instead of a single tuple", - format!("|{}|", sugg), - Applicability::MachineApplicable, - ); - } - } - if let &[ArgKind::Tuple(_, ref fields)] = &expected_args[..] { - if fields.len() == found_args.len() && is_closure { - let sugg = format!( - "|({}){}|", - found_args - .iter() - .map(|arg| match arg { - ArgKind::Arg(name, _) => name.to_owned(), - _ => "_".to_owned(), - }) - .collect::>() - .join(", "), - // add type annotations if available - if found_args.iter().any(|arg| match arg { - ArgKind::Arg(_, ty) => ty != "_", - _ => false, - }) { - format!( - ": ({})", - fields - .iter() - .map(|(_, ty)| ty.to_owned()) - .collect::>() - .join(", ") - ) - } else { - String::new() - }, - ); - err.span_suggestion( - found_span, - "change the closure to accept a tuple instead of individual arguments", - sugg, - Applicability::MachineApplicable, - ); - } - } - } - - err - } - - crate fn report_closure_arg_mismatch( + fn report_closure_arg_mismatch( &self, span: Span, found_span: Option, @@ -1022,10 +934,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err } -} -impl<'a, 'tcx> InferCtxt<'a, 'tcx> { - crate fn suggest_fully_qualified_path( + fn suggest_fully_qualified_path( &self, err: &mut DiagnosticBuilder<'_>, def_id: DefId, @@ -1091,7 +1001,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// ``` /// /// Returns `true` if an async-await specific note was added to the diagnostic. - crate fn maybe_note_obligation_cause_for_async_await( + fn maybe_note_obligation_cause_for_async_await( &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, @@ -1271,7 +1181,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Unconditionally adds the diagnostic note described in /// `maybe_note_obligation_cause_for_async_await`'s documentation comment. - crate fn note_obligation_cause_for_async_await( + fn note_obligation_cause_for_async_await( &self, err: &mut DiagnosticBuilder<'_>, target_span: Span, @@ -1423,7 +1333,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ); } - crate fn note_obligation_cause_code( + fn note_obligation_cause_code( &self, err: &mut DiagnosticBuilder<'_>, predicate: &T, @@ -1638,7 +1548,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } } - crate fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { + fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>) { let current_limit = self.tcx.sess.recursion_limit.get(); let suggested_limit = current_limit * 2; err.help(&format!( diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index ac9ff484a02..5def77ce732 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -4,9 +4,9 @@ use rustc::ty::{self, ToPolyTraitRef, Ty, TypeFoldable}; use rustc_data_structures::obligation_forest::ProcessResult; use rustc_data_structures::obligation_forest::{DoCompleted, Error, ForestObligation}; use rustc_data_structures::obligation_forest::{ObligationForest, ObligationProcessor}; +use rustc_infer::traits::{TraitEngine, TraitEngineExt as _}; use std::marker::PhantomData; -use super::engine::{TraitEngine, TraitEngineExt}; use super::project; use super::select::SelectionContext; use super::wf; @@ -17,6 +17,9 @@ use super::{ConstEvalFailure, Unimplemented}; use super::{FulfillmentError, FulfillmentErrorCode}; use super::{ObligationCause, PredicateObligation}; +use crate::traits::error_reporting::InferCtxtExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; + impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// Note that we include both the `ParamEnv` and the `Predicate`, /// as the `ParamEnv` can influence whether fulfillment succeeds diff --git a/src/librustc_trait_selection/traits/misc.rs b/src/librustc_trait_selection/traits/misc.rs index 7ab918c159e..d500cff67c6 100644 --- a/src/librustc_trait_selection/traits/misc.rs +++ b/src/librustc_trait_selection/traits/misc.rs @@ -1,10 +1,13 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. -use crate::infer::TyCtxtInferExt; +use crate::infer::InferCtxtExt as _; use crate::traits::{self, ObligationCause}; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; +use rustc_infer::infer::TyCtxtInferExt; + +use crate::traits::error_reporting::InferCtxtExt; #[derive(Clone)] pub enum CopyImplementationError<'tcx> { diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 9f7d019e8fd..7b93982db97 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -13,19 +13,18 @@ pub mod misc; mod object_safety; mod on_unimplemented; mod project; -mod projection_cache; pub mod query; mod select; mod specialize; -mod structural_impls; mod structural_match; mod util; pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use crate::traits::error_reporting::InferCtxtExt as _; +use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc::middle::region; -use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; @@ -43,7 +42,7 @@ pub use self::Vtable::*; pub use self::coherence::{add_placeholder_note, orphan_check, overlapping_impls}; pub use self::coherence::{OrphanCheckErr, OverlapResult}; -pub use self::engine::{TraitEngine, TraitEngineExt}; +pub use self::engine::TraitEngineExt; pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation}; pub use self::object_safety::astconv_object_safety_violations; pub use self::object_safety::is_vtable_safe_method; @@ -53,11 +52,6 @@ pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote}; pub use self::project::{ normalize, normalize_projection_type, normalize_to, poly_project_and_unify_type, }; -pub use self::projection_cache::MismatchedProjectionTypes; -pub use self::projection_cache::{ - Normalized, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey, ProjectionCacheSnapshot, - Reveal, -}; pub use self::select::{EvaluationCache, SelectionCache, SelectionContext}; pub use self::select::{EvaluationResult, IntercrateAmbiguityCause, OverflowError}; pub use self::specialize::find_associated_item; @@ -77,7 +71,7 @@ pub use self::util::{ supertrait_def_ids, supertraits, transitive_bounds, SupertraitDefIds, Supertraits, }; -pub use rustc::traits::*; +pub use rustc_infer::traits::*; /// Whether to skip the leak check, as part of a future compatibility warning step. #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -114,61 +108,6 @@ pub enum TraitQueryMode { Canonical, } -/// An `Obligation` represents some trait reference (e.g., `int: Eq`) for -/// which the vtable must be found. The process of finding a vtable is -/// called "resolving" the `Obligation`. This process consists of -/// either identifying an `impl` (e.g., `impl Eq for int`) that -/// provides the required vtable, or else finding a bound that is in -/// scope. The eventual result is usually a `Selection` (defined below). -#[derive(Clone, PartialEq, Eq, Hash)] -pub struct Obligation<'tcx, T> { - /// The reason we have to prove this thing. - pub cause: ObligationCause<'tcx>, - - /// The environment in which we should prove this thing. - pub param_env: ty::ParamEnv<'tcx>, - - /// The thing we are trying to prove. - pub predicate: T, - - /// If we started proving this as a result of trying to prove - /// something else, track the total depth to ensure termination. - /// If this goes over a certain threshold, we abort compilation -- - /// in such cases, we can not say whether or not the predicate - /// holds for certain. Stupid halting problem; such a drag. - pub recursion_depth: usize, -} - -pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>; -pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; - -// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. -#[cfg(target_arch = "x86_64")] -static_assert_size!(PredicateObligation<'_>, 112); - -pub type Obligations<'tcx, O> = Vec>; -pub type PredicateObligations<'tcx> = Vec>; -pub type TraitObligations<'tcx> = Vec>; - -pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>; - -pub struct FulfillmentError<'tcx> { - pub obligation: PredicateObligation<'tcx>, - pub code: FulfillmentErrorCode<'tcx>, - /// Diagnostics only: we opportunistically change the `code.span` when we encounter an - /// obligation error caused by a call argument. When this is the case, we also signal that in - /// this field to ensure accuracy of suggestions. - pub points_at_arg_span: bool, -} - -#[derive(Clone)] -pub enum FulfillmentErrorCode<'tcx> { - CodeSelectionError(SelectionError<'tcx>), - CodeProjectionError(MismatchedProjectionTypes<'tcx>), - CodeSubtypeError(ExpectedFound>, TypeError<'tcx>), // always comes from a SubtypePredicate - CodeAmbiguity, -} - /// Creates predicate obligations from the generic bounds. pub fn predicates_for_generics<'tcx>( cause: ObligationCause<'tcx>, @@ -581,58 +520,6 @@ fn vtable_methods<'tcx>( })) } -impl<'tcx, O> Obligation<'tcx, O> { - pub fn new( - cause: ObligationCause<'tcx>, - param_env: ty::ParamEnv<'tcx>, - predicate: O, - ) -> Obligation<'tcx, O> { - Obligation { cause, param_env, recursion_depth: 0, predicate } - } - - fn with_depth( - cause: ObligationCause<'tcx>, - recursion_depth: usize, - param_env: ty::ParamEnv<'tcx>, - predicate: O, - ) -> Obligation<'tcx, O> { - Obligation { cause, param_env, recursion_depth, predicate } - } - - pub fn misc( - span: Span, - body_id: hir::HirId, - param_env: ty::ParamEnv<'tcx>, - trait_ref: O, - ) -> Obligation<'tcx, O> { - Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref) - } - - pub fn with

(&self, value: P) -> Obligation<'tcx, P> { - Obligation { - cause: self.cause.clone(), - param_env: self.param_env, - recursion_depth: self.recursion_depth, - predicate: value, - } - } -} - -impl<'tcx> FulfillmentError<'tcx> { - fn new( - obligation: PredicateObligation<'tcx>, - code: FulfillmentErrorCode<'tcx>, - ) -> FulfillmentError<'tcx> { - FulfillmentError { obligation, code, points_at_arg_span: false } - } -} - -impl<'tcx> TraitObligation<'tcx> { - fn self_ty(&self) -> ty::Binder> { - self.predicate.map_bound(|p| p.self_ty()) - } -} - pub fn provide(providers: &mut ty::query::Providers<'_>) { object_safety::provide(providers); *providers = ty::query::Providers { diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index 6f20f5ac47e..d0d41f3ae32 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -11,6 +11,7 @@ use super::elaborate_predicates; use crate::infer::TyCtxtInferExt; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::{self, Obligation, ObligationCause}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, Predicate, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 551b8618af1..dde78aa4357 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -1,7 +1,6 @@ //! Code for projecting associated types out of trait references. use super::elaborate_predicates; -use super::projection_cache::NormalizedTy; use super::specialization_graph; use super::translate_substs; use super::util; @@ -12,11 +11,12 @@ use super::PredicateObligation; use super::Selection; use super::SelectionContext; use super::SelectionError; -use super::{Normalized, ProjectionCacheEntry, ProjectionCacheKey}; +use super::{Normalized, NormalizedTy, ProjectionCacheEntry, ProjectionCacheKey}; use super::{VtableClosureData, VtableFnPointerData, VtableGeneratorData, VtableImplData}; use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime}; +use crate::traits::error_reporting::InferCtxtExt; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; @@ -452,7 +452,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>( let infcx = selcx.infcx(); let projection_ty = infcx.resolve_vars_if_possible(&projection_ty); - let cache_key = ProjectionCacheKey { ty: projection_ty }; + let cache_key = ProjectionCacheKey::new(projection_ty); debug!( "opt_normalize_projection_type(\ @@ -1483,20 +1483,29 @@ fn assoc_ty_def( } } -impl<'cx, 'tcx> ProjectionCacheKey<'tcx> { - pub fn from_poly_projection_predicate( +crate trait ProjectionCacheKeyExt<'tcx>: Sized { + fn from_poly_projection_predicate( + selcx: &mut SelectionContext<'cx, 'tcx>, + predicate: &ty::PolyProjectionPredicate<'tcx>, + ) -> Option; +} + +impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> { + fn from_poly_projection_predicate( selcx: &mut SelectionContext<'cx, 'tcx>, predicate: &ty::PolyProjectionPredicate<'tcx>, ) -> Option { let infcx = selcx.infcx(); // We don't do cross-snapshot caching of obligations with escaping regions, // so there's no cache key to use - predicate.no_bound_vars().map(|predicate| ProjectionCacheKey { - // We don't attempt to match up with a specific type-variable state - // from a specific call to `opt_normalize_projection_type` - if - // there's no precise match, the original cache entry is "stranded" - // anyway. - ty: infcx.resolve_vars_if_possible(&predicate.projection_ty), + predicate.no_bound_vars().map(|predicate| { + ProjectionCacheKey::new( + // We don't attempt to match up with a specific type-variable state + // from a specific call to `opt_normalize_projection_type` - if + // there's no precise match, the original cache entry is "stranded" + // anyway. + infcx.resolve_vars_if_possible(&predicate.projection_ty), + ) }) } } diff --git a/src/librustc_trait_selection/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs index a1d7a2836e4..40a21b5a6ed 100644 --- a/src/librustc_trait_selection/traits/query/dropck_outlives.rs +++ b/src/librustc_trait_selection/traits/query/dropck_outlives.rs @@ -7,7 +7,11 @@ use rustc::ty::{self, Ty, TyCtxt}; pub use rustc::traits::query::{DropckOutlivesResult, DtorckConstraint}; -impl<'cx, 'tcx> At<'cx, 'tcx> { +pub trait AtExt<'tcx> { + fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>>; +} + +impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { /// Given a type `ty` of some value being dropped, computes a set /// of "kinds" (types, regions) that must be outlive the execution /// of the destructor. These basically correspond to data that the @@ -25,7 +29,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { /// /// [#1238]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md /// [#1327]: https://github.com/rust-lang/rfcs/blob/master/text/1327-dropck-param-eyepatch.md - pub fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>> { + fn dropck_outlives(&self, ty: Ty<'tcx>) -> InferOk<'tcx, Vec>> { debug!("dropck_outlives(ty={:?}, param_env={:?})", ty, self.param_env,); // Quick check: there are a number of cases that we know do not require diff --git a/src/librustc_trait_selection/traits/query/evaluate_obligation.rs b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs index b9ce3ccff27..0569f6217da 100644 --- a/src/librustc_trait_selection/traits/query/evaluate_obligation.rs +++ b/src/librustc_trait_selection/traits/query/evaluate_obligation.rs @@ -4,10 +4,35 @@ use crate::traits::{ EvaluationResult, OverflowError, PredicateObligation, SelectionContext, TraitQueryMode, }; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool; + + fn predicate_must_hold_considering_regions( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> bool; + + fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool; + + fn evaluate_obligation( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> Result; + + // Helper function that canonicalizes and runs the query. If an + // overflow results, we re-run it in the local context so we can + // report a nice error. + /*crate*/ + fn evaluate_obligation_no_overflow( + &self, + obligation: &PredicateObligation<'tcx>, + ) -> EvaluationResult; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Evaluates whether the predicate can be satisfied (by any means) /// in the given `ParamEnv`. - pub fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { + fn predicate_may_hold(&self, obligation: &PredicateObligation<'tcx>) -> bool { self.evaluate_obligation_no_overflow(obligation).may_apply() } @@ -17,7 +42,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// /// This version may conservatively fail when outlives obligations /// are required. - pub fn predicate_must_hold_considering_regions( + fn predicate_must_hold_considering_regions( &self, obligation: &PredicateObligation<'tcx>, ) -> bool { @@ -29,15 +54,12 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// not entirely accurate if inference variables are involved. /// /// This version ignores all outlives constraints. - pub fn predicate_must_hold_modulo_regions( - &self, - obligation: &PredicateObligation<'tcx>, - ) -> bool { + fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'tcx>) -> bool { self.evaluate_obligation_no_overflow(obligation).must_apply_modulo_regions() } /// Evaluate a given predicate, capturing overflow and propagating it back. - pub fn evaluate_obligation( + fn evaluate_obligation( &self, obligation: &PredicateObligation<'tcx>, ) -> Result { @@ -53,7 +75,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { // Helper function that canonicalizes and runs the query. If an // overflow results, we re-run it in the local context so we can // report a nice error. - crate fn evaluate_obligation_no_overflow( + fn evaluate_obligation_no_overflow( &self, obligation: &PredicateObligation<'tcx>, ) -> EvaluationResult { diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index 365bf9e295b..adec2ddb253 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -5,17 +5,24 @@ use crate::infer::at::At; use crate::infer::canonical::OriginalQueryValues; use crate::infer::{InferCtxt, InferOk}; -use crate::traits::Normalized; +use crate::traits::error_reporting::InferCtxtExt; use crate::traits::{Obligation, ObligationCause, PredicateObligation, Reveal}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; +use rustc_infer::traits::Normalized; use super::NoSolution; pub use rustc::traits::query::NormalizationResult; -impl<'cx, 'tcx> At<'cx, 'tcx> { +pub trait AtExt<'tcx> { + fn normalize(&self, value: &T) -> Result, NoSolution> + where + T: TypeFoldable<'tcx>; +} + +impl<'cx, 'tcx> AtExt<'tcx> for At<'cx, 'tcx> { /// Normalize `value` in the context of the inference context, /// yielding a resulting type, or an error if `value` cannot be /// normalized. If you don't care about regions, you should prefer @@ -29,7 +36,7 @@ impl<'cx, 'tcx> At<'cx, 'tcx> { /// normalizing, but for now should be used only when we actually /// know that normalization will succeed, since error reporting /// and other details are still "under development". - pub fn normalize(&self, value: &T) -> Result, NoSolution> + fn normalize(&self, value: &T) -> Result, NoSolution> where T: TypeFoldable<'tcx>, { diff --git a/src/librustc_trait_selection/traits/query/outlives_bounds.rs b/src/librustc_trait_selection/traits/query/outlives_bounds.rs index 9ce17bcec27..05c96dd520a 100644 --- a/src/librustc_trait_selection/traits/query/outlives_bounds.rs +++ b/src/librustc_trait_selection/traits/query/outlives_bounds.rs @@ -1,14 +1,25 @@ use crate::infer::canonical::OriginalQueryValues; use crate::infer::InferCtxt; use crate::traits::query::NoSolution; -use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine, TraitEngineExt}; +use crate::traits::{FulfillmentContext, ObligationCause, TraitEngine}; use rustc::ty::{self, Ty}; use rustc_hir as hir; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::Span; pub use rustc::traits::query::OutlivesBound; -impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { +pub trait InferCtxtExt<'tcx> { + fn implied_outlives_bounds( + &self, + param_env: ty::ParamEnv<'tcx>, + body_id: hir::HirId, + ty: Ty<'tcx>, + span: Span, + ) -> Vec>; +} + +impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> { /// Implied bounds are region relationships that we deduce /// automatically. The idea is that (e.g.) a caller must check that a /// function's argument types are well-formed immediately before @@ -30,7 +41,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { /// - `ty`, the type that we are supposed to assume is WF. /// - `span`, a span to use when normalizing, hopefully not important, /// might be useful if a `bug!` occurs. - pub fn implied_outlives_bounds( + fn implied_outlives_bounds( &self, param_env: ty::ParamEnv<'tcx>, body_id: hir::HirId, diff --git a/src/librustc_trait_selection/traits/query/type_op/custom.rs b/src/librustc_trait_selection/traits/query/type_op/custom.rs index c1c9030b888..915e8ae4a7a 100644 --- a/src/librustc_trait_selection/traits/query/type_op/custom.rs +++ b/src/librustc_trait_selection/traits/query/type_op/custom.rs @@ -4,7 +4,9 @@ use std::fmt; use crate::infer::canonical::query_response; use crate::infer::canonical::QueryRegionConstraints; -use crate::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use crate::traits::engine::TraitEngineExt as _; +use crate::traits::{ObligationCause, TraitEngine}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; use std::rc::Rc; diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index 12f39b12c72..ab3214d8d2d 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -33,6 +33,8 @@ use super::{ }; use crate::infer::{CombinedSnapshot, InferCtxt, InferOk, PlaceholderMap, TypeFreshener}; +use crate::traits::error_reporting::InferCtxtExt; +use crate::traits::project::ProjectionCacheKeyExt; use rustc::dep_graph::{DepKind, DepNodeIndex}; use rustc::middle::lang_items; use rustc::ty::fast_reject; @@ -3464,9 +3466,16 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } } -impl<'tcx> TraitObligation<'tcx> { +trait TraitObligationExt<'tcx> { + fn derived_cause( + &self, + variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, + ) -> ObligationCause<'tcx>; +} + +impl<'tcx> TraitObligationExt<'tcx> for TraitObligation<'tcx> { #[allow(unused_comparisons)] - pub fn derived_cause( + fn derived_cause( &self, variant: fn(DerivedObligationCause<'tcx>) -> ObligationCauseCode<'tcx>, ) -> ObligationCause<'tcx> { diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index 980a3f04781..b69c5bdce2a 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -1,5 +1,5 @@ -use crate::infer::opaque_types::required_region_bounds; use crate::infer::InferCtxt; +use crate::opaque_types::required_region_bounds; use crate::traits::{self, AssocTypeBoundData}; use rustc::middle::lang_items; use rustc::ty::subst::SubstsRef; From 1fcdc52f707015195b0706ea86ddbe2f749019de Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 11 Feb 2020 21:19:40 +0100 Subject: [PATCH 1102/1250] Make downstream crates compile. --- src/librustc_interface/passes.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- .../diagnostics/conflict_errors.rs | 2 +- .../borrow_check/region_infer/opaque_types.rs | 1 + .../type_check/free_region_relations.rs | 2 +- .../borrow_check/type_check/liveness/trace.rs | 6 +++--- .../borrow_check/type_check/mod.rs | 12 +++++++----- .../borrow_check/type_check/relate_tys.rs | 4 ++-- .../transform/check_consts/validation.rs | 3 ++- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir_build/hair/cx/mod.rs | 1 + .../hair/pattern/const_to_pat.rs | 5 +++-- src/librustc_passes/stability.rs | 2 +- src/librustc_traits/dropck_outlives.rs | 14 ++++++++++---- src/librustc_traits/evaluate_obligation.rs | 6 +++--- src/librustc_traits/implied_outlives_bounds.rs | 12 +++++++----- .../normalize_erasing_regions.rs | 3 ++- src/librustc_traits/normalize_projection_ty.rs | 8 +++++--- src/librustc_traits/type_op.rs | 18 +++++++++++------- src/librustc_ty/common_traits.rs | 2 +- src/librustc_ty/instance.rs | 2 +- src/librustc_ty/ty.rs | 2 +- src/librustc_typeck/astconv.rs | 8 ++++---- src/librustc_typeck/check/_match.rs | 4 ++-- src/librustc_typeck/check/autoderef.rs | 3 ++- src/librustc_typeck/check/cast.rs | 4 ++-- src/librustc_typeck/check/closure.rs | 5 +++-- src/librustc_typeck/check/coercion.rs | 3 ++- src/librustc_typeck/check/compare_method.rs | 3 ++- src/librustc_typeck/check/demand.rs | 4 +++- src/librustc_typeck/check/dropck.rs | 5 ++++- src/librustc_typeck/check/expr.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 3 ++- src/librustc_typeck/check/method/probe.rs | 11 +++++++---- src/librustc_typeck/check/method/suggest.rs | 3 ++- src/librustc_typeck/check/mod.rs | 11 ++++++++--- src/librustc_typeck/check/op.rs | 1 + src/librustc_typeck/check/pat.rs | 2 +- src/librustc_typeck/check/regionck.rs | 2 ++ src/librustc_typeck/check/wfcheck.rs | 5 +++-- src/librustc_typeck/check/writeback.rs | 1 + src/librustc_typeck/coherence/builtin.rs | 7 ++++--- .../coherence/inherent_impls_overlap.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/collect/type_of.rs | 2 +- src/librustc_typeck/lib.rs | 6 +++++- src/librustc_typeck/mem_categorization.rs | 1 + src/librustdoc/clean/auto_trait.rs | 2 +- src/librustdoc/clean/blanket_impl.rs | 1 + src/librustdoc/lib.rs | 1 + 52 files changed, 136 insertions(+), 83 deletions(-) diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 29e9ea1833f..bffbcd33669 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -27,7 +27,6 @@ use rustc_errors::PResult; use rustc_expand::base::ExtCtxt; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::Crate; -use rustc_infer::traits; use rustc_lint::LintStore; use rustc_mir as mir; use rustc_mir_build as mir_build; @@ -37,6 +36,7 @@ use rustc_plugin_impl as plugin; use rustc_resolve::{Resolver, ResolverArenas}; use rustc_span::symbol::Symbol; use rustc_span::FileName; +use rustc_trait_selection::traits; use rustc_typeck as typeck; use rustc_serialize::json; diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 249c9af3d48..50c2c6f9552 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -39,12 +39,12 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{GenericParamKind, PatKind}; use rustc_hir::{HirIdSet, Node}; -use rustc_infer::traits::misc::can_type_implement_copy; use rustc_session::lint::FutureIncompatibleInfo; use rustc_span::edition::Edition; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{BytePos, Span}; +use rustc_trait_selection::traits::misc::can_type_implement_copy; use crate::nonstandard_style::{method_context, MethodLateContext}; diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs index 8d4afd2c3b3..e895eec5d52 100644 --- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs @@ -10,9 +10,9 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; use rustc_index::vec::Idx; -use rustc_infer::traits::error_reporting::suggest_constraining_type_param; use rustc_span::source_map::DesugaringKind; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::suggest_constraining_type_param; use crate::dataflow::drop_flag_effects; use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex}; diff --git a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs index 15bbc5677da..49b49437328 100644 --- a/src/librustc_mir/borrow_check/region_infer/opaque_types.rs +++ b/src/librustc_mir/borrow_check/region_infer/opaque_types.rs @@ -3,6 +3,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_span::Span; +use rustc_trait_selection::opaque_types::InferCtxtExt; use super::RegionInferenceContext; diff --git a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs index 283d78062f3..c17db926946 100644 --- a/src/librustc_mir/borrow_check/type_check/free_region_relations.rs +++ b/src/librustc_mir/borrow_check/type_check/free_region_relations.rs @@ -7,8 +7,8 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives; use rustc_infer::infer::region_constraints::GenericKind; use rustc_infer::infer::InferCtxt; -use rustc_infer::traits::query::type_op::{self, TypeOp}; use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::query::type_op::{self, TypeOp}; use std::rc::Rc; use crate::borrow_check::{ diff --git a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs index baa9d1d212e..0c49ee44f9a 100644 --- a/src/librustc_mir/borrow_check/type_check/liveness/trace.rs +++ b/src/librustc_mir/borrow_check/type_check/liveness/trace.rs @@ -3,9 +3,9 @@ use rustc::ty::{Ty, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::bit_set::HybridBitSet; use rustc_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::traits::query::dropck_outlives::DropckOutlivesResult; -use rustc_infer::traits::query::type_op::outlives::DropckOutlives; -use rustc_infer::traits::query::type_op::TypeOp; +use rustc_trait_selection::traits::query::dropck_outlives::DropckOutlivesResult; +use rustc_trait_selection::traits::query::type_op::outlives::DropckOutlives; +use rustc_trait_selection::traits::query::type_op::TypeOp; use std::rc::Rc; use crate::dataflow::generic::ResultsCursor; diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index ace92949814..351b30bab61 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -24,17 +24,19 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; -use rustc_infer::infer::opaque_types::GenerateMemberConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{ InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionVariableOrigin, }; -use rustc_infer::traits::query::type_op; -use rustc_infer::traits::query::type_op::custom::CustomTypeOp; -use rustc_infer::traits::query::{Fallible, NoSolution}; -use rustc_infer::traits::{self, ObligationCause, PredicateObligations}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::opaque_types::{GenerateMemberConstraints, InferCtxtExt}; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::query::type_op; +use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; +use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligations}; use crate::dataflow::generic::ResultsCursor; use crate::dataflow::move_paths::MoveData; diff --git a/src/librustc_mir/borrow_check/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/type_check/relate_tys.rs index b0f048ff1a6..ebaafd40262 100644 --- a/src/librustc_mir/borrow_check/type_check/relate_tys.rs +++ b/src/librustc_mir/borrow_check/type_check/relate_tys.rs @@ -3,8 +3,8 @@ use rustc::ty::relate::TypeRelation; use rustc::ty::{self, Ty}; use rustc_infer::infer::nll_relate::{NormalizationStrategy, TypeRelating, TypeRelatingDelegate}; use rustc_infer::infer::{InferCtxt, NLLRegionVariableOrigin}; -use rustc_infer::traits::query::Fallible; -use rustc_infer::traits::DomainGoal; +use rustc_trait_selection::traits::query::Fallible; +use rustc_trait_selection::traits::DomainGoal; use crate::borrow_check::constraints::OutlivesConstraint; use crate::borrow_check::type_check::{BorrowCheckContext, Locations}; diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index 133772407c5..adffd444eb6 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -9,9 +9,10 @@ use rustc_errors::struct_span_err; use rustc_hir::{def_id::DefId, HirId}; use rustc_index::bit_set::BitSet; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{self, TraitEngine}; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, TraitEngine}; use std::borrow::Cow; use std::ops::Deref; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index f9682a77173..289b198d2c9 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -25,8 +25,8 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::HirId; use rustc_index::vec::IndexVec; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; use crate::const_eval::error_to_const_error; use crate::interpret::{ diff --git a/src/librustc_mir_build/hair/cx/mod.rs b/src/librustc_mir_build/hair/cx/mod.rs index 449e2e74946..99caa6a0f95 100644 --- a/src/librustc_mir_build/hair/cx/mod.rs +++ b/src/librustc_mir_build/hair/cx/mod.rs @@ -19,6 +19,7 @@ use rustc_hir::Node; use rustc_index::vec::Idx; use rustc_infer::infer::InferCtxt; use rustc_span::symbol::{sym, Symbol}; +use rustc_trait_selection::infer::InferCtxtExt; #[derive(Clone)] crate struct Cx<'a, 'tcx> { diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 27d1bce76ed..214e75fbdde 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -3,8 +3,9 @@ use rustc::mir::Field; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::predicate_for_trait_def; -use rustc_infer::traits::{self, ObligationCause, PredicateObligation}; +use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; use rustc_index::vec::Idx; diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 7ea9ab5335d..d056d9f0562 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -18,9 +18,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Generics, HirId, Item, StructField, Variant}; -use rustc_infer::traits::misc::can_type_implement_copy; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; +use rustc_trait_selection::traits::misc::can_type_implement_copy; use std::cmp::Ordering; use std::mem::replace; diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 2f854c045e5..b13a7a3acb1 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -5,11 +5,17 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::dropck_outlives::trivial_dropck_outlives; -use rustc_infer::traits::query::dropck_outlives::{DropckOutlivesResult, DtorckConstraint}; -use rustc_infer::traits::query::{CanonicalTyGoal, NoSolution}; -use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::{Span, DUMMY_SP}; +use rustc_trait_selection::traits::query::dropck_outlives::trivial_dropck_outlives; +use rustc_trait_selection::traits::query::dropck_outlives::{ + DropckOutlivesResult, DtorckConstraint, +}; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::query::{CanonicalTyGoal, NoSolution}; +use rustc_trait_selection::traits::{ + Normalized, ObligationCause, TraitEngine, TraitEngineExt as _, +}; crate fn provide(p: &mut Providers<'_>) { *p = Providers { dropck_outlives, adt_dtorck_constraint, ..*p }; diff --git a/src/librustc_traits/evaluate_obligation.rs b/src/librustc_traits/evaluate_obligation.rs index 4cf5b66b3cb..87895d8e384 100644 --- a/src/librustc_traits/evaluate_obligation.rs +++ b/src/librustc_traits/evaluate_obligation.rs @@ -1,11 +1,11 @@ use rustc::ty::query::Providers; use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::CanonicalPredicateGoal; -use rustc_infer::traits::{ +use rustc_span::source_map::DUMMY_SP; +use rustc_trait_selection::traits::query::CanonicalPredicateGoal; +use rustc_trait_selection::traits::{ EvaluationResult, Obligation, ObligationCause, OverflowError, SelectionContext, TraitQueryMode, }; -use rustc_span::source_map::DUMMY_SP; crate fn provide(p: &mut Providers<'_>) { *p = Providers { evaluate_obligation, ..*p }; diff --git a/src/librustc_traits/implied_outlives_bounds.rs b/src/librustc_traits/implied_outlives_bounds.rs index 1b6b8735651..4505a1e59d9 100644 --- a/src/librustc_traits/implied_outlives_bounds.rs +++ b/src/librustc_traits/implied_outlives_bounds.rs @@ -7,12 +7,14 @@ use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; use rustc_infer::infer::canonical::{self, Canonical}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::query::outlives_bounds::OutlivesBound; -use rustc_infer::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; -use rustc_infer::traits::wf; -use rustc_infer::traits::FulfillmentContext; -use rustc_infer::traits::{TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::source_map::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::traits::query::outlives_bounds::OutlivesBound; +use rustc_trait_selection::traits::query::{CanonicalTyGoal, Fallible, NoSolution}; +use rustc_trait_selection::traits::wf; +use rustc_trait_selection::traits::FulfillmentContext; +use rustc_trait_selection::traits::TraitEngine; use smallvec::{smallvec, SmallVec}; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/normalize_erasing_regions.rs b/src/librustc_traits/normalize_erasing_regions.rs index 4e5f20d80b0..c2fb237a05b 100644 --- a/src/librustc_traits/normalize_erasing_regions.rs +++ b/src/librustc_traits/normalize_erasing_regions.rs @@ -2,7 +2,8 @@ use rustc::traits::query::NoSolution; use rustc::ty::query::Providers; use rustc::ty::{self, ParamEnvAnd, Ty, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{Normalized, ObligationCause}; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::{Normalized, ObligationCause}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/normalize_projection_ty.rs b/src/librustc_traits/normalize_projection_ty.rs index b5678956347..57abff769de 100644 --- a/src/librustc_traits/normalize_projection_ty.rs +++ b/src/librustc_traits/normalize_projection_ty.rs @@ -3,11 +3,13 @@ use rustc::ty::{ParamEnvAnd, TyCtxt}; use rustc_hir as hir; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::query::{ +use rustc_infer::traits::TraitEngineExt as _; +use rustc_span::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::traits::query::{ normalize::NormalizationResult, CanonicalProjectionGoal, NoSolution, }; -use rustc_infer::traits::{self, ObligationCause, SelectionContext, TraitEngineExt}; -use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits::{self, ObligationCause, SelectionContext}; use std::sync::atomic::Ordering; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_traits/type_op.rs b/src/librustc_traits/type_op.rs index 41181338061..e174c040e0d 100644 --- a/src/librustc_traits/type_op.rs +++ b/src/librustc_traits/type_op.rs @@ -8,14 +8,18 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::at::ToTrace; use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; -use rustc_infer::traits::query::type_op::ascribe_user_type::AscribeUserType; -use rustc_infer::traits::query::type_op::eq::Eq; -use rustc_infer::traits::query::type_op::normalize::Normalize; -use rustc_infer::traits::query::type_op::prove_predicate::ProvePredicate; -use rustc_infer::traits::query::type_op::subtype::Subtype; -use rustc_infer::traits::query::{Fallible, NoSolution}; -use rustc_infer::traits::{Normalized, Obligation, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::DUMMY_SP; +use rustc_trait_selection::infer::InferCtxtBuilderExt; +use rustc_trait_selection::infer::InferCtxtExt; +use rustc_trait_selection::traits::query::normalize::AtExt; +use rustc_trait_selection::traits::query::type_op::ascribe_user_type::AscribeUserType; +use rustc_trait_selection::traits::query::type_op::eq::Eq; +use rustc_trait_selection::traits::query::type_op::normalize::Normalize; +use rustc_trait_selection::traits::query::type_op::prove_predicate::ProvePredicate; +use rustc_trait_selection::traits::query::type_op::subtype::Subtype; +use rustc_trait_selection::traits::query::{Fallible, NoSolution}; +use rustc_trait_selection::traits::{Normalized, Obligation, ObligationCause, TraitEngine}; use std::fmt; crate fn provide(p: &mut Providers<'_>) { diff --git a/src/librustc_ty/common_traits.rs b/src/librustc_ty/common_traits.rs index e0ce6ad23a6..311ba383f30 100644 --- a/src/librustc_ty/common_traits.rs +++ b/src/librustc_ty/common_traits.rs @@ -3,8 +3,8 @@ use rustc::middle::lang_items; use rustc::ty::{self, Ty, TyCtxt}; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits; use rustc_span::DUMMY_SP; +use rustc_trait_selection::traits; fn is_copy_raw<'tcx>(tcx: TyCtxt<'tcx>, query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>) -> bool { is_item_raw(tcx, query, lang_items::CopyTraitLangItem) diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 8b1ba57e819..10cc2c0e303 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -1,8 +1,8 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt, TypeFoldable}; use rustc_hir::def_id::DefId; -use rustc_infer::traits; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits; use log::debug; diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 5a87cf4c10d..4c0903b6b9d 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -5,9 +5,9 @@ use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_infer::traits; use rustc_span::symbol::Symbol; use rustc_span::Span; +use rustc_trait_selection::traits; fn sized_constraint_for_ty<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 36461f2400c..be8090cf21b 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -26,13 +26,13 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::print; use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; -use rustc_infer::traits; -use rustc_infer::traits::astconv_object_safety_violations; -use rustc_infer::traits::error_reporting::report_object_safety_error; -use rustc_infer::traits::wf::object_region_bounds; use rustc_span::symbol::sym; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::astconv_object_safety_violations; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; +use rustc_trait_selection::traits::wf::object_region_bounds; use smallvec::SmallVec; use std::collections::BTreeSet; diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 2c71fec6809..20737b44e7c 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -4,9 +4,9 @@ use rustc::ty::Ty; use rustc_hir as hir; use rustc_hir::ExprKind; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::ObligationCauseCode; -use rustc_infer::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; use rustc_span::Span; +use rustc_trait_selection::traits::ObligationCauseCode; +use rustc_trait_selection::traits::{IfExpressionCause, MatchExpressionArmCause, ObligationCause}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub fn check_match( diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 67bfb090253..991347714e8 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -8,7 +8,8 @@ use rustc::ty::{ToPredicate, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::{InferCtxt, InferOk}; -use rustc_infer::traits::{self, TraitEngine}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, TraitEngine}; use rustc_ast::ast::Ident; use rustc_span::Span; diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index ff100c261f1..d52b6c39ab5 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -44,9 +44,9 @@ use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_ast::ast; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_infer::traits; -use rustc_infer::traits::error_reporting::report_object_safety_error; use rustc_span::Span; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::error_reporting::report_object_safety_error; /// Reifies a cast check to be checked once we have full type information for /// a function context. diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 8689db1b1eb..49b7a997311 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -12,10 +12,11 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; -use rustc_infer::traits::error_reporting::ArgKind; -use rustc_infer::traits::Obligation; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::ArgKind; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::Obligation; use std::cmp; use std::iter; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index 022b2e82964..d74623a063f 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -66,10 +66,11 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use smallvec::{smallvec, SmallVec}; use std::ops::Deref; diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 0c8dec8f8d4..ff79d10273c 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -10,8 +10,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit; use rustc_hir::{GenericParamKind, ImplItemKind, TraitItemKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode, Reveal}; use super::{potentially_plural_count, FnCtxt, Inherited}; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 6df9d054195..0556c80e4f7 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -1,6 +1,8 @@ use crate::check::FnCtxt; use rustc_infer::infer::InferOk; -use rustc_infer::traits::{self, ObligationCause}; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{self, ObligationCause}; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::{self, AssocItem, Ty}; diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index ead7536f8c6..dca4f9e7cbe 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -10,8 +10,11 @@ use rustc::ty::{self, Predicate, Ty, TyCtxt}; use rustc_errors::struct_span_err; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt}; -use rustc_infer::traits::{ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::Span; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::query::dropck_outlives::AtExt; +use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt}; /// This function confirms that the `Drop` implementation identified by /// `drop_impl_did` is not any more specialized than the type it is diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 859a219c95a..93f9050b26e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -34,10 +34,10 @@ use rustc_hir::def_id::DefId; use rustc_hir::{ExprKind, QPath}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::{self, ObligationCauseCode}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_trait_selection::traits::{self, ObligationCauseCode}; use std::fmt::Display; diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 108affe5a86..48c72567b5c 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -11,8 +11,8 @@ use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, GenericParamDefKind, Ty}; use rustc_hir as hir; use rustc_infer::infer::{self, InferOk}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; use std::ops::Deref; diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index 189b05a819b..3cf7b65e30f 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -22,8 +22,9 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_infer::infer::{self, InferOk}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use self::probe::{IsSuggestion, ProbeScope}; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index d35761a6a21..16bab09feee 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -28,11 +28,14 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; -use rustc_infer::traits::query::method_autoderef::MethodAutoderefBadTy; -use rustc_infer::traits::query::method_autoderef::{CandidateStep, MethodAutoderefStepsResult}; -use rustc_infer::traits::query::CanonicalTyGoal; -use rustc_infer::traits::{self, ObligationCause}; use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; +use rustc_trait_selection::traits::query::method_autoderef::{ + CandidateStep, MethodAutoderefStepsResult, +}; +use rustc_trait_selection::traits::query::CanonicalTyGoal; +use rustc_trait_selection::traits::{self, ObligationCause}; use std::cmp::max; use std::iter; use std::mem; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 654ec372ded..bfbad1a0ea9 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -17,9 +17,10 @@ use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::Obligation; use rustc_span::symbol::kw; use rustc_span::{source_map, FileName, Span}; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::Obligation; use std::cmp::Ordering; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index f1f505e1859..1975b248999 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -121,17 +121,22 @@ use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, Q use rustc_index::vec::Idx; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; -use rustc_infer::infer::opaque_types::OpaqueTypeDecl; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt}; -use rustc_infer::traits::error_reporting::recursive_type_with_infinite_size_error; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode, TraitEngine}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::{self, BytePos, MultiSpan, Span}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::infer::InferCtxtExt as _; +use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl}; +use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; +use rustc_trait_selection::traits::{ + self, ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt, +}; use std::cell::{Cell, Ref, RefCell, RefMut}; use std::cmp; diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs index f7bbde35aa7..f589805e1e2 100644 --- a/src/librustc_typeck/check/op.rs +++ b/src/librustc_typeck/check/op.rs @@ -10,6 +10,7 @@ use rustc_errors::{self, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_span::Span; +use rustc_trait_selection::infer::InferCtxtExt; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Checks a `a = b` diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 70b39a62cd7..60132dde9ca 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -11,9 +11,9 @@ use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{HirId, Pat, PatKind}; use rustc_infer::infer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; -use rustc_infer::traits::{ObligationCause, Pattern}; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{Span, Spanned}; +use rustc_trait_selection::traits::{ObligationCause, Pattern}; use std::cmp; use std::collections::hash_map::Entry::{Occupied, Vacant}; diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index c0e33637fd0..bfa3d75b6b0 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -87,6 +87,8 @@ use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors}; use rustc_span::Span; +use rustc_trait_selection::infer::OutlivesEnvironmentExt; +use rustc_trait_selection::opaque_types::InferCtxtExt; use std::mem; use std::ops::Deref; diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 335b4a28501..026e68e10e0 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -12,10 +12,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; -use rustc_infer::infer::opaque_types::may_define_opaque_type; -use rustc_infer::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::opaque_types::may_define_opaque_type; +use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; +use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; use rustc_hir as hir; use rustc_hir::itemlikevisit::ParItemLikeVisitor; diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 380e256c9fc..f4c166b943d 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -16,6 +16,7 @@ use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; use rustc_span::symbol::sym; use rustc_span::Span; +use rustc_trait_selection::opaque_types::InferCtxtExt; use std::mem; diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 7d7d34e45a6..2ea7601ae65 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -13,9 +13,10 @@ use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt}; -use rustc_infer::traits::misc::{can_type_implement_copy, CopyImplementationError}; -use rustc_infer::traits::predicate_for_trait_def; -use rustc_infer::traits::{self, ObligationCause, TraitEngine}; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt; +use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; +use rustc_trait_selection::traits::predicate_for_trait_def; +use rustc_trait_selection::traits::{self, ObligationCause, TraitEngine, TraitEngineExt}; pub fn check_trait(tcx: TyCtxt<'_>, trait_def_id: DefId) { let lang_items = tcx.lang_items(); diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 778eee3586b..1eae9d3b7fa 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -3,7 +3,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_infer::traits::{self, SkipLeakCheck}; +use rustc_trait_selection::traits::{self, SkipLeakCheck}; pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) { assert_eq!(crate_num, LOCAL_CRATE); diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index d24ee5f156b..0d0149f9673 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -9,8 +9,8 @@ use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_errors::struct_span_err; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_infer::traits; use rustc_span::Span; +use rustc_trait_selection::traits; mod builtin; mod inherent_impls; diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index 0a574493573..fc77aad8688 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -6,7 +6,7 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits; +use rustc_trait_selection::traits; pub fn check(tcx: TyCtxt<'_>) { let mut orphan = OrphanChecker { tcx }; diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 815235adc71..43cf65d8151 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -11,9 +11,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_infer::traits; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::traits; use super::ItemCtxt; use super::{bad_placeholder_type, is_suggestable_infer_ty}; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index c5f339d6b76..4e7985dd988 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -101,9 +101,13 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; -use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::TraitEngineExt as _; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; +use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; +use rustc_trait_selection::traits::{ + ObligationCause, ObligationCauseCode, TraitEngine, TraitEngineExt as _, +}; use std::iter; diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 8e06948a109..4350b3dda97 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -59,6 +59,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::PatKind; use rustc_infer::infer::InferCtxt; use rustc_span::Span; +use rustc_trait_selection::infer::InferCtxtExt; #[derive(Clone, Debug)] pub enum PlaceBase { diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 407b50382fa..c85b21a5500 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -1,7 +1,7 @@ use rustc::ty::{self, Region, RegionVid, TypeFoldable}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; -use rustc_infer::traits::auto_trait::{self, AutoTraitResult}; +use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult}; use std::fmt::Debug; diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 4a1e2570d06..e66f8697717 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -1,3 +1,4 @@ +use crate::rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc::ty::subst::Subst; use rustc::ty::{ToPredicate, WithConstness}; use rustc_hir as hir; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 4ea14ab9077..2e90d6082ba 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -38,6 +38,7 @@ extern crate rustc_resolve; extern crate rustc_session; extern crate rustc_span as rustc_span; extern crate rustc_target; +extern crate rustc_trait_selection; extern crate rustc_typeck; extern crate test as testing; #[macro_use] From 0144a979464744261d1d9b74234a4376a084e9b2 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Tue, 11 Feb 2020 22:39:02 +0100 Subject: [PATCH 1103/1250] Trim dependencies and features. --- Cargo.lock | 7 ------- src/librustc_infer/Cargo.toml | 4 ---- src/librustc_infer/lib.rs | 6 ++---- src/librustc_resolve/Cargo.toml | 1 - src/librustc_trait_selection/Cargo.toml | 2 -- src/librustc_trait_selection/lib.rs | 11 ++--------- 6 files changed, 4 insertions(+), 27 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f453705db9e..303d5ba7eb8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3774,19 +3774,15 @@ dependencies = [ name = "rustc_infer" version = "0.0.0" dependencies = [ - "fmt_macros", "graphviz", "log", "rustc", "rustc_ast", - "rustc_attr", "rustc_data_structures", - "rustc_error_codes", "rustc_errors", "rustc_hir", "rustc_index", "rustc_macros", - "rustc_session", "rustc_span", "rustc_target", "smallvec 1.0.0", @@ -4044,7 +4040,6 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_hir", - "rustc_infer", "rustc_metadata", "rustc_session", "rustc_span", @@ -4129,13 +4124,11 @@ name = "rustc_trait_selection" version = "0.0.0" dependencies = [ "fmt_macros", - "graphviz", "log", "rustc", "rustc_ast", "rustc_attr", "rustc_data_structures", - "rustc_error_codes", "rustc_errors", "rustc_hir", "rustc_index", diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml index de99214901d..4f97fd82874 100644 --- a/src/librustc_infer/Cargo.toml +++ b/src/librustc_infer/Cargo.toml @@ -10,18 +10,14 @@ path = "lib.rs" doctest = false [dependencies] -fmt_macros = { path = "../libfmt_macros" } graphviz = { path = "../libgraphviz" } log = { version = "0.4", features = ["release_max_level_info", "std"] } -rustc_attr = { path = "../librustc_attr" } rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_macros = { path = "../librustc_macros" } -rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } rustc_target = { path = "../librustc_target" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs index 49e99b574b8..cb8ae8c592b 100644 --- a/src/librustc_infer/lib.rs +++ b/src/librustc_infer/lib.rs @@ -1,6 +1,5 @@ -//! This crates defines the trait resolution method and the type inference engine. +//! This crates defines the type inference engine. //! -//! - **Traits.** Trait resolution is implemented in the `traits` module. //! - **Type inference.** The type inference code can be found in the `infer` module; //! this code handles low-level equality and subtyping operations. The //! type check pass in the compiler is found in the `librustc_typeck` crate. @@ -17,12 +16,11 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] -#![feature(drain_filter)] #![feature(never_type)] #![feature(range_is_empty)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![recursion_limit = "512"] +#![recursion_limit = "512"] // For rustdoc #[macro_use] extern crate rustc_macros; diff --git a/src/librustc_resolve/Cargo.toml b/src/librustc_resolve/Cargo.toml index 11a3cedcc74..49f079ad270 100644 --- a/src/librustc_resolve/Cargo.toml +++ b/src/librustc_resolve/Cargo.toml @@ -24,7 +24,6 @@ rustc_errors = { path = "../librustc_errors" } rustc_expand = { path = "../librustc_expand" } rustc_feature = { path = "../librustc_feature" } rustc_hir = { path = "../librustc_hir" } -rustc_infer = { path = "../librustc_infer" } rustc_metadata = { path = "../librustc_metadata" } rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_trait_selection/Cargo.toml b/src/librustc_trait_selection/Cargo.toml index c7f2cc34b84..5b2da41d066 100644 --- a/src/librustc_trait_selection/Cargo.toml +++ b/src/librustc_trait_selection/Cargo.toml @@ -11,14 +11,12 @@ doctest = false [dependencies] fmt_macros = { path = "../libfmt_macros" } -graphviz = { path = "../libgraphviz" } log = { version = "0.4", features = ["release_max_level_info", "std"] } rustc_attr = { path = "../librustc_attr" } rustc = { path = "../librustc" } rustc_ast = { path = "../librustc_ast" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } -rustc_error_codes = { path = "../librustc_error_codes" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_infer = { path = "../librustc_infer" } diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs index 8b5cf223826..739aff4fb94 100644 --- a/src/librustc_trait_selection/lib.rs +++ b/src/librustc_trait_selection/lib.rs @@ -1,9 +1,6 @@ -//! This crates defines the trait resolution method and the type inference engine. +//! This crates defines the trait resolution method. //! //! - **Traits.** Trait resolution is implemented in the `traits` module. -//! - **Type inference.** The type inference code can be found in the `infer` module; -//! this code handles low-level equality and subtyping operations. The -//! type check pass in the compiler is found in the `librustc_typeck` crate. //! //! For more information about how rustc works, see the [rustc guide]. //! @@ -15,14 +12,10 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] -#![feature(box_patterns)] -#![feature(box_syntax)] #![feature(drain_filter)] -#![feature(never_type)] -#![feature(range_is_empty)] #![feature(in_band_lifetimes)] #![feature(crate_visibility_modifier)] -#![recursion_limit = "512"] +#![recursion_limit = "512"] // For rustdoc #[macro_use] extern crate rustc_macros; From 38fa3783ce635814b7e3814ab26d52b653fc0ab0 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 14 Mar 2020 15:46:57 +0100 Subject: [PATCH 1104/1250] Swap inserts to keep the original ordering --- src/librustc_mir/transform/generator.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index b386582947f..0001bb05363 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1099,17 +1099,17 @@ fn create_generator_resume_function<'tcx>( // Panic when resumed on the returned or poisoned state let generator_kind = body.generator_kind.unwrap(); - if can_return { + if can_unwind { cases.insert( 1, - (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))), + (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), ); } - if can_unwind { + if can_return { cases.insert( 1, - (POISONED, insert_panic_block(tcx, body, ResumedAfterPanic(generator_kind))), + (RETURNED, insert_panic_block(tcx, body, ResumedAfterReturn(generator_kind))), ); } From e80cb2032cac39db2226ba940fad05b5adb17e62 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 15:28:17 +0300 Subject: [PATCH 1105/1250] resolve: Fix regression in resolution of raw keywords in paths --- src/librustc_resolve/lib.rs | 5 +---- src/test/rustdoc-ui/issue-61732.rs | 2 +- src/test/rustdoc-ui/issue-61732.stderr | 8 ++++---- .../keyword/extern/keyword-extern-as-identifier-use.rs | 1 + .../extern/keyword-extern-as-identifier-use.stderr | 9 ++++++++- src/test/ui/resolve/raw-ident-in-path.rs | 5 +++++ src/test/ui/resolve/raw-ident-in-path.stderr | 9 +++++++++ 7 files changed, 29 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/resolve/raw-ident-in-path.rs create mode 100644 src/test/ui/resolve/raw-ident-in-path.stderr diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 948b86225f3..02ac560093d 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -2183,11 +2183,8 @@ impl<'a> Resolver<'a> { Applicability::MaybeIncorrect, )), ) - } else if !ident.is_reserved() { - (format!("maybe a missing crate `{}`?", ident), None) } else { - // the parser will already have complained about the keyword being used - return PathResult::NonModule(PartialRes::new(Res::Err)); + (format!("maybe a missing crate `{}`?", ident), None) } } else if i == 0 { (format!("use of undeclared type or module `{}`", ident), None) diff --git a/src/test/rustdoc-ui/issue-61732.rs b/src/test/rustdoc-ui/issue-61732.rs index d4835c09224..4bd8efeaa3b 100644 --- a/src/test/rustdoc-ui/issue-61732.rs +++ b/src/test/rustdoc-ui/issue-61732.rs @@ -1,4 +1,4 @@ // This previously triggered an ICE. pub(in crate::r#mod) fn main() {} -//~^ ERROR expected module, found unresolved item +//~^ ERROR failed to resolve: maybe a missing crate `r#mod` diff --git a/src/test/rustdoc-ui/issue-61732.stderr b/src/test/rustdoc-ui/issue-61732.stderr index 6c8ba48864d..82134224911 100644 --- a/src/test/rustdoc-ui/issue-61732.stderr +++ b/src/test/rustdoc-ui/issue-61732.stderr @@ -1,11 +1,11 @@ -error[E0577]: expected module, found unresolved item `crate::r#mod` - --> $DIR/issue-61732.rs:3:8 +error[E0433]: failed to resolve: maybe a missing crate `r#mod`? + --> $DIR/issue-61732.rs:3:15 | LL | pub(in crate::r#mod) fn main() {} - | ^^^^^^^^^^^^ not a module + | ^^^^^ maybe a missing crate `r#mod`? error: Compilation failed, aborting rustdoc error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0577`. +For more information about this error, try `rustc --explain E0433`. diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs index b07de3e341c..a46ce67d40d 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.rs @@ -1,3 +1,4 @@ use extern::foo; //~ ERROR expected identifier, found keyword `extern` + //~| ERROR unresolved import `r#extern` fn main() {} diff --git a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr index 05802f2d367..edbb36452b6 100644 --- a/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr +++ b/src/test/ui/keyword/extern/keyword-extern-as-identifier-use.stderr @@ -9,5 +9,12 @@ help: you can escape reserved keywords to use them as identifiers LL | use r#extern::foo; | ^^^^^^^^ -error: aborting due to previous error +error[E0432]: unresolved import `r#extern` + --> $DIR/keyword-extern-as-identifier-use.rs:1:5 + | +LL | use extern::foo; + | ^^^^^^ maybe a missing crate `r#extern`? + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0432`. diff --git a/src/test/ui/resolve/raw-ident-in-path.rs b/src/test/ui/resolve/raw-ident-in-path.rs new file mode 100644 index 00000000000..1bcbef59437 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.rs @@ -0,0 +1,5 @@ +// Regression test for issue #63882. + +type A = crate::r#break; //~ ERROR cannot find type `r#break` in module `crate` + +fn main() {} diff --git a/src/test/ui/resolve/raw-ident-in-path.stderr b/src/test/ui/resolve/raw-ident-in-path.stderr new file mode 100644 index 00000000000..f2efcbc8e85 --- /dev/null +++ b/src/test/ui/resolve/raw-ident-in-path.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `r#break` in module `crate` + --> $DIR/raw-ident-in-path.rs:3:17 + | +LL | type A = crate::r#break; + | ^^^^^^^ not found in `crate` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. From d4ea327f24ff3ba0f4caa9782693dd438429a565 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Mar 2020 18:17:08 +0100 Subject: [PATCH 1106/1250] Make ignore and compile fail signs more visible --- src/librustdoc/html/static/rustdoc.css | 13 ++++++++++--- src/librustdoc/html/static/themes/dark.css | 9 +++++---- src/librustdoc/html/static/themes/light.css | 12 ++++++------ 3 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index f05db6c2185..8887bca3c59 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -1032,7 +1032,7 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { .information { position: absolute; - left: -20px; + left: -25px; margin-top: 7px; z-index: 1; } @@ -1047,12 +1047,13 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { width: 120px; display: none; text-align: center; - padding: 5px 3px; + padding: 5px 3px 3px 3px; border-radius: 6px; margin-left: 5px; top: -5px; left: 105%; z-index: 10; + font-size: 16px; } .tooltip:hover .tooltiptext { @@ -1063,14 +1064,20 @@ h3 > .collapse-toggle, h4 > .collapse-toggle { content: " "; position: absolute; top: 50%; - left: 11px; + left: 16px; margin-top: -5px; border-width: 5px; border-style: solid; } +.tooltip.compile_fail, .tooltip.ignore { + font-weight: bold; + font-size: 20px; +} + .tooltip .tooltiptext { border: 1px solid; + font-weight: normal; } pre.rust { diff --git a/src/librustdoc/html/static/themes/dark.css b/src/librustdoc/html/static/themes/dark.css index e7041d54c6b..ff32a0fa09e 100644 --- a/src/librustdoc/html/static/themes/dark.css +++ b/src/librustdoc/html/static/themes/dark.css @@ -254,7 +254,7 @@ a.test-arrow:hover{ } pre.compile_fail { - border-left: 2px solid rgba(255,0,0,.6); + border-left: 2px solid rgba(255,0,0,.8); } pre.compile_fail:hover, .information:hover + pre.compile_fail { @@ -270,7 +270,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.compile_fail { - color: rgba(255,0,0,.6); + color: rgba(255,0,0,.8); } .information > .compile_fail:hover { @@ -282,7 +282,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .information > .ignore:hover { - color: rgba(255,142,0,1); + color: #ff9200; } .search-failed a { @@ -290,8 +290,9 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip .tooltiptext { - background-color: black; + background-color: #000; color: #fff; + border-color: #000; } .tooltip .tooltiptext::after { diff --git a/src/librustdoc/html/static/themes/light.css b/src/librustdoc/html/static/themes/light.css index a1efef6701f..2b2819f7126 100644 --- a/src/librustdoc/html/static/themes/light.css +++ b/src/librustdoc/html/static/themes/light.css @@ -248,7 +248,7 @@ a.test-arrow:hover{ } pre.compile_fail { - border-left: 2px solid rgba(255,0,0,.4); + border-left: 2px solid rgba(255,0,0,.5); } pre.compile_fail:hover, .information:hover + pre.compile_fail { @@ -256,7 +256,7 @@ pre.compile_fail:hover, .information:hover + pre.compile_fail { } pre.ignore { - border-left: 2px solid rgba(255,142,0,.4); + border-left: 2px solid rgba(255,142,0,.6); } pre.ignore:hover, .information:hover + pre.ignore { @@ -264,7 +264,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.compile_fail { - color: rgba(255,0,0,.3); + color: rgba(255,0,0,.5); } .information > .compile_fail:hover { @@ -272,11 +272,11 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip.ignore { - color: rgba(255,142,0,.3); + color: rgba(255,142,0,.6); } .information > .ignore:hover { - color: rgba(255,142,0,1); + color: #ff9200; } .search-failed a { @@ -284,7 +284,7 @@ pre.ignore:hover, .information:hover + pre.ignore { } .tooltip .tooltiptext { - background-color: black; + background-color: #000; color: #fff; } From 8216a32d32e705ecbc7c2329f7637fbd259a190d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Mar 2020 18:17:20 +0100 Subject: [PATCH 1107/1250] remove compilation warning --- src/librustdoc/clean/inline.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 7cb870ae702..f600b3308e8 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -12,7 +12,6 @@ use rustc_hir::Mutability; use rustc_metadata::creader::LoadedMacro; use rustc_mir::const_eval::is_min_const_fn; use rustc_span::hygiene::MacroKind; -use rustc_span::symbol::sym; use rustc_span::Span; use crate::clean::{self, GetDefId, ToSource, TypeKind}; From 864d05bc8a366daaa52807b37bb1ad86127bc23a Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 14 Mar 2020 19:57:10 +0100 Subject: [PATCH 1108/1250] Add a workaround for catch_unwind in stage1 mingw target Fixes #70001 --- src/libstd/panicking.rs | 54 +++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 0be71b52d9e..05a31358443 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -278,36 +278,36 @@ pub unsafe fn r#try R>(f: F) -> Result> Err(ManuallyDrop::into_inner(data.p)) }; - // Compatibility wrapper around the try intrinsic for bootstrap - #[inline] + // Compatibility wrapper around the try intrinsic for bootstrap. + // + // We also need to mark it #[inline(never)] to work around a bug on MinGW + // targets: the unwinding implementation was relying on UB, but this only + // becomes a problem in practice if inlining is involved. + #[cfg(not(bootstrap))] + use intrinsics::r#try as do_try; + #[cfg(bootstrap)] + #[inline(never)] unsafe fn do_try(try_fn: fn(*mut u8), data: *mut u8, catch_fn: fn(*mut u8, *mut u8)) -> i32 { - #[cfg(not(bootstrap))] - { - intrinsics::r#try(try_fn, data, catch_fn) - } - #[cfg(bootstrap)] - { - use crate::mem::MaybeUninit; + use crate::mem::MaybeUninit; + #[cfg(target_env = "msvc")] + type TryPayload = [u64; 2]; + #[cfg(not(target_env = "msvc"))] + type TryPayload = *mut u8; + + let mut payload: MaybeUninit = MaybeUninit::uninit(); + let payload_ptr = payload.as_mut_ptr() as *mut u8; + let r = intrinsics::r#try(try_fn, data, payload_ptr); + if r != 0 { #[cfg(target_env = "msvc")] - type TryPayload = [u64; 2]; + { + catch_fn(data, payload_ptr) + } #[cfg(not(target_env = "msvc"))] - type TryPayload = *mut u8; - - let mut payload: MaybeUninit = MaybeUninit::uninit(); - let payload_ptr = payload.as_mut_ptr() as *mut u8; - let r = intrinsics::r#try(try_fn, data, payload_ptr); - if r != 0 { - #[cfg(target_env = "msvc")] - { - catch_fn(data, payload_ptr) - } - #[cfg(not(target_env = "msvc"))] - { - catch_fn(data, payload.assume_init()) - } + { + catch_fn(data, payload.assume_init()) } - r } + r } // We consider unwinding to be rare, so mark this function as cold. However, @@ -321,7 +321,9 @@ pub unsafe fn r#try R>(f: F) -> Result> obj } - #[inline] + // See comment on do_try above for why #[inline(never)] is needed on bootstrap. + #[cfg_attr(bootstrap, inline(never))] + #[cfg_attr(not(bootstrap), inline)] fn do_call R, R>(data: *mut u8) { unsafe { let data = data as *mut Data; From cfa1d4e383d050e79868b9a6f8e1c57f1ab7dd13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 11:14:47 +0100 Subject: [PATCH 1109/1250] Add HIR queries --- src/librustc/hir/mod.rs | 24 +++++++++++ src/librustc/ich/hcx.rs | 9 ---- src/librustc/ich/impls_hir.rs | 62 ++++----------------------- src/librustc/query/mod.rs | 8 ++++ src/librustc/ty/query/mod.rs | 1 + src/librustc_hir/hir.rs | 2 +- src/librustc_hir/stable_hash_impls.rs | 59 ++++++++++++++++++++++++- 7 files changed, 101 insertions(+), 64 deletions(-) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 30c9a2ee769..fd0a7e73b34 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -7,12 +7,36 @@ pub mod map; use crate::ty::query::Providers; use crate::ty::TyCtxt; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::print; +use rustc_hir::Body; use rustc_hir::Crate; use rustc_hir::HirId; +use rustc_hir::ItemLocalId; +use rustc_hir::Node; +use rustc_index::vec::IndexVec; use std::ops::Deref; +#[derive(HashStable)] +pub struct HirOwner<'tcx> { + parent: HirId, + node: Node<'tcx>, +} + +#[derive(HashStable)] +pub struct HirItem<'tcx> { + parent: ItemLocalId, + node: Node<'tcx>, +} + +#[derive(HashStable)] +pub struct HirOwnerItems<'tcx> { + owner: &'tcx HirOwner<'tcx>, + items: IndexVec>>, + bodies: FxHashMap>, +} + /// A wrapper type which allows you to access HIR. #[derive(Clone)] pub struct Hir<'tcx> { diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index f28e26ef2c3..5a49d9a1f1a 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -164,15 +164,6 @@ impl<'a> StableHashingContext<'a> { } IGNORED_ATTRIBUTES.with(|attrs| attrs.contains(&name)) } - - pub fn hash_hir_item_like(&mut self, f: F) { - let prev_hash_node_ids = self.node_id_hashing_mode; - self.node_id_hashing_mode = NodeIdHashingMode::Ignore; - - f(self); - - self.node_id_hashing_mode = prev_hash_node_ids; - } } /// Something that can provide a stable hashing context. diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index eadc9ddeee6..1015ffdbf28 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -105,6 +105,15 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } } } + + fn hash_hir_item_like(&mut self, f: F) { + let prev_hash_node_ids = self.node_id_hashing_mode; + self.node_id_hashing_mode = NodeIdHashingMode::Ignore; + + f(self); + + self.node_id_hashing_mode = prev_hash_node_ids; + } } impl<'a> ToStableHashKey> for DefId { @@ -158,59 +167,6 @@ impl<'a> ToStableHashKey> for hir::ItemLocalId { } } -impl<'a> HashStable> for hir::TraitItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::ImplItem<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::ImplItem { - hir_id: _, - ident, - ref vis, - defaultness, - ref attrs, - ref generics, - ref kind, - span, - } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - defaultness.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - generics.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - -impl<'a> HashStable> for hir::Item<'_> { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let hir::Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; - - hcx.hash_hir_item_like(|hcx| { - ident.name.hash_stable(hcx, hasher); - attrs.hash_stable(hcx, hasher); - kind.hash_stable(hcx, hasher); - vis.hash_stable(hcx, hasher); - span.hash_stable(hcx, hasher); - }); - } -} - impl<'a> HashStable> for hir::Body<'_> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { let hir::Body { params, value, generator_kind } = self; diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 11e9acf3a39..cf7cb30a056 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -55,6 +55,14 @@ rustc_queries! { desc { "get the crate HIR" } } + query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { + eval_always + } + + query hir_owner_items(key: DefId) -> &'tcx HirOwnerItems<'tcx> { + eval_always + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { cache_on_disk_if { key.is_local() } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 8adb828fbeb..667c00a3df1 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,5 +1,6 @@ use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams}; use crate::hir::exports::Export; +use crate::hir::{HirOwner, HirOwnerItems}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; use crate::middle::codegen_fn_attrs::CodegenFnAttrs; diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 9993e5c55f6..ed06aeb60bb 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -2653,7 +2653,7 @@ pub type TraitMap = NodeMap>>; // imported. pub type GlobMap = NodeMap>; -#[derive(Copy, Clone, Debug)] +#[derive(Copy, Clone, Debug, HashStable_Generic)] pub enum Node<'hir> { Param(&'hir Param<'hir>), Item(&'hir Item<'hir>), diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index 3938a0369b9..9756edc3f4d 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -1,6 +1,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use crate::hir::{BodyId, Expr, ImplItemId, ItemId, Mod, TraitItemId, Ty, VisibilityKind}; +use crate::hir::{ + BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty, + VisibilityKind, +}; use crate::hir_id::HirId; /// Requirements for a `StableHashingContext` to be used in this crate. @@ -16,6 +19,7 @@ pub trait HashStableContext: fn hash_hir_expr(&mut self, _: &Expr<'_>, hasher: &mut StableHasher); fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); + fn hash_hir_item_like(&mut self, f: F); } impl HashStable for HirId { @@ -78,3 +82,56 @@ impl HashStable for VisibilityKind<'_> hcx.hash_hir_visibility_kind(self, hasher) } } + +impl HashStable for TraitItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let TraitItem { hir_id: _, ident, ref attrs, ref generics, ref kind, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for ImplItem<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let ImplItem { + hir_id: _, + ident, + ref vis, + defaultness, + ref attrs, + ref generics, + ref kind, + span, + } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + defaultness.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + generics.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} + +impl HashStable for Item<'_> { + fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) { + let Item { ident, ref attrs, hir_id: _, ref kind, ref vis, span } = *self; + + hcx.hash_hir_item_like(|hcx| { + ident.name.hash_stable(hcx, hasher); + attrs.hash_stable(hcx, hasher); + kind.hash_stable(hcx, hasher); + vis.hash_stable(hcx, hasher); + span.hash_stable(hcx, hasher); + }); + } +} From 21386e1355a1aa5b8709d969d7fef878b4602491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 11:45:04 +0100 Subject: [PATCH 1110/1250] Collect the new maps --- src/librustc/arena.rs | 4 +++ src/librustc/hir/map/collector.rs | 45 ++++++++++++++++++++++++++++--- src/librustc/hir/map/mod.rs | 21 ++++++++++++--- src/librustc/hir/mod.rs | 4 +-- src/librustc_interface/passes.rs | 2 +- 5 files changed, 67 insertions(+), 9 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 0384a9f7815..e379f2aa10b 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -161,6 +161,10 @@ macro_rules! arena_types { [] type_binding: rustc_hir::TypeBinding<$tcx>, [] variant: rustc_hir::Variant<$tcx>, [] where_predicate: rustc_hir::WherePredicate<$tcx>, + + // HIR query types + [] hir_owner: rustc::hir::HirOwner<$tcx>, + [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>, ], $tcx); ) } diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index ca5f9ba5ad6..a192cf52969 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,6 +1,8 @@ +use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; use crate::hir::map::definitions::{self, DefPathHash}; use crate::hir::map::{Entry, HirEntryMap, Map}; +use crate::hir::{HirItem, HirOwner, HirOwnerItems}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; use rustc_ast::ast::NodeId; @@ -22,12 +24,17 @@ use std::iter::repeat; /// A visitor that walks over the HIR and collects `Node`s into a HIR map. pub(super) struct NodeCollector<'a, 'hir> { + arena: &'hir Arena<'hir>, + /// The crate krate: &'hir Crate<'hir>, /// Source map source_map: &'a SourceMap, + owner_map: FxHashMap>, + owner_items_map: FxHashMap>, + /// The node map map: HirEntryMap<'hir>, /// The parent of this node @@ -112,6 +119,7 @@ fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { impl<'a, 'hir> NodeCollector<'a, 'hir> { pub(super) fn root( sess: &'a Session, + arena: &'hir Arena<'hir>, krate: &'hir Crate<'hir>, dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, @@ -161,6 +169,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } let mut collector = NodeCollector { + arena, krate, source_map: sess.source_map(), map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()), @@ -174,6 +183,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { hir_to_node_id, hcx, hir_body_nodes, + owner_map: FxHashMap::default(), + owner_items_map: FxHashMap::default(), }; collector.insert_entry( hir::CRATE_HIR_ID, @@ -192,7 +203,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64, - ) -> (HirEntryMap<'hir>, Svh) { + ) -> ( + HirEntryMap<'hir>, + FxHashMap>, + FxHashMap>, + Svh, + ) { self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); let node_hashes = self.hir_body_nodes.iter().fold( @@ -229,13 +245,36 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash: Fingerprint = stable_hasher.finish(); let svh = Svh::new(crate_hash.to_smaller_hash()); - (self.map, svh) + (self.map, self.owner_map, self.owner_items_map, svh) } fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { + let i = id.local_id.as_u32() as usize; + + let owner = HirOwner { parent: entry.parent, node: entry.node }; + + let arena = self.arena; + + let items = self.owner_items_map.entry(id.owner).or_insert_with(|| { + arena.alloc(HirOwnerItems { items: IndexVec::new(), bodies: FxHashMap::default() }) + }); + + if i == 0 { + self.owner_map.insert(id.owner, self.arena.alloc(owner)); + // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert + //assert!(self.owner_map.insert(id.owner, self.arena.alloc(owner)).is_none()); + } else { + let len = items.items.len(); + if i >= len { + items.items.extend(repeat(None).take(i - len + 1)); + } + assert_eq!(entry.parent.owner, id.owner); + items.items[id.local_id] = + Some(HirItem { parent: entry.parent.local_id, node: entry.node }); + } + debug!("hir_map: {:?} => {:?}", id, entry); let local_map = &mut self.map[id.owner]; - let i = id.local_id.as_u32() as usize; let len = local_map.len(); if i >= len { local_map.extend(repeat(None).take(i - len + 1)); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 4c889ef4100..16b4047bd15 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -3,7 +3,9 @@ pub use self::definitions::{ DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, }; +use crate::arena::Arena; use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::hir::{HirOwner, HirOwnerItems}; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; use rustc_ast::ast::{self, Name, NodeId}; @@ -145,6 +147,9 @@ pub struct Map<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, + pub(super) owner_map: FxHashMap>, + pub(super) owner_items_map: FxHashMap>, + map: HirEntryMap<'hir>, definitions: Definitions, @@ -1201,6 +1206,7 @@ impl Named for ImplItem<'_> { pub fn map_crate<'hir>( sess: &rustc_session::Session, + arena: &'hir Arena<'hir>, cstore: &CrateStoreDyn, krate: &'hir Crate<'hir>, dep_graph: DepGraph, @@ -1215,11 +1221,11 @@ pub fn map_crate<'hir>( .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); - let (map, crate_hash) = { + let (map, owner_map, owner_items_map, crate_hash) = { let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore); let mut collector = - NodeCollector::root(sess, krate, &dep_graph, &definitions, &hir_to_node_id, hcx); + NodeCollector::root(sess, arena, krate, &dep_graph, &definitions, &hir_to_node_id, hcx); intravisit::walk_crate(&mut collector, krate); let crate_disambiguator = sess.local_crate_disambiguator(); @@ -1227,7 +1233,16 @@ pub fn map_crate<'hir>( collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) }; - let map = Map { krate, dep_graph, crate_hash, map, hir_to_node_id, definitions }; + let map = Map { + krate, + dep_graph, + crate_hash, + map, + owner_map, + owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), + hir_to_node_id, + definitions, + }; sess.time("validate_HIR_map", || { hir_id_validator::check_crate(&map, sess); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index fd0a7e73b34..57af8d250b3 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -24,7 +24,7 @@ pub struct HirOwner<'tcx> { node: Node<'tcx>, } -#[derive(HashStable)] +#[derive(HashStable, Clone)] pub struct HirItem<'tcx> { parent: ItemLocalId, node: Node<'tcx>, @@ -32,7 +32,7 @@ pub struct HirItem<'tcx> { #[derive(HashStable)] pub struct HirOwnerItems<'tcx> { - owner: &'tcx HirOwner<'tcx>, + //owner: &'tcx HirOwner<'tcx>, items: IndexVec>>, bodies: FxHashMap>, } diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index bffbcd33669..7035b956c9d 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -716,7 +716,7 @@ pub fn create_global_ctxt<'tcx>( let defs = mem::take(&mut resolver_outputs.definitions); // Construct the HIR map. - let hir_map = map::map_crate(sess, &*resolver_outputs.cstore, krate, dep_graph, defs); + let hir_map = map::map_crate(sess, &**arena, &*resolver_outputs.cstore, krate, dep_graph, defs); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); From 518c78fbd30849b379e25c54584c6d8541d33eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 13:13:35 +0100 Subject: [PATCH 1111/1250] Create Map after TyCtxt --- src/librustc/arena.rs | 2 + src/librustc/hir/map/collector.rs | 6 + src/librustc/hir/map/hir_id_validator.rs | 23 ++-- src/librustc/hir/map/mod.rs | 163 +++++------------------ src/librustc/hir/mod.rs | 44 +++++- src/librustc/query/mod.rs | 6 + src/librustc/ty/context.rs | 42 +++--- src/librustc/ty/query/mod.rs | 1 + 8 files changed, 130 insertions(+), 157 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index e379f2aa10b..223bed5d635 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -163,6 +163,8 @@ macro_rules! arena_types { [] where_predicate: rustc_hir::WherePredicate<$tcx>, // HIR query types + [few] hir_map: rustc::hir::map::Map<$tcx>, + [few] hir_definitions: rustc::hir::map::definitions::Definitions, [] hir_owner: rustc::hir::HirOwner<$tcx>, [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>, ], $tcx); diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a192cf52969..0ac8f403cb7 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -209,6 +209,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { FxHashMap>, Svh, ) { + // Insert bodies into the map + for (id, body) in self.krate.bodies.iter() { + let bodies = &mut self.owner_items_map.get_mut(&id.hir_id.owner).unwrap().bodies; + assert!(bodies.insert(id.hir_id.local_id, body).is_none()); + } + self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0); let node_hashes = self.hir_body_nodes.iter().fold( diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index f176f924343..ef000f23d8b 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,15 +1,15 @@ -use crate::hir::map::Map; -use rustc_data_structures::fx::FxHashSet; +use crate::hir::map::EarlyMap; +/*use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::{HirId, ItemLocalId}; +use rustc_hir::{HirId, ItemLocalId};*/ -pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) { +pub fn check_crate(hir_map: &EarlyMap<'_>, sess: &rustc_session::Session) { hir_map.dep_graph.assert_ignored(); - + /* let errors = Lock::new(Vec::new()); par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| { @@ -25,23 +25,23 @@ pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); sess.delay_span_bug(rustc_span::DUMMY_SP, &message); - } + }*/ } - +/* struct HirIdValidator<'a, 'hir> { - hir_map: &'a Map<'hir>, + hir_map: &'a EarlyMap<'hir>, owner_def_index: Option, hir_ids_seen: FxHashSet, errors: &'a Lock>, } struct OuterVisitor<'a, 'hir> { - hir_map: &'a Map<'hir>, + hir_map: &'a EarlyMap<'hir>, errors: &'a Lock>, } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: &'a EarlyMap<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, owner_def_index: None, @@ -133,7 +133,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - type Map = Map<'hir>; + type Map = EarlyMap<'hir>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) @@ -173,3 +173,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { // different owner. } } +*/ diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 16b4047bd15..6b22ac01a06 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -8,6 +8,7 @@ use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; use crate::hir::{HirOwner, HirOwnerItems}; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; +use crate::ty::TyCtxt; use rustc_ast::ast::{self, Name, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; @@ -138,9 +139,30 @@ impl<'hir> Entry<'hir> { pub(super) type HirEntryMap<'hir> = IndexVec>>>; /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. -#[derive(Clone)] +pub struct EarlyMap<'hir> { + pub krate: &'hir Crate<'hir>, + + pub dep_graph: DepGraph, + + /// The SVH of the local crate. + pub crate_hash: Svh, + + pub(super) owner_map: FxHashMap>, + pub(super) owner_items_map: FxHashMap>, + + pub(super) map: HirEntryMap<'hir>, + + pub(crate) definitions: &'hir Definitions, + + /// The reverse mapping of `node_to_hir_id`. + pub(super) hir_to_node_id: FxHashMap, +} + +/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. pub struct Map<'hir> { - krate: &'hir Crate<'hir>, + pub(super) tcx: TyCtxt<'hir>, + + pub(super) krate: &'hir Crate<'hir>, pub dep_graph: DepGraph, @@ -150,12 +172,12 @@ pub struct Map<'hir> { pub(super) owner_map: FxHashMap>, pub(super) owner_items_map: FxHashMap>, - map: HirEntryMap<'hir>, + pub(super) map: HirEntryMap<'hir>, - definitions: Definitions, + pub(super) definitions: &'hir Definitions, /// The reverse mapping of `node_to_hir_id`. - hir_to_node_id: FxHashMap, + pub(super) hir_to_node_id: FxHashMap, } /// An iterator that walks up the ancestor tree of a given `HirId`. @@ -406,11 +428,11 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.body(id) + self.tcx + .hir_owner_items(DefId::local(id.hir_id.owner)) + .bodies + .get(&id.hir_id.local_id) + .unwrap() } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { @@ -966,45 +988,6 @@ impl<'hir> Map<'hir> { attrs.unwrap_or(&[]) } - /// Returns an iterator that yields all the hir ids in the map. - fn all_ids<'a>(&'a self) -> impl Iterator + 'a { - // This code is a bit awkward because the map is implemented as 2 levels of arrays, - // see the comment on `HirEntryMap`. - // Iterate over all the indices and return a reference to - // local maps and their index given that they exist. - self.map.iter_enumerated().flat_map(move |(owner, local_map)| { - // Iterate over each valid entry in the local map. - local_map.iter_enumerated().filter_map(move |(i, entry)| { - entry.map(move |_| { - // Reconstruct the `HirId` based on the 3 indices we used to find it. - HirId { owner, local_id: i } - }) - }) - }) - } - - /// Returns an iterator that yields the node id's with paths that - /// match `parts`. (Requires `parts` is non-empty.) - /// - /// For example, if given `parts` equal to `["bar", "quux"]`, then - /// the iterator will produce node id's for items with paths - /// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and - /// any other such items it can find in the map. - pub fn nodes_matching_suffix<'a>( - &'a self, - parts: &'a [String], - ) -> impl Iterator + 'a { - let nodes = NodesMatchingSuffix { - map: self, - item_name: parts.last().unwrap(), - in_which: &parts[..parts.len() - 1], - }; - - self.all_ids() - .filter(move |hir| nodes.matches_suffix(*hir)) - .map(move |hir| self.hir_to_node_id(hir)) - } - pub fn span(&self, hir_id: HirId) -> Span { self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { @@ -1087,82 +1070,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> { } } -pub struct NodesMatchingSuffix<'a> { - map: &'a Map<'a>, - item_name: &'a String, - in_which: &'a [String], -} - -impl<'a> NodesMatchingSuffix<'a> { - /// Returns `true` only if some suffix of the module path for parent - /// matches `self.in_which`. - /// - /// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`; - /// returns true if parent's path ends with the suffix - /// `x_0::x_1::...::x_k`. - fn suffix_matches(&self, parent: HirId) -> bool { - let mut cursor = parent; - for part in self.in_which.iter().rev() { - let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) { - None => return false, - Some((node_id, name)) => (node_id, name), - }; - if mod_name.as_str() != *part { - return false; - } - cursor = self.map.get_parent_item(mod_id); - } - return true; - - // Finds the first mod in parent chain for `id`, along with - // that mod's name. - // - // If `id` itself is a mod named `m` with parent `p`, then - // returns `Some(id, m, p)`. If `id` has no mod in its parent - // chain, then returns `None`. - fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> { - loop { - if let Node::Item(item) = map.find(id)? { - if item_is_mod(&item) { - return Some((id, item.ident.name)); - } - } - let parent = map.get_parent_item(id); - if parent == id { - return None; - } - id = parent; - } - - fn item_is_mod(item: &Item<'_>) -> bool { - match item.kind { - ItemKind::Mod(_) => true, - _ => false, - } - } - } - } - - // We are looking at some node `n` with a given name and parent - // id; do their names match what I am seeking? - fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool { - name.as_str() == *self.item_name && self.suffix_matches(parent_of_n) - } - - fn matches_suffix(&self, hir: HirId) -> bool { - let name = match self.map.find_entry(hir).map(|entry| entry.node) { - Some(Node::Item(n)) => n.name(), - Some(Node::ForeignItem(n)) => n.name(), - Some(Node::TraitItem(n)) => n.name(), - Some(Node::ImplItem(n)) => n.name(), - Some(Node::Variant(n)) => n.name(), - Some(Node::Field(n)) => n.name(), - _ => return false, - }; - self.matches_names(self.map.get_parent_item(hir), name) - } -} - trait Named { fn name(&self) -> Name; } @@ -1211,7 +1118,7 @@ pub fn map_crate<'hir>( krate: &'hir Crate<'hir>, dep_graph: DepGraph, definitions: Definitions, -) -> Map<'hir> { +) -> EarlyMap<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); // Build the reverse mapping of `node_to_hir_id`. @@ -1233,7 +1140,7 @@ pub fn map_crate<'hir>( collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) }; - let map = Map { + let map = EarlyMap { krate, dep_graph, crate_hash, @@ -1241,7 +1148,7 @@ pub fn map_crate<'hir>( owner_map, owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), hir_to_node_id, - definitions, + definitions: arena.alloc(definitions), }; sess.time("validate_HIR_map", || { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 57af8d250b3..d7999ee5f51 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -7,6 +7,7 @@ pub mod map; use crate::ty::query::Providers; use crate::ty::TyCtxt; +use rustc_data_structures::cold_path; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::print; @@ -68,7 +69,17 @@ impl<'hir> print::PpAnn for Hir<'hir> { impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn hir(self) -> Hir<'tcx> { - Hir { tcx: self, map: &self.hir_map } + let map = self.late_hir_map.load(); + let map = if unlikely!(map.is_none()) { + cold_path(|| { + let map = self.hir_map(LOCAL_CRATE); + self.late_hir_map.store(Some(map)); + map + }) + } else { + map.unwrap() + }; + Hir { tcx: self, map } } pub fn parent_module(self, id: HirId) -> DefId { @@ -81,6 +92,35 @@ pub fn provide(providers: &mut Providers<'_>) { let hir = tcx.hir(); hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap())) }; - providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate(); + providers.hir_crate = |tcx, _| tcx.hir_map(LOCAL_CRATE).untracked_krate(); + providers.hir_map = |tcx, id| { + assert_eq!(id, LOCAL_CRATE); + let early = tcx.hir_map.steal(); + tcx.arena.alloc(map::Map { + tcx, + krate: early.krate, + + dep_graph: early.dep_graph, + + crate_hash: early.crate_hash, + + owner_map: early.owner_map, + owner_items_map: early.owner_items_map, + + map: early.map, + + definitions: early.definitions, + + hir_to_node_id: early.hir_to_node_id, + }) + }; + providers.hir_owner = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + *tcx.hir().map.owner_map.get(&id.index).unwrap() + }; + providers.hir_owner_items = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + *tcx.hir().map.owner_items_map.get(&id.index).unwrap() + }; map::provide(providers); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index cf7cb30a056..b843bc17d2c 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -55,6 +55,12 @@ rustc_queries! { desc { "get the crate HIR" } } + query hir_map(_: CrateNum) -> &'tcx map::Map<'tcx> { + eval_always + no_hash + desc { "index HIR" } + } + query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { eval_always } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6fab55e9fd9..cff93015d04 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -5,6 +5,7 @@ use crate::dep_graph::DepGraph; use crate::dep_graph::{self, DepConstructor}; use crate::hir::exports::Export; use crate::hir::map as hir_map; +use crate::hir::map::definitions::Definitions; use crate::hir::map::{DefPathData, DefPathHash}; use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos}; @@ -52,7 +53,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; -use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, AtomicCell, Lock, Lrc, WorkerLocal}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE}; @@ -971,8 +972,11 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - /// This should usually be accessed with the `tcx.hir()` method. - pub(crate) hir_map: hir_map::Map<'tcx>, + /// These should usually be accessed with the `tcx.hir()` method. + pub(crate) hir_map: Steal>, + pub(crate) late_hir_map: AtomicCell>>, + pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, + pub(crate) definitions: &'tcx Definitions, /// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate /// as well as all upstream crates. Only populated in incremental mode. @@ -1116,7 +1120,7 @@ impl<'tcx> TyCtxt<'tcx> { extern_providers: ty::query::Providers<'tcx>, arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, - hir: hir_map::Map<'tcx>, + hir: hir_map::EarlyMap<'tcx>, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, output_filenames: &OutputFilenames, @@ -1129,6 +1133,7 @@ impl<'tcx> TyCtxt<'tcx> { let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); let dep_graph = hir.dep_graph.clone(); + let definitions = hir.definitions; let cstore = resolutions.cstore; let crates = cstore.crates_untracked(); let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); @@ -1139,7 +1144,7 @@ impl<'tcx> TyCtxt<'tcx> { let def_path_tables = crates .iter() .map(|&cnum| (cnum, cstore.def_path_table(cnum))) - .chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table()))); + .chain(iter::once((LOCAL_CRATE, definitions.def_path_table()))); // Precompute the capacity of the hashmap so we don't have to // re-allocate when populating it. @@ -1159,11 +1164,11 @@ impl<'tcx> TyCtxt<'tcx> { let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { - let hir_id = hir.node_to_hir_id(k); + let hir_id = definitions.node_to_hir_id(k); let map = trait_map.entry(hir_id.owner).or_default(); let v = v .into_iter() - .map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id))) + .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id))) .collect(); map.insert(hir_id.local_id, StableVec::new(v)); } @@ -1185,28 +1190,33 @@ impl<'tcx> TyCtxt<'tcx> { .export_map .into_iter() .map(|(k, v)| { - let exports: Vec<_> = - v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect(); + let exports: Vec<_> = v + .into_iter() + .map(|e| e.map_id(|id| definitions.node_to_hir_id(id))) + .collect(); (k, exports) }) .collect(), maybe_unused_trait_imports: resolutions .maybe_unused_trait_imports .into_iter() - .map(|id| hir.local_def_id_from_node_id(id)) + .map(|id| definitions.local_def_id(id)) .collect(), maybe_unused_extern_crates: resolutions .maybe_unused_extern_crates .into_iter() - .map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp)) + .map(|(id, sp)| (definitions.local_def_id(id), sp)) .collect(), glob_map: resolutions .glob_map .into_iter() - .map(|(id, names)| (hir.local_def_id_from_node_id(id), names)) + .map(|(id, names)| (definitions.local_def_id(id), names)) .collect(), extern_prelude: resolutions.extern_prelude, - hir_map: hir, + untracked_crate: hir.krate, + hir_map: Steal::new(hir), + late_hir_map: AtomicCell::new(None), + definitions, def_path_hash_to_def_id, queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), rcache: Default::default(), @@ -1286,7 +1296,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { if def_id.is_local() { - self.hir().definitions().def_path_hash(def_id.index) + self.definitions.def_path_hash(def_id.index) } else { self.cstore.def_path_hash(def_id) } @@ -1333,9 +1343,9 @@ impl<'tcx> TyCtxt<'tcx> { #[inline(always)] pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> { - let krate = self.gcx.hir_map.untracked_krate(); + let krate = self.gcx.untracked_crate; - StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore) + StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore) } // This method makes sure that we have a DepNode and a Fingerprint for diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 667c00a3df1..b6976221ef7 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -1,5 +1,6 @@ use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams}; use crate::hir::exports::Export; +use crate::hir::map; use crate::hir::{HirOwner, HirOwnerItems}; use crate::infer::canonical::{self, Canonical}; use crate::lint::LintLevelMap; From e1a9626bb3202568e97bd580a13c1bf61ca4d6e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 15:17:05 +0100 Subject: [PATCH 1112/1250] Update item functions --- src/librustc/hir/map/mod.rs | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 6b22ac01a06..c5499e7fe17 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -404,27 +404,24 @@ impl<'hir> Map<'hir> { } pub fn item(&self, id: HirId) -> &'hir Item<'hir> { - self.read(id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.item(id) + match self.find(id).unwrap() { + Node::Item(item) => item, + _ => bug!(), + } } pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_item(id) + match self.find(id.hir_id).unwrap() { + Node::TraitItem(item) => item, + _ => bug!(), + } } pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { - self.read(id.hir_id); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.impl_item(id) + match self.find(id.hir_id).unwrap() { + Node::ImplItem(item) => item, + _ => bug!(), + } } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { From d3c73940b7516f68aaa682e5ef1b54e3b6103e3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 15:34:39 +0100 Subject: [PATCH 1113/1250] Update `fn_decl_by_hir_id` and `fn_sig_by_hir_id` --- src/librustc/hir/map/mod.rs | 86 +++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index c5499e7fe17..e9d38656348 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -45,54 +45,56 @@ impl<'hir> Entry<'hir> { _ => Some(self.parent), } } +} - fn fn_decl(&self) -> Option<&'hir FnDecl<'hir>> { - match self.node { - Node::Item(ref item) => match item.kind { - ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), - _ => None, - }, - - Node::TraitItem(ref item) => match item.kind { - TraitItemKind::Fn(ref sig, _) => Some(&sig.decl), - _ => None, - }, +fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { + match node { + Node::Item(ref item) => match item.kind { + ItemKind::Fn(ref sig, _, _) => Some(&sig.decl), + _ => None, + }, - Node::ImplItem(ref item) => match item.kind { - ImplItemKind::Method(ref sig, _) => Some(&sig.decl), - _ => None, - }, + Node::TraitItem(ref item) => match item.kind { + TraitItemKind::Fn(ref sig, _) => Some(&sig.decl), + _ => None, + }, - Node::Expr(ref expr) => match expr.kind { - ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), - _ => None, - }, + Node::ImplItem(ref item) => match item.kind { + ImplItemKind::Method(ref sig, _) => Some(&sig.decl), + _ => None, + }, + Node::Expr(ref expr) => match expr.kind { + ExprKind::Closure(_, ref fn_decl, ..) => Some(fn_decl), _ => None, - } - } + }, - fn fn_sig(&self) -> Option<&'hir FnSig<'hir>> { - match &self.node { - Node::Item(item) => match &item.kind { - ItemKind::Fn(sig, _, _) => Some(sig), - _ => None, - }, + _ => None, + } +} - Node::TraitItem(item) => match &item.kind { - TraitItemKind::Fn(sig, _) => Some(sig), - _ => None, - }, +fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> { + match &node { + Node::Item(item) => match &item.kind { + ItemKind::Fn(sig, _, _) => Some(sig), + _ => None, + }, - Node::ImplItem(item) => match &item.kind { - ImplItemKind::Method(sig, _) => Some(sig), - _ => None, - }, + Node::TraitItem(item) => match &item.kind { + TraitItemKind::Fn(sig, _) => Some(sig), + _ => None, + }, + Node::ImplItem(item) => match &item.kind { + ImplItemKind::Method(sig, _) => Some(sig), _ => None, - } + }, + + _ => None, } +} +impl<'hir> Entry<'hir> { fn associated_body(self) -> Option { match self.node { Node::Item(item) => match item.kind { @@ -433,18 +435,18 @@ impl<'hir> Map<'hir> { } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_decl() + if let Some(node) = self.find(hir_id) { + fn_decl(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } pub fn fn_sig_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnSig<'hir>> { - if let Some(entry) = self.find_entry(hir_id) { - entry.fn_sig() + if let Some(node) = self.find(hir_id) { + fn_sig(node) } else { - bug!("no entry for hir_id `{}`", hir_id) + bug!("no node for hir_id `{}`", hir_id) } } From 0c68b7a7fa55f4a958dd85f140ece052aafc4a2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 16:10:50 +0100 Subject: [PATCH 1114/1250] Update `body_owner` and `maybe_body_owned_by` --- src/librustc/hir/map/mod.rs | 70 ++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e9d38656348..38260eac890 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -94,43 +94,41 @@ fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> { } } -impl<'hir> Entry<'hir> { - fn associated_body(self) -> Option { - match self.node { - Node::Item(item) => match item.kind { - ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { - Some(body) - } - _ => None, - }, - - Node::TraitItem(item) => match item.kind { - TraitItemKind::Const(_, Some(body)) - | TraitItemKind::Fn(_, TraitMethod::Provided(body)) => Some(body), - _ => None, - }, +fn associated_body<'hir>(node: Node<'hir>) -> Option { + match node { + Node::Item(item) => match item.kind { + ItemKind::Const(_, body) | ItemKind::Static(.., body) | ItemKind::Fn(.., body) => { + Some(body) + } + _ => None, + }, - Node::ImplItem(item) => match item.kind { - ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), - _ => None, - }, + Node::TraitItem(item) => match item.kind { + TraitItemKind::Const(_, Some(body)) + | TraitItemKind::Fn(_, TraitMethod::Provided(body)) => Some(body), + _ => None, + }, - Node::AnonConst(constant) => Some(constant.body), + Node::ImplItem(item) => match item.kind { + ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), + _ => None, + }, - Node::Expr(expr) => match expr.kind { - ExprKind::Closure(.., body, _, _) => Some(body), - _ => None, - }, + Node::AnonConst(constant) => Some(constant.body), + Node::Expr(expr) => match expr.kind { + ExprKind::Closure(.., body, _, _) => Some(body), _ => None, - } + }, + + _ => None, } +} - fn is_body_owner(self, hir_id: HirId) -> bool { - match self.associated_body() { - Some(b) => b.hir_id == hir_id, - None => false, - } +fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { + match associated_body(node) { + Some(b) => b.hir_id == hir_id, + None => false, } } @@ -455,7 +453,7 @@ impl<'hir> Map<'hir> { /// item (possibly associated), a closure, or a `hir::AnonConst`. pub fn body_owner(&self, BodyId { hir_id }: BodyId) -> HirId { let parent = self.get_parent_node(hir_id); - assert!(self.lookup(parent).map_or(false, |e| e.is_body_owner(hir_id))); + assert!(self.find(parent).map_or(false, |n| is_body_owner(n, hir_id))); parent } @@ -466,14 +464,8 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(entry) = self.find_entry(hir_id) { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); - } - - entry.associated_body() + if let Some(node) = self.find(hir_id) { + associated_body(node) } else { bug!("no entry for id `{}`", hir_id) } From 38e613c4eb165f778fa8bb12107141d34a4c0621 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 16:43:36 +0100 Subject: [PATCH 1115/1250] Update `krate_attrs` and `get_module` --- src/librustc/hir/map/collector.rs | 10 ++-- src/librustc/hir/map/mod.rs | 50 ++++++++++++------- src/librustc_ast_lowering/lib.rs | 4 +- src/librustc_codegen_ssa/back/write.rs | 4 +- src/librustc_hir/hir.rs | 14 ++++-- src/librustc_hir/intravisit.rs | 4 +- src/librustc_hir/print.rs | 4 +- src/librustc_incremental/assert_dep_graph.rs | 2 +- .../assert_module_sources.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/late.rs | 2 +- src/librustc_lint/levels.rs | 2 +- src/librustc_metadata/link_args.rs | 2 +- src/librustc_metadata/rmeta/encoder.rs | 2 +- src/librustc_passes/entry.rs | 4 +- src/librustc_passes/stability.rs | 6 +-- .../traits/error_reporting/suggestions.rs | 2 +- src/librustdoc/clean/mod.rs | 2 + src/librustdoc/test.rs | 3 +- src/librustdoc/visit_ast.rs | 6 +-- 20 files changed, 72 insertions(+), 55 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 0ac8f403cb7..7e626f79c0c 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -133,11 +133,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // Allocate `DepNode`s for the root module. let (root_mod_sig_dep_index, root_mod_full_dep_index) = { let Crate { - ref module, - // Crate attributes are not copied over to the root `Mod`, so hash - // them explicitly here. - ref attrs, - span, + ref item, // These fields are handled separately: exported_macros: _, non_exported_macro_attrs: _, @@ -155,7 +151,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { dep_graph, &mut hcx, root_mod_def_path_hash, - (module, attrs, span), + item, &mut hir_body_nodes, ) }; @@ -191,7 +187,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { Entry { parent: hir::CRATE_HIR_ID, dep_node: root_mod_sig_dep_index, - node: Node::Crate, + node: Node::Crate(&krate.item), }, ); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 38260eac890..106475e5e13 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -13,7 +13,7 @@ use rustc_ast::ast::{self, Name, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, DefIndex, LocalDefId}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; @@ -41,7 +41,7 @@ pub struct Entry<'hir> { impl<'hir> Entry<'hir> { fn parent_node(self) -> Option { match self.node { - Node::Crate | Node::MacroDef(_) => None, + Node::Crate(_) | Node::MacroDef(_) => None, _ => Some(self.parent), } } @@ -389,7 +389,7 @@ impl<'hir> Map<'hir> { | Node::Lifetime(_) | Node::Visibility(_) | Node::Block(_) - | Node::Crate => return None, + | Node::Crate(_) => return None, Node::MacroDef(_) => DefKind::Macro(MacroKind::Bang), Node::GenericParam(param) => match param.kind { GenericParamKind::Lifetime { .. } => return None, @@ -403,6 +403,21 @@ impl<'hir> Map<'hir> { self.lookup(id).cloned() } + fn get_entry(&self, id: HirId) -> Entry<'hir> { + if id.local_id == ItemLocalId::from_u32_const(0) { + let owner = self.tcx.hir_owner(id.owner_def_id()); + Entry { parent: owner.parent, node: owner.node, dep_node: DepNodeIndex::INVALID } + } else { + let owner = self.tcx.hir_owner_items(id.owner_def_id()); + let item = owner.items[id.local_id].as_ref().unwrap(); + Entry { + parent: HirId { owner: id.owner, local_id: item.parent }, + node: item.node, + dep_node: DepNodeIndex::INVALID, + } + } + } + pub fn item(&self, id: HirId) -> &'hir Item<'hir> { match self.find(id).unwrap() { Node::Item(item) => item, @@ -528,18 +543,17 @@ impl<'hir> Map<'hir> { /// invoking `krate.attrs` because it registers a tighter /// dep-graph access. pub fn krate_attrs(&self) -> &'hir [ast::Attribute] { - let def_path_hash = self.definitions.def_path_hash(CRATE_DEF_INDEX); - - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::Hir)); - &self.krate.attrs + match self.get_entry(CRATE_HIR_ID).node { + Node::Crate(item) => item.attrs, + _ => bug!(), + } } pub fn get_module(&self, module: DefId) -> (&'hir Mod<'hir>, Span, HirId) { let hir_id = self.as_local_hir_id(module).unwrap(); - self.read(hir_id); - match self.find_entry(hir_id).unwrap().node { + match self.get_entry(hir_id).node { Node::Item(&Item { span, kind: ItemKind::Mod(ref m), .. }) => (m, span, hir_id), - Node::Crate => (&self.krate.module, self.krate.span, hir_id), + Node::Crate(item) => (&item.module, item.span, hir_id), node => panic!("not a module: {:?}", node), } } @@ -602,9 +616,9 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self - .find_entry(hir_id) - .and_then(|entry| if let Node::Crate = entry.node { None } else { Some(entry.node) }); + let result = self.find_entry(hir_id).and_then(|entry| { + if let Node::Crate(..) = entry.node { None } else { Some(entry.node) } + }); if result.is_some() { self.read(hir_id); } @@ -675,7 +689,7 @@ impl<'hir> Map<'hir> { pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { match self.lookup(hir_id) { Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) - | Some(Entry { node: Node::Crate, .. }) => true, + | Some(Entry { node: Node::Crate(..), .. }) => true, _ => false, } } @@ -752,7 +766,7 @@ impl<'hir> Map<'hir> { pub fn get_parent_item(&self, hir_id: HirId) -> HirId { for (hir_id, node) in self.parent_iter(hir_id) { match node { - Node::Crate + Node::Crate(_) | Node::Item(_) | Node::ForeignItem(_) | Node::TraitItem(_) @@ -973,7 +987,7 @@ impl<'hir> Map<'hir> { // Unit/tuple structs/variants take the attributes straight from // the struct/variant definition. Some(Node::Ctor(..)) => return self.attrs(self.get_parent_item(id)), - Some(Node::Crate) => Some(&self.krate.attrs[..]), + Some(Node::Crate(item)) => Some(&item.attrs[..]), _ => None, }; attrs.unwrap_or(&[]) @@ -1013,7 +1027,7 @@ impl<'hir> Map<'hir> { Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v), Some(Node::Local(local)) => local.span, Some(Node::MacroDef(macro_def)) => macro_def.span, - Some(Node::Crate) => self.krate.span, + Some(Node::Crate(item)) => item.span, None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id), } } @@ -1255,7 +1269,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { Some(Node::GenericParam(ref param)) => format!("generic_param {:?}{}", param, id_str), Some(Node::Visibility(ref vis)) => format!("visibility {:?}{}", vis, id_str), Some(Node::MacroDef(_)) => format!("macro {}{}", path_str(), id_str), - Some(Node::Crate) => String::from("root_crate"), + Some(Node::Crate(..)) => String::from("root_crate"), None => format!("unknown node{}", id_str), } } diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index dd9526ccee4..748b9b7fb40 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -535,9 +535,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.resolver.definitions().init_node_id_to_hir_id_mapping(self.node_id_to_hir_id); hir::Crate { - module, - attrs, - span: c.span, + item: hir::CrateItem { module, attrs, span: c.span }, exported_macros: self.arena.alloc_from_iter(self.exported_macros), non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs), items: self.items, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 3afa4758253..dbc2ef6f2b0 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -341,9 +341,9 @@ pub fn start_async_codegen( let crate_name = tcx.crate_name(LOCAL_CRATE); let crate_hash = tcx.crate_hash(LOCAL_CRATE); - let no_builtins = attr::contains_name(&tcx.hir().krate().attrs, sym::no_builtins); + let no_builtins = attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_builtins); let subsystem = - attr::first_attr_value_str_by_name(&tcx.hir().krate().attrs, sym::windows_subsystem); + attr::first_attr_value_str_by_name(&tcx.hir().krate().item.attrs, sym::windows_subsystem); let windows_subsystem = subsystem.map(|subsystem| { if subsystem != sym::windows && subsystem != sym::console { tcx.sess.fatal(&format!( diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index ed06aeb60bb..65bb4b9a6a1 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -606,6 +606,14 @@ pub struct ModuleItems { pub impl_items: BTreeSet, } +/// A type representing only the top-level module. +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] +pub struct CrateItem<'hir> { + pub module: Mod<'hir>, + pub attrs: &'hir [Attribute], + pub span: Span, +} + /// The top-level data structure that stores the entire contents of /// the crate currently being compiled. /// @@ -614,9 +622,7 @@ pub struct ModuleItems { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(RustcEncodable, RustcDecodable, Debug)] pub struct Crate<'hir> { - pub module: Mod<'hir>, - pub attrs: &'hir [Attribute], - pub span: Span, + pub item: CrateItem<'hir>, pub exported_macros: &'hir [MacroDef<'hir>], // Attributes from non-exported macros, kept only for collecting the library feature list. pub non_exported_macro_attrs: &'hir [Attribute], @@ -2683,7 +2689,7 @@ pub enum Node<'hir> { GenericParam(&'hir GenericParam<'hir>), Visibility(&'hir Visibility<'hir>), - Crate, + Crate(&'hir CrateItem<'hir>), } impl Node<'_> { diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index f8bd40d380d..5f31ddeae95 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -438,8 +438,8 @@ pub trait Visitor<'v>: Sized { /// Walks the contents of a crate. See also `Crate::visit_all_items`. pub fn walk_crate<'v, V: Visitor<'v>>(visitor: &mut V, krate: &'v Crate<'v>) { - visitor.visit_mod(&krate.module, krate.span, CRATE_HIR_ID); - walk_list!(visitor, visit_attribute, krate.attrs); + visitor.visit_mod(&krate.item.module, krate.item.span, CRATE_HIR_ID); + walk_list!(visitor, visit_attribute, krate.item.attrs); walk_list!(visitor, visit_macro_def, krate.exported_macros); } diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 7eb5cc417b7..1a2c3a38565 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -102,7 +102,7 @@ impl<'a> State<'a> { Node::Ctor(..) => panic!("cannot print isolated Ctor"), Node::Local(a) => self.print_local_decl(&a), Node::MacroDef(_) => panic!("cannot print MacroDef"), - Node::Crate => panic!("cannot print Crate"), + Node::Crate(..) => panic!("cannot print Crate"), } } } @@ -151,7 +151,7 @@ pub fn print_crate<'a>( // When printing the AST, we sometimes need to inject `#[no_std]` here. // Since you can't compile the HIR, it's not necessary. - s.print_mod(&krate.module, &krate.attrs); + s.print_mod(&krate.item.module, &krate.item.attrs); s.print_remaining_comments(); s.s.eof() } diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index c2b62f9670c..5f186f0e1b2 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -68,7 +68,7 @@ pub fn assert_dep_graph(tcx: TyCtxt<'_>) { let (if_this_changed, then_this_would_need) = { let mut visitor = IfThisChanged { tcx, if_this_changed: vec![], then_this_would_need: vec![] }; - visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().attrs); + visitor.process_attrs(hir::CRATE_HIR_ID, &tcx.hir().krate().item.attrs); tcx.hir().krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); (visitor.if_this_changed, visitor.then_this_would_need) }; diff --git a/src/librustc_incremental/assert_module_sources.rs b/src/librustc_incremental/assert_module_sources.rs index 261540abcad..54d7e0ece50 100644 --- a/src/librustc_incremental/assert_module_sources.rs +++ b/src/librustc_incremental/assert_module_sources.rs @@ -44,7 +44,7 @@ pub fn assert_module_sources(tcx: TyCtxt<'_>) { let ams = AssertModuleSource { tcx, available_cgus }; - for attr in tcx.hir().krate().attrs { + for attr in tcx.hir().krate().item.attrs { ams.check_attr(attr); } }) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 50c2c6f9552..852998c9e7d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -399,7 +399,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { } fn check_crate(&mut self, cx: &LateContext<'_, '_>, krate: &hir::Crate<'_>) { - self.check_missing_docs_attrs(cx, None, &krate.attrs, krate.span, "crate"); + self.check_missing_docs_attrs(cx, None, &krate.item.attrs, krate.item.span, "crate"); for macro_def in krate.exported_macros { let has_doc = macro_def.attrs.iter().any(|a| has_doc(a)); diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 0964dfa2899..839057a75a6 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -419,7 +419,7 @@ fn late_lint_pass_crate<'tcx, T: for<'a> LateLintPass<'a, 'tcx>>(tcx: TyCtxt<'tc let mut cx = LateContextAndPass { context, pass }; // Visit the whole crate. - cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.attrs, |cx| { + cx.with_lint_attrs(hir::CRATE_HIR_ID, &krate.item.attrs, |cx| { // since the root module isn't visited as an item (because it isn't an // item), warn for it here. lint_callback!(cx, check_crate, krate); diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 0e85b8d2a39..6fddf1535c9 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -29,7 +29,7 @@ fn lint_levels(tcx: TyCtxt<'_>, cnum: CrateNum) -> &LintLevelMap { let mut builder = LintLevelMapBuilder { levels, tcx, store }; let krate = tcx.hir().krate(); - let push = builder.levels.push(&krate.attrs, &store); + let push = builder.levels.push(&krate.item.attrs, &store); builder.levels.register_id(hir::CRATE_HIR_ID); for macro_def in krate.exported_macros { builder.levels.register_id(macro_def.hir_id); diff --git a/src/librustc_metadata/link_args.rs b/src/librustc_metadata/link_args.rs index 8d018b9bb94..13668b2423f 100644 --- a/src/librustc_metadata/link_args.rs +++ b/src/librustc_metadata/link_args.rs @@ -8,7 +8,7 @@ crate fn collect(tcx: TyCtxt<'_>) -> Vec { let mut collector = Collector { args: Vec::new() }; tcx.hir().krate().visit_all_item_likes(&mut collector); - for attr in tcx.hir().krate().attrs.iter() { + for attr in tcx.hir().krate().item.attrs.iter() { if attr.has_name(sym::link_args) { if let Some(linkarg) = attr.value_str() { collector.add_link_args(&linkarg.as_str()); diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ce62f15f85d..e69b4fd6195 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -331,7 +331,7 @@ impl<'tcx> EncodeContext<'tcx> { fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.item.module, &krate.item.attrs, &vis); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in krate.exported_macros { self.visit_macro_def(macro_def); diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index 86596e20556..c29c552202a 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -59,7 +59,7 @@ fn entry_fn(tcx: TyCtxt<'_>, cnum: CrateNum) -> Option<(DefId, EntryFnType)> { } // If the user wants no main function at all, then stop here. - if attr::contains_name(&tcx.hir().krate().attrs, sym::no_main) { + if attr::contains_name(&tcx.hir().krate().item.attrs, sym::no_main) { return None; } @@ -157,7 +157,7 @@ fn configure_main(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) -> Option<(De } fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_, '_>) { - let sp = tcx.hir().krate().span; + let sp = tcx.hir().krate().item.span; if *tcx.sess.parse_sess.reached_eof.borrow() { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index d056d9f0562..84ba245998c 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -459,8 +459,8 @@ fn new_index(tcx: TyCtxt<'tcx>) -> Index<'tcx> { annotator.annotate( hir::CRATE_HIR_ID, - &krate.attrs, - krate.span, + &krate.item.attrs, + krate.item.span, AnnotationKind::Required, |v| intravisit::walk_crate(v, krate), ); @@ -585,7 +585,7 @@ pub fn check_unused_or_stable_features(tcx: TyCtxt<'_>) { if tcx.stability().staged_api[&LOCAL_CRATE] { let krate = tcx.hir().krate(); let mut missing = MissingStabilityAnnotations { tcx, access_levels }; - missing.check_missing_stability(hir::CRATE_HIR_ID, krate.span, "crate"); + missing.check_missing_stability(hir::CRATE_HIR_ID, krate.item.span, "crate"); intravisit::walk_crate(&mut missing, krate); krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 351e557d40b..0e0cb8ccb0c 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -282,7 +282,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } } - hir::Node::Crate => return, + hir::Node::Crate(..) => return, _ => {} } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 661666b6637..e2fca8f39a3 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -141,6 +141,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() @@ -194,6 +195,7 @@ impl Clean for CrateNum { cx.tcx .hir() .krate() + .item .module .item_ids .iter() diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index b63dbbf80d8..85ccb55333b 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -112,7 +112,7 @@ pub fn run(options: Options) -> i32 { compiler.session().opts.unstable_features.is_nightly_build(), ), }; - hir_collector.visit_testable("".to_string(), &krate.attrs, |this| { + hir_collector.visit_testable("".to_string(), &krate.item.attrs, |this| { intravisit::walk_crate(this, krate); }); }); @@ -146,6 +146,7 @@ fn scrape_test_config(krate: &::rustc_hir::Crate) -> TestOptions { TestOptions { no_crate_inject: false, display_warnings: false, attrs: Vec::new() }; let test_attrs: Vec<_> = krate + .item .attrs .iter() .filter(|a| a.check_name(sym::doc)) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 8f2f88d08bf..6e34f731e3b 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -64,11 +64,11 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { pub fn visit(mut self, krate: &'tcx hir::Crate) -> Module<'tcx> { let mut module = self.visit_mod_contents( - krate.span, - krate.attrs, + krate.item.span, + krate.item.attrs, &Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, - &krate.module, + &krate.item.module, None, ); // Attach the crate's exported macros to the top-level module: From b40e6baec7504ebc7c681259d268c81b1e0241b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 18:25:36 +0100 Subject: [PATCH 1116/1250] Update `visit_item_likes_in_module` --- src/librustc/dep_graph/dep_node.rs | 12 ++----- src/librustc/hir/map/collector.rs | 4 +-- src/librustc/hir/map/definitions.rs | 26 ++------------- src/librustc/hir/map/mod.rs | 12 ++----- src/librustc/hir/mod.rs | 6 ++++ src/librustc/ich/hcx.rs | 15 +-------- src/librustc/ich/impls_hir.rs | 7 +++- src/librustc/query/mod.rs | 4 +++ src/librustc_hir/hir.rs | 2 +- src/librustc_hir/stable_hash_impls.rs | 34 ++++++++++++++++++-- src/librustc_incremental/assert_dep_graph.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 5 +-- src/librustc_span/def_id.rs | 25 ++++++++++++++ 13 files changed, 88 insertions(+), 66 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 03218920ef1..755bc15ba93 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -223,8 +223,8 @@ macro_rules! define_dep_nodes { /// Construct a DepNode from the given DepKind and DefPathHash. This /// method will assert that the given DepKind actually requires a /// single DefId/DefPathHash parameter. - pub fn from_def_path_hash(kind: DepKind, - def_path_hash: DefPathHash) + pub fn from_def_path_hash(def_path_hash: DefPathHash, + kind: DepKind) -> DepNode { debug_assert!(kind.can_reconstruct_query_key() && kind.has_params()); DepNode { @@ -280,7 +280,7 @@ macro_rules! define_dep_nodes { } if kind.has_params() { - Ok(def_path_hash.to_dep_node(kind)) + Ok(DepNode::from_def_path_hash(def_path_hash, kind)) } else { Ok(DepNode::new_no_params(kind)) } @@ -337,12 +337,6 @@ impl fmt::Debug for DepNode { } } -impl DefPathHash { - pub fn to_dep_node(self, kind: DepKind) -> DepNode { - DepNode::from_def_path_hash(kind, self) - } -} - rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 7e626f79c0c..231d0ee4821 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -86,7 +86,7 @@ fn alloc_hir_dep_nodes( ) -> (DepNodeIndex, DepNodeIndex) { let sig = dep_graph .input_task( - def_path_hash.to_dep_node(DepKind::Hir), + DepNode::from_def_path_hash(def_path_hash, DepKind::Hir), &mut *hcx, HirItemLike { item_like: &item_like, hash_bodies: false }, ) @@ -94,7 +94,7 @@ fn alloc_hir_dep_nodes( let (full, hash) = input_dep_node_and_hash( dep_graph, hcx, - def_path_hash.to_dep_node(DepKind::HirBody), + DepNode::from_def_path_hash(def_path_hash, DepKind::HirBody), HirItemLike { item_like: &item_like, hash_bodies: true }, ); hir_body_nodes.push((def_path_hash, hash)); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index e1b5ec041db..50117f73d48 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -6,7 +6,6 @@ use rustc_ast::ast; use rustc_ast::node_id::NodeMap; -use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_hir as hir; @@ -17,10 +16,11 @@ use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; -use std::borrow::Borrow; use std::fmt::Write; use std::hash::Hash; +pub use rustc_hir::def_id::DefPathHash; + /// The `DefPathTable` maps `DefIndex`es to `DefKey`s and vice versa. /// Internally the `DefPathTable` holds a tree of `DefKey`s, where each `DefKey` /// stores the `DefIndex` of its parent. @@ -282,28 +282,6 @@ pub enum DefPathData { ImplTrait, } -#[derive( - Copy, - Clone, - Hash, - PartialEq, - Eq, - PartialOrd, - Ord, - Debug, - RustcEncodable, - RustcDecodable, - HashStable -)] -pub struct DefPathHash(pub Fingerprint); - -impl Borrow for DefPathHash { - #[inline] - fn borrow(&self) -> &Fingerprint { - &self.0 - } -} - impl Definitions { pub fn def_path_table(&self) -> &DefPathTable { &self.table diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 106475e5e13..f7990ca0149 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -562,15 +562,7 @@ impl<'hir> Map<'hir> { where V: ItemLikeVisitor<'hir>, { - let hir_id = self.as_local_hir_id(module).unwrap(); - - // Read the module so we'll be re-executed if new items - // appear immediately under in the module. If some new item appears - // in some nested item in the module, we'll be re-executed due to reads - // in the expect_* calls the loops below - self.read(hir_id); - - let module = &self.krate.modules[&hir_id]; + let module = self.tcx.hir_module_items(module); for id in &module.items { visitor.visit_item(self.expect_item(*id)); @@ -639,7 +631,7 @@ impl<'hir> Map<'hir> { if self.dep_graph.is_fully_enabled() { let hir_id_owner = hir_id.owner; let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(def_path_hash.to_dep_node(DepKind::HirBody)); + self.dep_graph.read(DepNode::from_def_path_hash(def_path_hash, DepKind::HirBody)); } self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index d7999ee5f51..f113efa6300 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -114,6 +114,12 @@ pub fn provide(providers: &mut Providers<'_>) { hir_to_node_id: early.hir_to_node_id, }) }; + providers.hir_module_items = |tcx, id| { + assert_eq!(id.krate, LOCAL_CRATE); + let hir = tcx.hir(); + let module = hir.as_local_hir_id(id).unwrap(); + &hir.untracked_krate().modules[&module] + }; providers.hir_owner = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); *tcx.hir().map.owner_map.get(&id.index).unwrap() diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 5a49d9a1f1a..c15d54745a1 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -7,7 +7,7 @@ use crate::ty::{fast_reject, TyCtxt}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex}; @@ -197,19 +197,6 @@ impl<'a> StableHashingContextProvider<'a> for StableHashingContext<'a> { impl<'a> crate::dep_graph::DepGraphSafe for StableHashingContext<'a> {} -impl<'a> ToStableHashKey> for hir::HirId { - type KeyType = (DefPathHash, hir::ItemLocalId); - - #[inline] - fn to_stable_hash_key( - &self, - hcx: &StableHashingContext<'a>, - ) -> (DefPathHash, hir::ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner); - (def_path_hash, self.local_id) - } -} - impl<'a> HashStable> for ast::NodeId { fn hash_stable(&self, _: &mut StableHashingContext<'a>, _: &mut StableHasher) { panic!("Node IDs should not appear in incremental state"); diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 1015ffdbf28..06bfd782b59 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -6,7 +6,7 @@ use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; use rustc_attr as attr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; use smallvec::SmallVec; use std::mem; @@ -114,6 +114,11 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { self.node_id_hashing_mode = prev_hash_node_ids; } + + #[inline] + fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { + self.local_def_path_hash(def_index) + } } impl<'a> ToStableHashKey> for DefId { diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index b843bc17d2c..2a8e34ddc25 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -61,6 +61,10 @@ rustc_queries! { desc { "index HIR" } } + query hir_module_items(key: DefId) -> &'tcx hir::ModuleItems { + eval_always + } + query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { eval_always } diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 65bb4b9a6a1..88cc8639331 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -597,7 +597,7 @@ pub struct WhereEqPredicate<'hir> { pub rhs_ty: &'hir Ty<'hir>, } -#[derive(RustcEncodable, RustcDecodable, Debug)] +#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] pub struct ModuleItems { // Use BTreeSets here so items are in the same order as in the // list of all items in Crate diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index 9756edc3f4d..7ca2bfded3c 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -1,10 +1,11 @@ -use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use crate::hir::{ BodyId, Expr, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem, TraitItemId, Ty, VisibilityKind, }; -use crate::hir_id::HirId; +use crate::hir_id::{HirId, ItemLocalId}; +use rustc_span::def_id::{DefIndex, DefPathHash}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro @@ -20,6 +21,35 @@ pub trait HashStableContext: fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); fn hash_hir_item_like(&mut self, f: F); + fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash; +} + +impl ToStableHashKey for HirId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + let def_path_hash = hcx.local_def_path_hash(self.owner); + (def_path_hash, self.local_id) + } +} + +impl ToStableHashKey for TraitItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } +} + +impl ToStableHashKey for ImplItemId { + type KeyType = (DefPathHash, ItemLocalId); + + #[inline] + fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { + self.hir_id.to_stable_hash_key(hcx) + } } impl HashStable for HirId { diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 5f186f0e1b2..7686a507ff5 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> { if attr.check_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => def_path_hash.to_dep_node(DepKind::Hir), + None => DepNode::from_def_path_hash(def_path_hash, DepKind::Hir), Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 1d8eb0cde46..7126f86c326 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -4,7 +4,7 @@ use crate::creader::CrateMetadataRef; use crate::rmeta::table::{FixedSizeEncoding, Table}; use crate::rmeta::*; -use rustc::dep_graph::{self, DepNodeIndex}; +use rustc::dep_graph::{self, DepNode, DepNodeIndex}; use rustc::hir::exports::Export; use rustc::hir::map::definitions::DefPathTable; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; @@ -1607,7 +1607,8 @@ impl CrateMetadata { // would always write the same value. let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX); - let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata); + let dep_node = + DepNode::from_def_path_hash(def_path_hash, dep_graph::DepKind::CrateMetadata); dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node); assert!(dep_node_index != DepNodeIndex::INVALID); diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 66cdf46bd4e..a2944782e91 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -1,8 +1,11 @@ use crate::HashStableContext; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::AtomicRef; use rustc_index::vec::Idx; +use rustc_macros::HashStable_Generic; use rustc_serialize::{Decoder, Encoder}; +use std::borrow::Borrow; use std::fmt; use std::{u32, u64}; @@ -102,6 +105,28 @@ impl ::std::fmt::Debug for CrateNum { } } +#[derive( + Copy, + Clone, + Hash, + PartialEq, + Eq, + PartialOrd, + Ord, + Debug, + RustcEncodable, + RustcDecodable, + HashStable_Generic +)] +pub struct DefPathHash(pub Fingerprint); + +impl Borrow for DefPathHash { + #[inline] + fn borrow(&self) -> &Fingerprint { + &self.0 + } +} + rustc_index::newtype_index! { /// A DefIndex is an index into the hir-map for a crate, identifying a /// particular definition. It should really be considered an interned From d5827d8bc1fd18883ad7f7a220490d12f60ae704 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 18:46:21 +0100 Subject: [PATCH 1117/1250] Update `get_parent_node` --- src/librustc/hir/map/mod.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f7990ca0149..23a80eb6b7d 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -579,12 +579,11 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, panicking if it cannot be found. pub fn get(&self, id: HirId) -> Node<'hir> { - // read recorded by `find` self.find(id).unwrap_or_else(|| bug!("couldn't find hir id {} in the HIR map", id)) } pub fn get_if_local(&self, id: DefId) -> Option> { - self.as_local_hir_id(id).map(|id| self.get(id)) // read recorded by `get` + self.as_local_hir_id(id).map(|id| self.get(id)) } pub fn get_generics(&self, id: DefId) -> Option<&'hir Generics<'hir>> { @@ -628,13 +627,7 @@ impl<'hir> Map<'hir> { /// from a node to the root of the HIR (unless you get back the same ID here, /// which can happen if the ID is not in the map itself or is just weird). pub fn get_parent_node(&self, hir_id: HirId) -> HirId { - if self.dep_graph.is_fully_enabled() { - let hir_id_owner = hir_id.owner; - let def_path_hash = self.definitions.def_path_hash(hir_id_owner); - self.dep_graph.read(DepNode::from_def_path_hash(def_path_hash, DepKind::HirBody)); - } - - self.find_entry(hir_id).and_then(|x| x.parent_node()).unwrap_or(hir_id) + self.get_entry(hir_id).parent_node().unwrap_or(hir_id) } /// Returns an iterator for the nodes in the ancestor tree of the `current_id` From 9c4308ed9296b4023b627337c81d55c4532d11c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 19:01:27 +0100 Subject: [PATCH 1118/1250] Update `find` --- src/librustc/hir/map/mod.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 23a80eb6b7d..c98a919d0f5 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -607,13 +607,8 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { - let result = self.find_entry(hir_id).and_then(|entry| { - if let Node::Crate(..) = entry.node { None } else { Some(entry.node) } - }); - if result.is_some() { - self.read(hir_id); - } - result + let node = self.get_entry(hir_id).node; + if let Node::Crate(..) = node { None } else { Some(node) } } /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there From 21942a5cf6f75be68bcef22bd830e6379ede7df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 19:09:19 +0100 Subject: [PATCH 1119/1250] Update `is_hir_id_module` --- src/librustc/hir/map/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index c98a919d0f5..9d88e78afa7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -667,9 +667,9 @@ impl<'hir> Map<'hir> { /// Whether `hir_id` corresponds to a `mod` or a crate. pub fn is_hir_id_module(&self, hir_id: HirId) -> bool { - match self.lookup(hir_id) { - Some(Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. }) - | Some(Entry { node: Node::Crate(..), .. }) => true, + match self.get_entry(hir_id) { + Entry { node: Node::Item(Item { kind: ItemKind::Mod(_), .. }), .. } + | Entry { node: Node::Crate(..), .. } => true, _ => false, } } From 61527c8d8c7d301e37d241c6dfa7e5c281e9a5b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 7 Feb 2020 19:17:48 +0100 Subject: [PATCH 1120/1250] Update `find_entry` --- src/librustc/hir/map/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 9d88e78afa7..52bdc6a1475 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -400,7 +400,7 @@ impl<'hir> Map<'hir> { } fn find_entry(&self, id: HirId) -> Option> { - self.lookup(id).cloned() + Some(self.get_entry(id)) } fn get_entry(&self, id: HirId) -> Entry<'hir> { From 270ee7eca39188ba7adc7af19a26d4aca3cc186b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 03:30:57 +0100 Subject: [PATCH 1121/1250] Remove comments --- src/librustc/hir/map/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 52bdc6a1475..f9b9c7a3cfe 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -859,7 +859,6 @@ impl<'hir> Map<'hir> { node: Node::Item(Item { kind: ItemKind::ForeignMod(ref nm), .. }), .. } = entry { - self.read(hir_id); // reveals some of the content of a node return nm.abi; } } @@ -868,7 +867,6 @@ impl<'hir> Map<'hir> { pub fn expect_item(&self, id: HirId) -> &'hir Item<'hir> { match self.find(id) { - // read recorded by `find` Some(Node::Item(item)) => item, _ => bug!("expected item, found {}", self.node_to_string(id)), } @@ -918,7 +916,6 @@ impl<'hir> Map<'hir> { pub fn expect_expr(&self, id: HirId) -> &'hir Expr<'hir> { match self.find(id) { - // read recorded by find Some(Node::Expr(expr)) => expr, _ => bug!("expected expr, found {}", self.node_to_string(id)), } From 072449c0dc9bd435f002fa7fb531d6819033229e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 04:14:29 +0100 Subject: [PATCH 1122/1250] Update `trait_impls` --- src/librustc/hir/map/mod.rs | 10 +++------- src/librustc/query/mod.rs | 3 +++ src/librustc/ty/mod.rs | 7 +++++-- src/librustc/ty/query/mod.rs | 1 + src/librustc/ty/trait_def.rs | 12 +++++++++++- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index f9b9c7a3cfe..1a816e6b2cb 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -4,7 +4,7 @@ pub use self::definitions::{ }; use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; +use crate::dep_graph::{DepGraph, DepNodeIndex}; use crate::hir::{HirOwner, HirOwnerItems}; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; @@ -13,7 +13,7 @@ use rustc_ast::ast::{self, Name, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIndex, LocalDefId}; +use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; @@ -532,11 +532,7 @@ impl<'hir> Map<'hir> { } pub fn trait_impls(&self, trait_did: DefId) -> &'hir [HirId] { - self.dep_graph.read(DepNode::new_no_params(DepKind::AllLocalTraitImpls)); - - // N.B., intentionally bypass `self.krate()` so that we - // do not trigger a read of the whole krate here - self.krate.trait_impls.get(&trait_did).map_or(&[], |xs| &xs[..]) + self.tcx.all_local_trait_impls(LOCAL_CRATE).get(&trait_did).map_or(&[], |xs| &xs[..]) } /// Gets the attributes on the crate. This is preferable to diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 2a8e34ddc25..5dafa462ca8 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -671,6 +671,9 @@ rustc_queries! { } TypeChecking { + query all_local_trait_impls(key: CrateNum) -> &'tcx BTreeMap> { + desc { "local trait impls" } + } query trait_impls_of(key: DefId) -> &'tcx ty::trait_def::TraitImpls { desc { |tcx| "trait impls of `{}`", tcx.def_path_str(key) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c2697570dda..d3c4ddf1ed3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3142,8 +3142,11 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { context::provide(providers); erase_regions::provide(providers); layout::provide(providers); - *providers = - ty::query::Providers { trait_impls_of: trait_def::trait_impls_of_provider, ..*providers }; + *providers = ty::query::Providers { + trait_impls_of: trait_def::trait_impls_of_provider, + all_local_trait_impls: trait_def::all_local_trait_impls, + ..*providers + }; } /// A map for the local crate mapping each type to a vector of its diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index b6976221ef7..3dbcf9228d2 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -56,6 +56,7 @@ use rustc_attr as attr; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; use std::borrow::Cow; +use std::collections::BTreeMap; use std::convert::TryFrom; use std::ops::Deref; use std::sync::Arc; diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 0cf1c397648..91a99ec43e6 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -5,11 +5,13 @@ use crate::ty::fast_reject; use crate::ty::fold::TypeFoldable; use crate::ty::{Ty, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{CrateNum, DefId}; +use rustc_hir::HirId; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_macros::HashStable; +use std::collections::BTreeMap; /// A trait's definition with type information. #[derive(HashStable)] @@ -146,6 +148,14 @@ impl<'tcx> TyCtxt<'tcx> { } } +// Query provider for `all_local_trait_impls`. +pub(super) fn all_local_trait_impls<'tcx>( + tcx: TyCtxt<'tcx>, + krate: CrateNum, +) -> &'tcx BTreeMap> { + &tcx.hir_crate(krate).trait_impls +} + // Query provider for `trait_impls_of`. pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> &TraitImpls { let mut impls = TraitImpls::default(); From d99b17fa6478e1c7d55c95938e90467ae0e2ab2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 04:24:42 +0100 Subject: [PATCH 1123/1250] Remove the `map` field from `Map` --- src/librustc/hir/map/mod.rs | 25 ------------------------- src/librustc/hir/mod.rs | 2 -- 2 files changed, 27 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 1a816e6b2cb..7604aeb8766 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -172,8 +172,6 @@ pub struct Map<'hir> { pub(super) owner_map: FxHashMap>, pub(super) owner_items_map: FxHashMap>, - pub(super) map: HirEntryMap<'hir>, - pub(super) definitions: &'hir Definitions, /// The reverse mapping of `node_to_hir_id`. @@ -220,27 +218,6 @@ impl<'hir> Map<'hir> { &self.krate } - #[inline] - fn lookup(&self, id: HirId) -> Option<&Entry<'hir>> { - let local_map = self.map.get(id.owner)?; - local_map.get(id.local_id)?.as_ref() - } - - /// Registers a read in the dependency graph of the AST node with - /// the given `id`. This needs to be called each time a public - /// function returns the HIR for a node -- in other words, when it - /// "reveals" the content of a node to the caller (who might not - /// otherwise have had access to those contents, and hence needs a - /// read recorded). If the function just returns a DefId or - /// HirId, no actual content was returned, so no read is needed. - pub fn read(&self, hir_id: HirId) { - if let Some(entry) = self.lookup(hir_id) { - self.dep_graph.read_index(entry.dep_node); - } else { - bug!("called `HirMap::read()` with invalid `HirId`: {:?}", hir_id) - } - } - #[inline] pub fn definitions(&self) -> &Definitions { &self.definitions @@ -943,7 +920,6 @@ impl<'hir> Map<'hir> { /// Given a node ID, gets a list of attributes associated with the AST /// corresponding to the node-ID. pub fn attrs(&self, id: HirId) -> &'hir [ast::Attribute] { - self.read(id); // reveals attributes on the node let attrs = match self.find_entry(id).map(|entry| entry.node) { Some(Node::Param(a)) => Some(&a.attrs[..]), Some(Node::Local(l)) => Some(&l.attrs[..]), @@ -967,7 +943,6 @@ impl<'hir> Map<'hir> { } pub fn span(&self, hir_id: HirId) -> Span { - self.read(hir_id); // reveals span from node match self.find_entry(hir_id).map(|entry| entry.node) { Some(Node::Param(param)) => param.span, Some(Node::Item(item)) => item.span, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index f113efa6300..34cfff999a7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -107,8 +107,6 @@ pub fn provide(providers: &mut Providers<'_>) { owner_map: early.owner_map, owner_items_map: early.owner_items_map, - map: early.map, - definitions: early.definitions, hir_to_node_id: early.hir_to_node_id, From fa09db846832aa106264a449ae625e143b605319 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 04:26:12 +0100 Subject: [PATCH 1124/1250] Remove `AllLocalTraitImpls` --- src/librustc/dep_graph/dep_node.rs | 4 +--- src/librustc/hir/map/collector.rs | 8 -------- src/librustc/ty/query/mod.rs | 1 - 3 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 755bc15ba93..36b5f4de099 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -35,7 +35,7 @@ //! "infer" some properties for each kind of `DepNode`: //! //! * Whether a `DepNode` of a given kind has any parameters at all. Some -//! `DepNode`s, like `AllLocalTraitImpls`, represent global concepts with only one value. +//! `DepNode`s could represent global concepts with only one value. //! * Whether it is possible, in principle, to reconstruct a query key from a //! given `DepNode`. Many `DepKind`s only require a single `DefId` parameter, //! in which case it is possible to map the node's fingerprint back to the @@ -351,8 +351,6 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // Represents metadata from an extern crate. [eval_always] CrateMetadata(CrateNum), - [eval_always] AllLocalTraitImpls, - [anon] TraitSelect, [] CompileCodegenUnit(Symbol), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 231d0ee4821..5c2808fee0d 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -156,14 +156,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { ) }; - { - dep_graph.input_task( - DepNode::new_no_params(DepKind::AllLocalTraitImpls), - &mut hcx, - &krate.trait_impls, - ); - } - let mut collector = NodeCollector { arena, krate, diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 3dbcf9228d2..d1141a48990 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -179,7 +179,6 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool rustc_dep_node_force!([dep_node, tcx] // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already. - DepKind::AllLocalTraitImpls | DepKind::CrateMetadata | DepKind::HirBody | DepKind::Hir | From e9d166fac54dc3944e293121c732ff709acfd9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 05:18:34 +0100 Subject: [PATCH 1125/1250] Clean up the collector --- src/librustc/hir/map/collector.rs | 132 +++++------------------ src/librustc/hir/map/hir_id_validator.rs | 4 +- src/librustc/hir/map/mod.rs | 30 +----- src/librustc/hir/mod.rs | 2 - src/librustc/ty/context.rs | 2 +- src/librustc_interface/passes.rs | 3 +- 6 files changed, 34 insertions(+), 139 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 5c2808fee0d..b9ab43ed289 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,7 +1,6 @@ use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex}; use crate::hir::map::definitions::{self, DefPathHash}; -use crate::hir::map::{Entry, HirEntryMap, Map}; +use crate::hir::map::{Entry, Map}; use crate::hir::{HirItem, HirOwner, HirOwnerItems}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; @@ -35,70 +34,38 @@ pub(super) struct NodeCollector<'a, 'hir> { owner_map: FxHashMap>, owner_items_map: FxHashMap>, - /// The node map - map: HirEntryMap<'hir>, /// The parent of this node parent_node: hir::HirId, - // These fields keep track of the currently relevant DepNodes during - // the visitor's traversal. current_dep_node_owner: DefIndex, - current_signature_dep_index: DepNodeIndex, - current_full_dep_index: DepNodeIndex, - currently_in_body: bool, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, hir_to_node_id: &'a FxHashMap, hcx: StableHashingContext<'a>, // We are collecting `DepNode::HirBody` hashes here so we can compute the - // crate hash from then later on. + // crate hash from them later on. hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } -fn input_dep_node_and_hash( - dep_graph: &DepGraph, +fn hash( hcx: &mut StableHashingContext<'_>, - dep_node: DepNode, input: impl for<'a> HashStable>, -) -> (DepNodeIndex, Fingerprint) { - let dep_node_index = dep_graph.input_task(dep_node, &mut *hcx, &input).1; - - let hash = if dep_graph.is_fully_enabled() { - dep_graph.fingerprint_of(dep_node_index) - } else { - let mut stable_hasher = StableHasher::new(); - input.hash_stable(hcx, &mut stable_hasher); - stable_hasher.finish() - }; - - (dep_node_index, hash) +) -> Fingerprint { + let mut stable_hasher = StableHasher::new(); + input.hash_stable(hcx, &mut stable_hasher); + stable_hasher.finish() } -fn alloc_hir_dep_nodes( - dep_graph: &DepGraph, +fn hash_body( hcx: &mut StableHashingContext<'_>, def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, -) -> (DepNodeIndex, DepNodeIndex) { - let sig = dep_graph - .input_task( - DepNode::from_def_path_hash(def_path_hash, DepKind::Hir), - &mut *hcx, - HirItemLike { item_like: &item_like, hash_bodies: false }, - ) - .1; - let (full, hash) = input_dep_node_and_hash( - dep_graph, - hcx, - DepNode::from_def_path_hash(def_path_hash, DepKind::HirBody), - HirItemLike { item_like: &item_like, hash_bodies: true }, - ); +) { + let hash = hash(hcx, HirItemLike { item_like: &item_like }); hir_body_nodes.push((def_path_hash, hash)); - (sig, full) } fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { @@ -121,7 +88,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { sess: &'a Session, arena: &'hir Arena<'hir>, krate: &'hir Crate<'hir>, - dep_graph: &'a DepGraph, definitions: &'a definitions::Definitions, hir_to_node_id: &'a FxHashMap, mut hcx: StableHashingContext<'a>, @@ -130,8 +96,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let mut hir_body_nodes = Vec::new(); - // Allocate `DepNode`s for the root module. - let (root_mod_sig_dep_index, root_mod_full_dep_index) = { + { let Crate { ref item, // These fields are handled separately: @@ -147,40 +112,31 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { proc_macros: _, } = *krate; - alloc_hir_dep_nodes( - dep_graph, - &mut hcx, - root_mod_def_path_hash, - item, - &mut hir_body_nodes, - ) + hash_body(&mut hcx, root_mod_def_path_hash, item, &mut hir_body_nodes) }; let mut collector = NodeCollector { arena, krate, source_map: sess.source_map(), - map: IndexVec::from_elem_n(IndexVec::new(), definitions.def_index_count()), parent_node: hir::CRATE_HIR_ID, - current_signature_dep_index: root_mod_sig_dep_index, - current_full_dep_index: root_mod_full_dep_index, current_dep_node_owner: CRATE_DEF_INDEX, - currently_in_body: false, - dep_graph, definitions, hir_to_node_id, hcx, hir_body_nodes, - owner_map: FxHashMap::default(), - owner_items_map: FxHashMap::default(), + owner_map: FxHashMap::with_capacity_and_hasher( + definitions.def_index_count(), + Default::default(), + ), + owner_items_map: FxHashMap::with_capacity_and_hasher( + definitions.def_index_count(), + Default::default(), + ), }; collector.insert_entry( hir::CRATE_HIR_ID, - Entry { - parent: hir::CRATE_HIR_ID, - dep_node: root_mod_sig_dep_index, - node: Node::Crate(&krate.item), - }, + Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) }, ); collector @@ -192,7 +148,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { cstore: &dyn CrateStore, commandline_args_hash: u64, ) -> ( - HirEntryMap<'hir>, FxHashMap>, FxHashMap>, Svh, @@ -239,7 +194,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash: Fingerprint = stable_hasher.finish(); let svh = Svh::new(crate_hash.to_smaller_hash()); - (self.map, self.owner_map, self.owner_items_map, svh) + (self.owner_map, self.owner_items_map, svh) } fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { @@ -266,26 +221,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { items.items[id.local_id] = Some(HirItem { parent: entry.parent.local_id, node: entry.node }); } - - debug!("hir_map: {:?} => {:?}", id, entry); - let local_map = &mut self.map[id.owner]; - let len = local_map.len(); - if i >= len { - local_map.extend(repeat(None).take(i - len + 1)); - } - local_map[id.local_id] = Some(entry); } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { - let entry = Entry { - parent: self.parent_node, - dep_node: if self.currently_in_body { - self.current_full_dep_index - } else { - self.current_signature_dep_index - }, - node, - }; + let entry = Entry { parent: self.parent_node, node }; // Make sure that the DepNode of some node coincides with the HirId // owner of that node. @@ -340,29 +279,14 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { f: F, ) { let prev_owner = self.current_dep_node_owner; - let prev_signature_dep_index = self.current_signature_dep_index; - let prev_full_dep_index = self.current_full_dep_index; - let prev_in_body = self.currently_in_body; let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - let (signature_dep_index, full_dep_index) = alloc_hir_dep_nodes( - self.dep_graph, - &mut self.hcx, - def_path_hash, - item_like, - &mut self.hir_body_nodes, - ); - self.current_signature_dep_index = signature_dep_index; - self.current_full_dep_index = full_dep_index; + hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); self.current_dep_node_owner = dep_node_owner; - self.currently_in_body = false; f(self); - self.currently_in_body = prev_in_body; self.current_dep_node_owner = prev_owner; - self.current_full_dep_index = prev_full_dep_index; - self.current_signature_dep_index = prev_signature_dep_index; } } @@ -391,10 +315,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_nested_body(&mut self, id: BodyId) { - let prev_in_body = self.currently_in_body; - self.currently_in_body = true; self.visit_body(self.krate.body(id)); - self.currently_in_body = prev_in_body; } fn visit_param(&mut self, param: &'hir Param<'hir>) { @@ -617,11 +538,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } } -// This is a wrapper structure that allows determining if span values within -// the wrapped item should be hashed or not. struct HirItemLike { item_like: T, - hash_bodies: bool, } impl<'hir, T> HashStable> for HirItemLike @@ -629,7 +547,7 @@ where T: HashStable>, { fn hash_stable(&self, hcx: &mut StableHashingContext<'hir>, hasher: &mut StableHasher) { - hcx.while_hashing_hir_bodies(self.hash_bodies, |hcx| { + hcx.while_hashing_hir_bodies(true, |hcx| { self.item_like.hash_stable(hcx, hasher); }); } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index ef000f23d8b..0c6415a1308 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -8,8 +8,8 @@ use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId};*/ pub fn check_crate(hir_map: &EarlyMap<'_>, sess: &rustc_session::Session) { - hir_map.dep_graph.assert_ignored(); - /* + /*hir_map.dep_graph.assert_ignored(); + let errors = Lock::new(Vec::new()); par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 7604aeb8766..96ee938a172 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -4,7 +4,6 @@ pub use self::definitions::{ }; use crate::arena::Arena; -use crate::dep_graph::{DepGraph, DepNodeIndex}; use crate::hir::{HirOwner, HirOwnerItems}; use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; @@ -18,7 +17,6 @@ use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; use rustc_hir::*; -use rustc_index::vec::IndexVec; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::kw; @@ -34,7 +32,6 @@ mod hir_id_validator; #[derive(Copy, Clone, Debug)] pub struct Entry<'hir> { parent: HirId, - dep_node: DepNodeIndex, node: Node<'hir>, } @@ -132,26 +129,16 @@ fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { } } -/// This type is effectively a `HashMap>`, -/// but it is implemented as 2 layers of arrays. -/// - first we have `A = IndexVec` mapping `DefIndex`s to an inner value -/// - which is `B = IndexVec>` which gives you the `Entry`. -pub(super) type HirEntryMap<'hir> = IndexVec>>>; - /// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. pub struct EarlyMap<'hir> { pub krate: &'hir Crate<'hir>, - pub dep_graph: DepGraph, - /// The SVH of the local crate. pub crate_hash: Svh, pub(super) owner_map: FxHashMap>, pub(super) owner_items_map: FxHashMap>, - pub(super) map: HirEntryMap<'hir>, - pub(crate) definitions: &'hir Definitions, /// The reverse mapping of `node_to_hir_id`. @@ -164,8 +151,6 @@ pub struct Map<'hir> { pub(super) krate: &'hir Crate<'hir>, - pub dep_graph: DepGraph, - /// The SVH of the local crate. pub crate_hash: Svh, @@ -383,15 +368,11 @@ impl<'hir> Map<'hir> { fn get_entry(&self, id: HirId) -> Entry<'hir> { if id.local_id == ItemLocalId::from_u32_const(0) { let owner = self.tcx.hir_owner(id.owner_def_id()); - Entry { parent: owner.parent, node: owner.node, dep_node: DepNodeIndex::INVALID } + Entry { parent: owner.parent, node: owner.node } } else { let owner = self.tcx.hir_owner_items(id.owner_def_id()); let item = owner.items[id.local_id].as_ref().unwrap(); - Entry { - parent: HirId { owner: id.owner, local_id: item.parent }, - node: item.node, - dep_node: DepNodeIndex::INVALID, - } + Entry { parent: HirId { owner: id.owner, local_id: item.parent }, node: item.node } } } @@ -1069,7 +1050,6 @@ pub fn map_crate<'hir>( arena: &'hir Arena<'hir>, cstore: &CrateStoreDyn, krate: &'hir Crate<'hir>, - dep_graph: DepGraph, definitions: Definitions, ) -> EarlyMap<'hir> { let _prof_timer = sess.prof.generic_activity("build_hir_map"); @@ -1081,11 +1061,11 @@ pub fn map_crate<'hir>( .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); - let (map, owner_map, owner_items_map, crate_hash) = { + let (owner_map, owner_items_map, crate_hash) = { let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore); let mut collector = - NodeCollector::root(sess, arena, krate, &dep_graph, &definitions, &hir_to_node_id, hcx); + NodeCollector::root(sess, arena, krate, &definitions, &hir_to_node_id, hcx); intravisit::walk_crate(&mut collector, krate); let crate_disambiguator = sess.local_crate_disambiguator(); @@ -1095,9 +1075,7 @@ pub fn map_crate<'hir>( let map = EarlyMap { krate, - dep_graph, crate_hash, - map, owner_map, owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), hir_to_node_id, diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 34cfff999a7..590ad1b6995 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -100,8 +100,6 @@ pub fn provide(providers: &mut Providers<'_>) { tcx, krate: early.krate, - dep_graph: early.dep_graph, - crate_hash: early.crate_hash, owner_map: early.owner_map, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index cff93015d04..0d6c185e8ed 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1121,6 +1121,7 @@ impl<'tcx> TyCtxt<'tcx> { arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, hir: hir_map::EarlyMap<'tcx>, + dep_graph: DepGraph, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, output_filenames: &OutputFilenames, @@ -1132,7 +1133,6 @@ impl<'tcx> TyCtxt<'tcx> { let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); - let dep_graph = hir.dep_graph.clone(); let definitions = hir.definitions; let cstore = resolutions.cstore; let crates = cstore.crates_untracked(); diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 7035b956c9d..c1a373bb06b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -716,7 +716,7 @@ pub fn create_global_ctxt<'tcx>( let defs = mem::take(&mut resolver_outputs.definitions); // Construct the HIR map. - let hir_map = map::map_crate(sess, &**arena, &*resolver_outputs.cstore, krate, dep_graph, defs); + let hir_map = map::map_crate(sess, &**arena, &*resolver_outputs.cstore, krate, defs); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -743,6 +743,7 @@ pub fn create_global_ctxt<'tcx>( arena, resolver_outputs, hir_map, + dep_graph, query_result_on_disk_cache, &crate_name, &outputs, From b97d4383a4e82b084e9044ea47bad39fbfb91649 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 8 Feb 2020 05:30:45 +0100 Subject: [PATCH 1126/1250] Remove `Hir` and `HirBody` dep nodes --- src/librustc/dep_graph/dep_node.rs | 7 ------- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/hir_id_validator.rs | 2 +- src/librustc/ty/query/mod.rs | 2 -- src/librustc_incremental/assert_dep_graph.rs | 2 +- src/librustc_incremental/persist/dirty_clean.rs | 3 +-- 7 files changed, 5 insertions(+), 15 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 36b5f4de099..e3df9d5d04b 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -341,13 +341,6 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx> // We use this for most things when incr. comp. is turned off. [] Null, - // Represents the body of a function or method. The def-id is that of the - // function/method. - [eval_always] HirBody(DefId), - - // Represents the HIR node with the given node-id - [eval_always] Hir(DefId), - // Represents metadata from an extern crate. [eval_always] CrateMetadata(CrateNum), diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index a2dc1fdb34b..f5d68e8074d 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -677,7 +677,7 @@ impl DepGraph { } } else { match dep_dep_node.kind { - DepKind::Hir | DepKind::HirBody | DepKind::CrateMetadata => { + DepKind::CrateMetadata => { if let Some(def_id) = dep_dep_node.extract_def_id(tcx) { if def_id_corresponds_to_hir_dep_node(tcx, def_id) { // The `DefPath` has corresponding node, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index b9ab43ed289..ee5192f58c2 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -44,7 +44,7 @@ pub(super) struct NodeCollector<'a, 'hir> { hcx: StableHashingContext<'a>, - // We are collecting `DepNode::HirBody` hashes here so we can compute the + // We are collecting HIR hashes here so we can compute the // crate hash from them later on. hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 0c6415a1308..6792c00e763 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -7,7 +7,7 @@ use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId};*/ -pub fn check_crate(hir_map: &EarlyMap<'_>, sess: &rustc_session::Session) { +pub fn check_crate(_: &EarlyMap<'_>, sess: &rustc_session::Session) { /*hir_map.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index d1141a48990..3d17883fec3 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -180,8 +180,6 @@ pub fn force_from_dep_node<'tcx>(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> bool // These are inputs that are expected to be pre-allocated and that // should therefore always be red or green already. DepKind::CrateMetadata | - DepKind::HirBody | - DepKind::Hir | // These are anonymous nodes. DepKind::TraitSelect | diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 7686a507ff5..7ddb29c3cb6 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -120,7 +120,7 @@ impl IfThisChanged<'tcx> { if attr.check_name(sym::rustc_if_this_changed) { let dep_node_interned = self.argument(attr); let dep_node = match dep_node_interned { - None => DepNode::from_def_path_hash(def_path_hash, DepKind::Hir), + None => DepNode::from_def_path_hash(def_path_hash, DepKind::hir_owner), Some(n) => match DepNode::from_label_string(&n.as_str(), def_path_hash) { Ok(n) => n, Err(()) => { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c90b5abfe30..bb77309d32b 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -54,8 +54,7 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ // Hir and HirBody should be computed for all nodes - label_strs::Hir, - label_strs::HirBody, + "Hir", "HirBody", ]; /// `impl` implementation of struct/trait From d73268b05c07487c43ca9d09023db0bc47251e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 9 Feb 2020 10:31:13 +0100 Subject: [PATCH 1127/1250] Remove `input_task` --- src/librustc/dep_graph/graph.rs | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index f5d68e8074d..8a8ae60c813 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -225,28 +225,6 @@ impl DepGraph { ) } - /// Creates a new dep-graph input with value `input` - pub fn input_task<'a, C, R>(&self, key: DepNode, cx: C, input: R) -> (R, DepNodeIndex) - where - C: DepGraphSafe + StableHashingContextProvider<'a>, - R: for<'b> HashStable>, - { - fn identity_fn(_: C, arg: A) -> A { - arg - } - - self.with_task_impl( - key, - cx, - input, - true, - identity_fn, - |_| None, - |data, key, fingerprint, _| data.alloc_node(key, SmallVec::new(), fingerprint), - hash_result::, - ) - } - fn with_task_impl<'a, C, A, R>( &self, key: DepNode, From 3538cb38fceb82bbde827aeb44e96e25c4873b7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 9 Feb 2020 12:13:08 +0100 Subject: [PATCH 1128/1250] Only hash the Hir owner (including its bodies) --- src/librustc/hir/map/collector.rs | 12 +++++++++++- src/librustc/hir/mod.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index ee5192f58c2..a33ccf1b970 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -203,12 +203,22 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let owner = HirOwner { parent: entry.parent, node: entry.node }; let arena = self.arena; + let krate = self.krate; let items = self.owner_items_map.entry(id.owner).or_insert_with(|| { - arena.alloc(HirOwnerItems { items: IndexVec::new(), bodies: FxHashMap::default() }) + arena.alloc(HirOwnerItems { + // Insert a dummy node which will be overwritten + // when we call `insert_entry` on the HIR owner. + owner: Node::Crate(&krate.item), + items: IndexVec::new(), + bodies: FxHashMap::default(), + }) }); if i == 0 { + // Overwrite the dummy node with the real HIR owner. + items.owner = entry.node; + self.owner_map.insert(id.owner, self.arena.alloc(owner)); // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert //assert!(self.owner_map.insert(id.owner, self.arena.alloc(owner)).is_none()); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 590ad1b6995..edb52666923 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -5,10 +5,12 @@ pub mod exports; pub mod map; +use crate::ich::StableHashingContext; use crate::ty::query::Providers; use crate::ty::TyCtxt; use rustc_data_structures::cold_path; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::print; use rustc_hir::Body; @@ -25,19 +27,39 @@ pub struct HirOwner<'tcx> { node: Node<'tcx>, } -#[derive(HashStable, Clone)] +#[derive(Clone)] pub struct HirItem<'tcx> { parent: ItemLocalId, node: Node<'tcx>, } -#[derive(HashStable)] +impl<'a, 'tcx> HashStable> for HirItem<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + let HirItem { parent, node } = self; + hcx.while_hashing_hir_bodies(false, |hcx| { + parent.hash_stable(hcx, hasher); + node.hash_stable(hcx, hasher); + }); + } +} + pub struct HirOwnerItems<'tcx> { - //owner: &'tcx HirOwner<'tcx>, + owner: Node<'tcx>, items: IndexVec>>, bodies: FxHashMap>, } +impl<'a, 'tcx> HashStable> for HirOwnerItems<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + // We ignore the `items` and `bodies` fields since these refer to information reachable + // when hashing `owner` with its bodies. + let HirOwnerItems { owner, items: _, bodies: _ } = *self; + hcx.while_hashing_hir_bodies(true, |hcx| { + owner.hash_stable(hcx, hasher); + }); + } +} + /// A wrapper type which allows you to access HIR. #[derive(Clone)] pub struct Hir<'tcx> { From 8b16b023b1809fb10ed305cae4349c47c0accebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 9 Feb 2020 15:32:00 +0100 Subject: [PATCH 1129/1250] Index HIR after creating TyCtxt --- src/librustc/arena.rs | 2 +- src/librustc/hir/map/collector.rs | 2 +- src/librustc/hir/map/hir_id_validator.rs | 10 +- src/librustc/hir/map/mod.rs | 104 +++++++----------- src/librustc/hir/mod.rs | 79 ++----------- src/librustc/query/mod.rs | 2 +- src/librustc/ty/context.rs | 15 +-- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_driver/pretty.rs | 20 ++-- src/librustc_hir/intravisit.rs | 14 +-- src/librustc_incremental/assert_dep_graph.rs | 4 +- .../persist/dirty_clean.rs | 4 +- .../infer/error_reporting/need_type_info.rs | 10 +- .../nice_region_error/find_anon_type.rs | 8 +- src/librustc_interface/passes.rs | 10 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/late.rs | 4 +- src/librustc_lint/levels.rs | 4 +- src/librustc_metadata/rmeta/encoder.rs | 4 +- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/mod.rs | 2 +- .../hair/pattern/check_match.rs | 4 +- src/librustc_passes/check_attr.rs | 4 +- src/librustc_passes/check_const.rs | 7 +- src/librustc_passes/dead.rs | 6 +- src/librustc_passes/entry.rs | 4 +- src/librustc_passes/hir_stats.rs | 2 +- src/librustc_passes/intrinsicck.rs | 4 +- src/librustc_passes/lib_features.rs | 4 +- src/librustc_passes/liveness.rs | 6 +- src/librustc_passes/loops.rs | 9 +- src/librustc_passes/reachable.rs | 2 +- src/librustc_passes/region.rs | 2 +- src/librustc_passes/stability.rs | 12 +- src/librustc_passes/upvars.rs | 4 +- src/librustc_passes/weak_lang_items.rs | 2 +- src/librustc_privacy/lib.rs | 26 ++--- src/librustc_resolve/late/lifetimes.rs | 14 +-- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_traits/lowering/mod.rs | 4 +- src/librustc_ty/ty.rs | 3 +- src/librustc_typeck/check/compare_method.rs | 2 +- .../check/generator_interior.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/regionck.rs | 2 +- src/librustc_typeck/check/upvar.rs | 2 +- src/librustc_typeck/check/writeback.rs | 2 +- src/librustc_typeck/collect.rs | 8 +- src/librustc_typeck/collect/type_of.rs | 4 +- src/librustdoc/test.rs | 8 +- 51 files changed, 180 insertions(+), 279 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index 223bed5d635..72258c0537a 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -163,7 +163,7 @@ macro_rules! arena_types { [] where_predicate: rustc_hir::WherePredicate<$tcx>, // HIR query types - [few] hir_map: rustc::hir::map::Map<$tcx>, + [few] indexed_hir: rustc::hir::map::IndexedHir<$tcx>, [few] hir_definitions: rustc::hir::map::definitions::Definitions, [] hir_owner: rustc::hir::HirOwner<$tcx>, [] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>, diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index a33ccf1b970..1b95be9a3c5 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -307,7 +307,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { /// deep walking so that we walk nested items in the context of /// their outer items. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { panic!("`visit_nested_xxx` must be manually implemented in this visitor"); } diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 6792c00e763..281056684a1 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,4 +1,4 @@ -use crate::hir::map::EarlyMap; +use crate::ty::TyCtxt; /*use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; @@ -7,8 +7,8 @@ use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId};*/ -pub fn check_crate(_: &EarlyMap<'_>, sess: &rustc_session::Session) { - /*hir_map.dep_graph.assert_ignored(); +pub fn check_crate(_tcx: TyCtxt<'_>) { + /*tcx.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); @@ -24,7 +24,7 @@ pub fn check_crate(_: &EarlyMap<'_>, sess: &rustc_session::Session) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); - sess.delay_span_bug(rustc_span::DUMMY_SP, &message); + tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); }*/ } /* @@ -135,7 +135,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { type Map = EarlyMap<'hir>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 96ee938a172..d3aff7c963f 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -3,16 +3,14 @@ pub use self::definitions::{ DefKey, DefPath, DefPathData, DefPathHash, Definitions, DisambiguatedDefPathData, }; -use crate::arena::Arena; use crate::hir::{HirOwner, HirOwnerItems}; -use crate::middle::cstore::CrateStoreDyn; use crate::ty::query::Providers; use crate::ty::TyCtxt; use rustc_ast::ast::{self, Name, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, DefIndex, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; @@ -129,38 +127,20 @@ fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { } } -/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. -pub struct EarlyMap<'hir> { - pub krate: &'hir Crate<'hir>, - +pub struct IndexedHir<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, pub(super) owner_map: FxHashMap>, pub(super) owner_items_map: FxHashMap>, - pub(crate) definitions: &'hir Definitions, - /// The reverse mapping of `node_to_hir_id`. pub(super) hir_to_node_id: FxHashMap, } -/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s. +#[derive(Copy, Clone)] pub struct Map<'hir> { pub(super) tcx: TyCtxt<'hir>, - - pub(super) krate: &'hir Crate<'hir>, - - /// The SVH of the local crate. - pub crate_hash: Svh, - - pub(super) owner_map: FxHashMap>, - pub(super) owner_items_map: FxHashMap>, - - pub(super) definitions: &'hir Definitions, - - /// The reverse mapping of `node_to_hir_id`. - pub(super) hir_to_node_id: FxHashMap, } /// An iterator that walks up the ancestor tree of a given `HirId`. @@ -196,21 +176,18 @@ impl<'hir> Iterator for ParentHirIterator<'_, 'hir> { } impl<'hir> Map<'hir> { - /// This is used internally in the dependency tracking system. - /// Use the `krate` method to ensure your dependency on the - /// crate is tracked. - pub fn untracked_krate(&self) -> &Crate<'hir> { - &self.krate + pub fn krate(&self) -> &'hir Crate<'hir> { + self.tcx.hir_crate(LOCAL_CRATE) } #[inline] - pub fn definitions(&self) -> &Definitions { - &self.definitions + pub fn definitions(&self) -> &'hir Definitions { + &self.tcx.definitions } pub fn def_key(&self, def_id: DefId) -> DefKey { assert!(def_id.is_local()); - self.definitions.def_key(def_id.index) + self.tcx.definitions.def_key(def_id.index) } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { @@ -219,7 +196,7 @@ impl<'hir> Map<'hir> { pub fn def_path(&self, def_id: DefId) -> DefPath { assert!(def_id.is_local()); - self.definitions.def_path(def_id.index) + self.tcx.definitions.def_path(def_id.index) } #[inline] @@ -248,42 +225,42 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(&self, hir_id: HirId) -> Option { let node_id = self.hir_to_node_id(hir_id); - self.definitions.opt_local_def_id(node_id) + self.tcx.definitions.opt_local_def_id(node_id) } #[inline] pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option { - self.definitions.opt_local_def_id(node) + self.tcx.definitions.opt_local_def_id(node) } #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { - self.definitions.as_local_node_id(def_id) + self.tcx.definitions.as_local_node_id(def_id) } #[inline] pub fn as_local_hir_id(&self, def_id: DefId) -> Option { - self.definitions.as_local_hir_id(def_id) + self.tcx.definitions.as_local_hir_id(def_id) } #[inline] pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId { - self.hir_to_node_id[&hir_id] + self.tcx.index_hir(LOCAL_CRATE).hir_to_node_id[&hir_id] } #[inline] pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId { - self.definitions.node_to_hir_id(node_id) + self.tcx.definitions.node_to_hir_id(node_id) } #[inline] pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId { - self.definitions.def_index_to_hir_id(def_index) + self.tcx.definitions.def_index_to_hir_id(def_index) } #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - self.definitions.def_index_to_hir_id(def_id.to_def_id().index) + self.tcx.definitions.def_index_to_hir_id(def_id.to_def_id().index) } pub fn def_kind(&self, hir_id: HirId) -> Option { @@ -1045,45 +1022,42 @@ impl Named for ImplItem<'_> { } } -pub fn map_crate<'hir>( - sess: &rustc_session::Session, - arena: &'hir Arena<'hir>, - cstore: &CrateStoreDyn, - krate: &'hir Crate<'hir>, - definitions: Definitions, -) -> EarlyMap<'hir> { - let _prof_timer = sess.prof.generic_activity("build_hir_map"); +pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx IndexedHir<'tcx> { + assert_eq!(cnum, LOCAL_CRATE); + + let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = definitions + let hir_to_node_id = tcx + .definitions .node_to_hir_id .iter_enumerated() .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); let (owner_map, owner_items_map, crate_hash) = { - let hcx = crate::ich::StableHashingContext::new(sess, krate, &definitions, cstore); - - let mut collector = - NodeCollector::root(sess, arena, krate, &definitions, &hir_to_node_id, hcx); - intravisit::walk_crate(&mut collector, krate); - - let crate_disambiguator = sess.local_crate_disambiguator(); - let cmdline_args = sess.opts.dep_tracking_hash(); - collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args) + let hcx = tcx.create_stable_hashing_context(); + + let mut collector = NodeCollector::root( + tcx.sess, + &**tcx.arena, + tcx.untracked_crate, + &tcx.definitions, + &hir_to_node_id, + hcx, + ); + intravisit::walk_crate(&mut collector, tcx.untracked_crate); + + let crate_disambiguator = tcx.sess.local_crate_disambiguator(); + let cmdline_args = tcx.sess.opts.dep_tracking_hash(); + collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; - let map = EarlyMap { - krate, + let map = tcx.arena.alloc(IndexedHir { crate_hash, owner_map, owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), hir_to_node_id, - definitions: arena.alloc(definitions), - }; - - sess.time("validate_HIR_map", || { - hir_id_validator::check_crate(&map, sess); }); map diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index edb52666923..2142e61ca98 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -8,18 +8,14 @@ pub mod map; use crate::ich::StableHashingContext; use crate::ty::query::Providers; use crate::ty::TyCtxt; -use rustc_data_structures::cold_path; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::print; use rustc_hir::Body; -use rustc_hir::Crate; use rustc_hir::HirId; use rustc_hir::ItemLocalId; use rustc_hir::Node; use rustc_index::vec::IndexVec; -use std::ops::Deref; #[derive(HashStable)] pub struct HirOwner<'tcx> { @@ -60,48 +56,10 @@ impl<'a, 'tcx> HashStable> for HirOwnerItems<'tcx> { } } -/// A wrapper type which allows you to access HIR. -#[derive(Clone)] -pub struct Hir<'tcx> { - tcx: TyCtxt<'tcx>, - map: &'tcx map::Map<'tcx>, -} - -impl<'tcx> Hir<'tcx> { - pub fn krate(&self) -> &'tcx Crate<'tcx> { - self.tcx.hir_crate(LOCAL_CRATE) - } -} - -impl<'tcx> Deref for Hir<'tcx> { - type Target = &'tcx map::Map<'tcx>; - - #[inline(always)] - fn deref(&self) -> &Self::Target { - &self.map - } -} - -impl<'hir> print::PpAnn for Hir<'hir> { - fn nested(&self, state: &mut print::State<'_>, nested: print::Nested) { - self.map.nested(state, nested) - } -} - impl<'tcx> TyCtxt<'tcx> { #[inline(always)] - pub fn hir(self) -> Hir<'tcx> { - let map = self.late_hir_map.load(); - let map = if unlikely!(map.is_none()) { - cold_path(|| { - let map = self.hir_map(LOCAL_CRATE); - self.late_hir_map.store(Some(map)); - map - }) - } else { - map.unwrap() - }; - Hir { tcx: self, map } + pub fn hir(self) -> map::Map<'tcx> { + map::Map { tcx: self } } pub fn parent_module(self, id: HirId) -> DefId { @@ -114,37 +72,16 @@ pub fn provide(providers: &mut Providers<'_>) { let hir = tcx.hir(); hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap())) }; - providers.hir_crate = |tcx, _| tcx.hir_map(LOCAL_CRATE).untracked_krate(); - providers.hir_map = |tcx, id| { - assert_eq!(id, LOCAL_CRATE); - let early = tcx.hir_map.steal(); - tcx.arena.alloc(map::Map { - tcx, - krate: early.krate, - - crate_hash: early.crate_hash, - - owner_map: early.owner_map, - owner_items_map: early.owner_items_map, - - definitions: early.definitions, - - hir_to_node_id: early.hir_to_node_id, - }) - }; + providers.hir_crate = |tcx, _| tcx.untracked_crate; + providers.index_hir = map::index_hir; providers.hir_module_items = |tcx, id| { assert_eq!(id.krate, LOCAL_CRATE); let hir = tcx.hir(); let module = hir.as_local_hir_id(id).unwrap(); - &hir.untracked_krate().modules[&module] - }; - providers.hir_owner = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - *tcx.hir().map.owner_map.get(&id.index).unwrap() - }; - providers.hir_owner_items = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - *tcx.hir().map.owner_items_map.get(&id.index).unwrap() + &tcx.untracked_crate.modules[&module] }; + providers.hir_owner = |tcx, id| *tcx.index_hir(id.krate).owner_map.get(&id.index).unwrap(); + providers.hir_owner_items = + |tcx, id| *tcx.index_hir(id.krate).owner_items_map.get(&id.index).unwrap(); map::provide(providers); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5dafa462ca8..866fe8c88a8 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -55,7 +55,7 @@ rustc_queries! { desc { "get the crate HIR" } } - query hir_map(_: CrateNum) -> &'tcx map::Map<'tcx> { + query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> { eval_always no_hash desc { "index HIR" } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0d6c185e8ed..611a2dc20b4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -53,7 +53,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{ hash_stable_hashmap, HashStable, StableHasher, StableVec, }; -use rustc_data_structures::sync::{self, AtomicCell, Lock, Lrc, WorkerLocal}; +use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE}; @@ -939,7 +939,7 @@ pub struct GlobalCtxt<'tcx> { interners: CtxtInterners<'tcx>, - cstore: Box, + pub(crate) cstore: Box, pub sess: &'tcx Session, @@ -972,9 +972,6 @@ pub struct GlobalCtxt<'tcx> { /// Export map produced by name resolution. export_map: FxHashMap>>, - /// These should usually be accessed with the `tcx.hir()` method. - pub(crate) hir_map: Steal>, - pub(crate) late_hir_map: AtomicCell>>, pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>, pub(crate) definitions: &'tcx Definitions, @@ -1120,7 +1117,8 @@ impl<'tcx> TyCtxt<'tcx> { extern_providers: ty::query::Providers<'tcx>, arena: &'tcx WorkerLocal>, resolutions: ty::ResolverOutputs, - hir: hir_map::EarlyMap<'tcx>, + krate: &'tcx hir::Crate<'tcx>, + definitions: &'tcx Definitions, dep_graph: DepGraph, on_disk_query_result_cache: query::OnDiskCache<'tcx>, crate_name: &str, @@ -1133,7 +1131,6 @@ impl<'tcx> TyCtxt<'tcx> { let common_types = CommonTypes::new(&interners); let common_lifetimes = CommonLifetimes::new(&interners); let common_consts = CommonConsts::new(&interners, &common_types); - let definitions = hir.definitions; let cstore = resolutions.cstore; let crates = cstore.crates_untracked(); let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0); @@ -1213,9 +1210,7 @@ impl<'tcx> TyCtxt<'tcx> { .map(|(id, names)| (definitions.local_def_id(id), names)) .collect(), extern_prelude: resolutions.extern_prelude, - untracked_crate: hir.krate, - hir_map: Steal::new(hir), - late_hir_map: AtomicCell::new(None), + untracked_crate: krate, definitions, def_path_hash_to_def_id, queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache), diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 748b9b7fb40..b5b1d82f1ee 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -1462,7 +1462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 65fe1fec526..2361046c036 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -106,7 +106,7 @@ trait HirPrinterSupport<'hir>: pprust_hir::PpAnn { /// Provides a uniform interface for re-extracting a reference to an /// `hir_map::Map` from a value that now owns it. - fn hir_map(&self) -> Option<&hir_map::Map<'hir>>; + fn hir_map(&self) -> Option>; /// Produces the pretty-print annotation object. /// @@ -142,8 +142,8 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> { self.sess } - fn hir_map(&self) -> Option<&hir_map::Map<'hir>> { - self.tcx.map(|tcx| *tcx.hir()) + fn hir_map(&self) -> Option> { + self.tcx.map(|tcx| tcx.hir()) } fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { @@ -155,7 +155,7 @@ impl<'hir> pprust::PpAnn for NoAnn<'hir> {} impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { if let Some(tcx) = self.tcx { - pprust_hir::PpAnn::nested(*tcx.hir(), state, nested) + pprust_hir::PpAnn::nested(&tcx.hir(), state, nested) } } } @@ -216,8 +216,8 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { self.sess } - fn hir_map(&self) -> Option<&hir_map::Map<'hir>> { - self.tcx.map(|tcx| *tcx.hir()) + fn hir_map(&self) -> Option> { + self.tcx.map(|tcx| tcx.hir()) } fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { @@ -228,7 +228,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> { impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> { fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested) { if let Some(ref tcx) = self.tcx { - pprust_hir::PpAnn::nested(*tcx.hir(), state, nested) + pprust_hir::PpAnn::nested(&tcx.hir(), state, nested) } } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { @@ -315,8 +315,8 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> { &self.tcx.sess } - fn hir_map(&self) -> Option<&hir_map::Map<'tcx>> { - Some(&self.tcx.hir()) + fn hir_map(&self) -> Option> { + Some(self.tcx.hir()) } fn pp_ann(&self) -> &dyn pprust_hir::PpAnn { @@ -334,7 +334,7 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> { if let pprust_hir::Nested::Body(id) = nested { self.tables.set(self.tcx.body_tables(id)); } - pprust_hir::PpAnn::nested(*self.tcx.hir(), state, nested); + pprust_hir::PpAnn::nested(&self.tcx.hir(), state, nested); self.tables.set(old_tables); } fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) { diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 5f31ddeae95..7202c6cac26 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -134,7 +134,7 @@ pub trait Map<'hir> { /// /// See the comments on `ItemLikeVisitor` for more details on the overall /// visit strategy. -pub enum NestedVisitorMap<'this, M> { +pub enum NestedVisitorMap { /// Do not visit any nested things. When you add a new /// "non-nested" thing, you will want to audit such uses to see if /// they remain valid. @@ -151,20 +151,20 @@ pub enum NestedVisitorMap<'this, M> { /// to use `visit_all_item_likes()` as an outer loop, /// and to have the visitor that visits the contents of each item /// using this setting. - OnlyBodies(&'this M), + OnlyBodies(M), /// Visits all nested things, including item-likes. /// /// **This is an unusual choice.** It is used when you want to /// process everything within their lexical context. Typically you /// kick off the visit by doing `walk_krate()`. - All(&'this M), + All(M), } -impl<'this, M> NestedVisitorMap<'this, M> { +impl NestedVisitorMap { /// Returns the map to use for an "intra item-like" thing (if any). /// E.g., function body. - fn intra(self) -> Option<&'this M> { + fn intra(self) -> Option { match self { NestedVisitorMap::None => None, NestedVisitorMap::OnlyBodies(map) => Some(map), @@ -174,7 +174,7 @@ impl<'this, M> NestedVisitorMap<'this, M> { /// Returns the map to use for an "item-like" thing (if any). /// E.g., item, impl-item. - fn inter(self) -> Option<&'this M> { + fn inter(self) -> Option { match self { NestedVisitorMap::None => None, NestedVisitorMap::OnlyBodies(_) => None, @@ -221,7 +221,7 @@ pub trait Visitor<'v>: Sized { /// `panic!()`. This way, if a new `visit_nested_XXX` variant is /// added in the future, we will see the panic in your code and /// fix it appropriately. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map>; + fn nested_visit_map(&mut self) -> NestedVisitorMap; /// Invoked when a nested item is encountered. By default does /// nothing unless you override `nested_visit_map` to return other than diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 7ddb29c3cb6..a7dccaf974b 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -162,8 +162,8 @@ impl IfThisChanged<'tcx> { impl Visitor<'tcx> for IfThisChanged<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index bb77309d32b..c2274a7424e 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -547,8 +547,8 @@ impl FindAllAttrs<'tcx> { impl intravisit::Visitor<'tcx> for FindAllAttrs<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index 22576c088ff..0eda4555e25 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -16,7 +16,7 @@ use std::borrow::Cow; struct FindLocalByTypeVisitor<'a, 'tcx> { infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, - hir_map: &'a Map<'tcx>, + hir_map: Map<'tcx>, found_local_pattern: Option<&'tcx Pat<'tcx>>, found_arg_pattern: Option<&'tcx Pat<'tcx>>, found_ty: Option>, @@ -25,7 +25,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> { } impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { - fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: &'a Map<'tcx>) -> Self { + fn new(infcx: &'a InferCtxt<'a, 'tcx>, target_ty: Ty<'tcx>, hir_map: Map<'tcx>) -> Self { Self { infcx, target_ty, @@ -69,8 +69,8 @@ impl<'a, 'tcx> FindLocalByTypeVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.hir_map) } fn visit_local(&mut self, local: &'tcx Local<'tcx>) { @@ -223,7 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let ty = self.resolve_vars_if_possible(&ty); let (name, name_sp, descr, parent_name, parent_descr) = self.extract_type_name(&ty, None); - let mut local_visitor = FindLocalByTypeVisitor::new(&self, ty, &self.tcx.hir()); + 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); diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index 23ad93c6a21..47d6f5ccbb1 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -93,8 +93,8 @@ struct FindNestedTypeVisitor<'tcx> { impl Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) { @@ -212,8 +212,8 @@ struct TyPathVisitor<'tcx> { impl Visitor<'tcx> for TyPathVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'tcx>> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap> { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_lifetime(&mut self, lifetime: &hir::Lifetime) { diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index c1a373bb06b..a250fcc217a 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -5,7 +5,7 @@ use crate::util; use log::{info, log_enabled, warn}; use rustc::arena::Arena; use rustc::dep_graph::DepGraph; -use rustc::hir::map; +use rustc::hir::map::Definitions; use rustc::lint; use rustc::middle; use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; @@ -713,10 +713,7 @@ pub fn create_global_ctxt<'tcx>( arena: &'tcx WorkerLocal>, ) -> QueryContext<'tcx> { let sess = &compiler.session(); - let defs = mem::take(&mut resolver_outputs.definitions); - - // Construct the HIR map. - let hir_map = map::map_crate(sess, &**arena, &*resolver_outputs.cstore, krate, defs); + let defs: &'tcx Definitions = arena.alloc(mem::take(&mut resolver_outputs.definitions)); let query_result_on_disk_cache = rustc_incremental::load_query_result_cache(sess); @@ -742,7 +739,8 @@ pub fn create_global_ctxt<'tcx>( extern_providers, arena, resolver_outputs, - hir_map, + krate, + defs, dep_graph, query_result_on_disk_cache, &crate_name, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 852998c9e7d..d9333658b90 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1073,7 +1073,7 @@ impl TypeAliasBounds { impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } diff --git a/src/librustc_lint/late.rs b/src/librustc_lint/late.rs index 839057a75a6..d2cc5510603 100644 --- a/src/librustc_lint/late.rs +++ b/src/librustc_lint/late.rs @@ -99,8 +99,8 @@ impl<'a, 'tcx, T: LateLintPass<'a, 'tcx>> hir_visit::Visitor<'tcx> /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> { - hir_visit::NestedVisitorMap::All(&self.context.tcx.hir()) + fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { + hir_visit::NestedVisitorMap::All(self.context.tcx.hir()) } fn visit_nested_body(&mut self, body: hir::BodyId) { diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs index 6fddf1535c9..2062f9499ae 100644 --- a/src/librustc_lint/levels.rs +++ b/src/librustc_lint/levels.rs @@ -438,8 +438,8 @@ impl LintLevelMapBuilder<'_, '_> { impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'_, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) { diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index e69b4fd6195..06475ab270c 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1505,8 +1505,8 @@ impl EncodeContext<'tcx> { impl Visitor<'tcx> for EncodeContext<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) { intravisit::walk_expr(self, ex); diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 152a98c0c1a..21788593259 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -453,7 +453,7 @@ struct UnusedUnsafeVisitor<'a> { impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 95e2db75080..d4a5966af4a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -87,7 +87,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet { intravisit::walk_struct_def(self, v) } type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index d0eefb2e4d1..96172a4aca2 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -45,7 +45,7 @@ struct MatchVisitor<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -752,7 +752,7 @@ fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pa impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 7ee16de52be..702872400c4 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -418,8 +418,8 @@ impl CheckAttrVisitor<'tcx> { impl Visitor<'tcx> for CheckAttrVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx Item<'tcx>) { diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index 53e8213ae48..af06fc0c002 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -8,7 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc::hir::map::Map; -use rustc::hir::Hir; use rustc::session::config::nightly_options; use rustc::session::parse::feature_err; use rustc::ty::query::Providers; @@ -75,7 +74,7 @@ enum ConstKind { } impl ConstKind { - fn for_body(body: &hir::Body<'_>, hir_map: Hir<'_>) -> Option { + fn for_body(body: &hir::Body<'_>, hir_map: Map<'_>) -> Option { let is_const_fn = |id| hir_map.fn_sig_by_hir_id(id).unwrap().header.is_const(); let owner = hir_map.body_owner(body.id()); @@ -202,8 +201,8 @@ impl<'tcx> CheckConstVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for CheckConstVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_anon_const(&mut self, anon: &'tcx hir::AnonConst) { diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 4a0ffc23365..7460b8e2fe9 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { NestedVisitorMap::None } @@ -568,8 +568,8 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { /// on inner functions when the outer function is already getting /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index c29c552202a..2cabe786d0c 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -1,4 +1,4 @@ -use rustc::hir::Hir; +use rustc::hir::map::Map; use rustc::session::config::EntryFnType; use rustc::session::{config, Session}; use rustc::ty::query::Providers; @@ -15,7 +15,7 @@ use rustc_span::{Span, DUMMY_SP}; struct EntryContext<'a, 'tcx> { session: &'a Session, - map: Hir<'tcx>, + map: Map<'tcx>, /// The top-level function called `main`. main_fn: Option<(HirId, Span)>, diff --git a/src/librustc_passes/hir_stats.rs b/src/librustc_passes/hir_stats.rs index c819809041f..7037ed0d9b9 100644 --- a/src/librustc_passes/hir_stats.rs +++ b/src/librustc_passes/hir_stats.rs @@ -95,7 +95,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap { panic!("visit_nested_xxx must be manually implemented in this visitor") } diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 782199003c7..5cf9666797e 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -124,7 +124,7 @@ impl ExprVisitor<'tcx> { impl Visitor<'tcx> for ItemVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -141,7 +141,7 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> { impl Visitor<'tcx> for ExprVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/lib_features.rs b/src/librustc_passes/lib_features.rs index 172d7e7628e..133e30f6ff0 100644 --- a/src/librustc_passes/lib_features.rs +++ b/src/librustc_passes/lib_features.rs @@ -114,8 +114,8 @@ impl LibFeatureCollector<'tcx> { impl Visitor<'tcx> for LibFeatureCollector<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_attribute(&mut self, attr: &'tcx Attribute) { diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 5b6d0fc74e8..030d0893b02 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -156,8 +156,8 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String { impl<'tcx> Visitor<'tcx> for IrMaps<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_fn( @@ -1361,7 +1361,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/loops.rs b/src/librustc_passes/loops.rs index 2719057fb53..1daef45a1f5 100644 --- a/src/librustc_passes/loops.rs +++ b/src/librustc_passes/loops.rs @@ -24,15 +24,14 @@ enum Context { #[derive(Copy, Clone)] struct CheckLoopVisitor<'a, 'hir> { sess: &'a Session, - hir_map: &'a Map<'hir>, + hir_map: Map<'hir>, cx: Context, } fn check_mod_loops(tcx: TyCtxt<'_>, module_def_id: DefId) { tcx.hir().visit_item_likes_in_module( module_def_id, - &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: &tcx.hir(), cx: Normal } - .as_deep_visitor(), + &mut CheckLoopVisitor { sess: &tcx.sess, hir_map: tcx.hir(), cx: Normal }.as_deep_visitor(), ); } @@ -43,8 +42,8 @@ pub(crate) fn provide(providers: &mut Providers<'_>) { impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { type Map = Map<'hir>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.hir_map) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.hir_map) } fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) { diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 79a9f226030..ad415ed8f62 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -85,7 +85,7 @@ struct ReachableContext<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index 908785faff0..640a3a35aa0 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -698,7 +698,7 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 84ba245998c..6cf4132141b 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -259,8 +259,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { /// deep-walking. type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item<'tcx>) { @@ -350,8 +350,8 @@ impl<'a, 'tcx> MissingStabilityAnnotations<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, i: &'tcx Item<'tcx>) { @@ -492,8 +492,8 @@ impl Visitor<'tcx> for Checker<'tcx> { /// Because stability levels are scoped lexically, we want to walk /// nested items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_passes/upvars.rs b/src/librustc_passes/upvars.rs index 6be4f130c1f..d20237a22d9 100644 --- a/src/librustc_passes/upvars.rs +++ b/src/librustc_passes/upvars.rs @@ -46,7 +46,7 @@ struct LocalCollector { impl Visitor<'tcx> for LocalCollector { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -75,7 +75,7 @@ impl CaptureCollector<'_, '_> { impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 7bf49d56531..d85c7d8c6de 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -87,7 +87,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> { impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { type Map = Map<'v>; - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, Map<'v>> { + fn nested_visit_map(&mut self) -> NestedVisitorMap> { NestedVisitorMap::None } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 175b2390d30..46067187173 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -373,8 +373,8 @@ struct PubRestrictedVisitor<'tcx> { impl Visitor<'tcx> for PubRestrictedVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_vis(&mut self, vis: &'tcx hir::Visibility<'tcx>) { self.has_pub_restricted = self.has_pub_restricted || vis.node.is_pub_restricted(); @@ -678,8 +678,8 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -1049,8 +1049,8 @@ impl<'a, 'tcx> Visitor<'tcx> for NamePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { @@ -1191,8 +1191,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_mod(&mut self, _m: &'tcx hir::Mod<'tcx>, _s: Span, _n: hir::HirId) { @@ -1449,7 +1449,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -1479,8 +1479,8 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { /// We want to visit items in the context of their containing /// module and so forth, so supply a crate for doing a deep walk. - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -1925,8 +1925,8 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5c0748797f0..ddee73e72a4 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -367,8 +367,8 @@ fn sub_items_have_self_param(node: &hir::ItemKind<'_>) -> bool { impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::All(self.tcx.hir()) } // We want to nest trait/impl items in their parent, but nothing else. @@ -1125,7 +1125,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2174,7 +2174,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { impl<'a> Visitor<'a> for SelfVisitor<'a> { type Map = Map<'a>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2265,7 +2265,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2854,7 +2854,7 @@ fn insert_late_bound_lifetimes( impl<'v> Visitor<'v> for ConstrainedCollector { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } @@ -2897,7 +2897,7 @@ fn insert_late_bound_lifetimes( impl<'v> Visitor<'v> for AllCollector { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 0e0cb8ccb0c..656c3c7e613 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1569,7 +1569,7 @@ struct ReturnsVisitor<'v> { impl<'v> Visitor<'v> for ReturnsVisitor<'v> { type Map = rustc::hir::map::Map<'v>; - fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { hir::intravisit::NestedVisitorMap::None } diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index e77bb6df8e6..3a0c36a84ae 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -603,8 +603,8 @@ impl ClauseDumper<'tcx> { impl Visitor<'tcx> for ClauseDumper<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 4c0903b6b9d..387d1d9923d 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -273,8 +273,7 @@ fn original_crate_name(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Symbol { } fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { - assert_eq!(crate_num, LOCAL_CRATE); - tcx.hir().crate_hash + tcx.index_hir(crate_num).crate_hash } fn instance_def_size_estimate<'tcx>( diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index ff79d10273c..1dde57124ee 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -893,7 +893,7 @@ fn compare_synthetic_generics<'tcx>( type Map = Map<'v>; fn nested_visit_map( &mut self, - ) -> intravisit::NestedVisitorMap<'_, Self::Map> + ) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 7e526573773..5208e2f56a5 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -211,7 +211,7 @@ pub fn resolve_interior<'a, 'tcx>( impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index bfbad1a0ea9..ef779cfa834 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -1349,7 +1349,7 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1975b248999..d0d421746ae 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1179,7 +1179,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index bfa3d75b6b0..975c6e101a6 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -419,7 +419,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index b5ed6335dc0..7bc121733a4 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -62,7 +62,7 @@ struct InferBorrowKindVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index f4c166b943d..b8f8030e3cd 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -246,7 +246,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cd63dacdcda..779b30c55e1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -107,7 +107,7 @@ crate struct PlaceholderHirTyCollector(crate Vec); impl<'v> Visitor<'v> for PlaceholderHirTyCollector { type Map = Map<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } fn visit_ty(&mut self, t: &'v hir::Ty<'v>) { @@ -201,8 +201,8 @@ fn reject_placeholder_type_signatures_in_item(tcx: TyCtxt<'tcx>, item: &'tcx hir impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { - NestedVisitorMap::OnlyBodies(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> NestedVisitorMap { + NestedVisitorMap::OnlyBodies(self.tcx.hir()) } fn visit_item(&mut self, item: &'tcx hir::Item<'tcx>) { @@ -1047,7 +1047,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option for LateBoundRegionsDetector<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> NestedVisitorMap<'_, Self::Map> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index 43cf65d8151..c4a8edd86f8 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -529,8 +529,8 @@ fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { impl<'tcx> intravisit::Visitor<'tcx> for ConstraintLocator<'tcx> { type Map = Map<'tcx>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.tcx.hir()) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) { if let hir::ExprKind::Closure(..) = ex.kind { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 85ccb55333b..15e588705f7 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -107,7 +107,7 @@ pub fn run(options: Options) -> i32 { let mut hir_collector = HirCollector { sess: compiler.session(), collector: &mut collector, - map: *tcx.hir(), + map: tcx.hir(), codes: ErrorCodes::from( compiler.session().opts.unstable_features.is_nightly_build(), ), @@ -856,7 +856,7 @@ impl Tester for Collector { struct HirCollector<'a, 'hir> { sess: &'a session::Session, collector: &'a mut Collector, - map: &'a Map<'hir>, + map: Map<'hir>, codes: ErrorCodes, } @@ -904,8 +904,8 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { impl<'a, 'hir> intravisit::Visitor<'hir> for HirCollector<'a, 'hir> { type Map = Map<'hir>; - fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> { - intravisit::NestedVisitorMap::All(&self.map) + fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { + intravisit::NestedVisitorMap::All(self.map) } fn visit_item(&mut self, item: &'hir hir::Item) { From 0e316e29e6f7166989cb3e8342b145f16dc48cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Sun, 9 Feb 2020 17:11:02 +0100 Subject: [PATCH 1130/1250] Fix HIR map validation --- src/librustc/hir/map/hir_id_validator.rs | 25 ++++++++++++------------ src/librustc/hir/map/mod.rs | 1 + src/librustc_interface/passes.rs | 2 ++ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 281056684a1..c4c23c1a754 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -1,18 +1,20 @@ +use crate::hir::map::Map; use crate::ty::TyCtxt; -/*use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::{HirId, ItemLocalId};*/ +use rustc_hir::{HirId, ItemLocalId}; -pub fn check_crate(_tcx: TyCtxt<'_>) { - /*tcx.dep_graph.assert_ignored(); +pub fn check_crate(tcx: TyCtxt<'_>) { + tcx.dep_graph.assert_ignored(); let errors = Lock::new(Vec::new()); + let hir_map = tcx.hir(); - par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| { + par_iter(&hir_map.krate().modules).for_each(|(module_id, _)| { let local_def_id = hir_map.local_def_id(*module_id); hir_map.visit_item_likes_in_module( local_def_id, @@ -25,23 +27,23 @@ pub fn check_crate(_tcx: TyCtxt<'_>) { if !errors.is_empty() { let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2); tcx.sess.delay_span_bug(rustc_span::DUMMY_SP, &message); - }*/ + } } -/* + struct HirIdValidator<'a, 'hir> { - hir_map: &'a EarlyMap<'hir>, + hir_map: Map<'hir>, owner_def_index: Option, hir_ids_seen: FxHashSet, errors: &'a Lock>, } struct OuterVisitor<'a, 'hir> { - hir_map: &'a EarlyMap<'hir>, + hir_map: Map<'hir>, errors: &'a Lock>, } impl<'a, 'hir> OuterVisitor<'a, 'hir> { - fn new_inner_visitor(&self, hir_map: &'a EarlyMap<'hir>) -> HirIdValidator<'a, 'hir> { + fn new_inner_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, owner_def_index: None, @@ -133,7 +135,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { - type Map = EarlyMap<'hir>; + type Map = Map<'hir>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::OnlyBodies(self.hir_map) @@ -173,4 +175,3 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { // different owner. } } -*/ diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index d3aff7c963f..8b13f008a89 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -25,6 +25,7 @@ pub mod blocks; mod collector; pub mod definitions; mod hir_id_validator; +pub use hir_id_validator::check_crate; /// Represents an entry and its parent `HirId`. #[derive(Copy, Clone, Debug)] diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index a250fcc217a..4fe7a06e560 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -762,6 +762,8 @@ pub fn create_global_ctxt<'tcx>( fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> { assert_eq!(cnum, LOCAL_CRATE); + rustc::hir::map::check_crate(tcx); + let sess = tcx.sess; let mut entry_point = None; From aea57aee5fd6debadb91dd30cd4bb4ccb92411f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 10 Feb 2020 14:29:21 +0100 Subject: [PATCH 1131/1250] Don't hash HIR with bodies thrice --- src/librustc/hir/map/collector.rs | 50 ++++++++++++++++++------------- src/librustc/hir/mod.rs | 30 +++++++++---------- 2 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 1b95be9a3c5..58f755693f7 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -63,9 +63,10 @@ fn hash_body( def_path_hash: DefPathHash, item_like: impl for<'a> HashStable>, hir_body_nodes: &mut Vec<(DefPathHash, Fingerprint)>, -) { +) -> Fingerprint { let hash = hash(hcx, HirItemLike { item_like: &item_like }); hir_body_nodes.push((def_path_hash, hash)); + hash } fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { @@ -96,7 +97,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let mut hir_body_nodes = Vec::new(); - { + let hash = { let Crate { ref item, // These fields are handled separately: @@ -137,6 +138,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { collector.insert_entry( hir::CRATE_HIR_ID, Entry { parent: hir::CRATE_HIR_ID, node: Node::Crate(&krate.item) }, + hash, ); collector @@ -197,27 +199,24 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { (self.owner_map, self.owner_items_map, svh) } - fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>) { + fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) { let i = id.local_id.as_u32() as usize; let owner = HirOwner { parent: entry.parent, node: entry.node }; let arena = self.arena; - let krate = self.krate; let items = self.owner_items_map.entry(id.owner).or_insert_with(|| { arena.alloc(HirOwnerItems { - // Insert a dummy node which will be overwritten - // when we call `insert_entry` on the HIR owner. - owner: Node::Crate(&krate.item), + hash, items: IndexVec::new(), bodies: FxHashMap::default(), }) }); if i == 0 { - // Overwrite the dummy node with the real HIR owner. - items.owner = entry.node; + // Overwrite the dummy hash with the real HIR owner hash. + items.hash = hash; self.owner_map.insert(id.owner, self.arena.alloc(owner)); // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert @@ -234,6 +233,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } fn insert(&mut self, span: Span, hir_id: HirId, node: Node<'hir>) { + self.insert_with_hash(span, hir_id, node, Fingerprint::ZERO) + } + + fn insert_with_hash(&mut self, span: Span, hir_id: HirId, node: Node<'hir>, hash: Fingerprint) { let entry = Entry { parent: self.parent_node, node }; // Make sure that the DepNode of some node coincides with the HirId @@ -269,7 +272,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { } } - self.insert_entry(hir_id, entry); + self.insert_entry(hir_id, entry, hash); } fn with_parent(&mut self, parent_node_id: HirId, f: F) { @@ -281,7 +284,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { fn with_dep_node_owner< T: for<'b> HashStable>, - F: FnOnce(&mut Self), + F: FnOnce(&mut Self, Fingerprint), >( &mut self, dep_node_owner: DefIndex, @@ -292,10 +295,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let def_path_hash = self.definitions.def_path_hash(dep_node_owner); - hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); + let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); self.current_dep_node_owner = dep_node_owner; - f(self); + f(self, hash); self.current_dep_node_owner = prev_owner; } } @@ -342,8 +345,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { i.hir_id.owner, self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap() ); - self.with_dep_node_owner(i.hir_id.owner, i, |this| { - this.insert(i.span, i.hir_id, Node::Item(i)); + self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| { + this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash); this.with_parent(i.hir_id, |this| { if let ItemKind::Struct(ref struct_def, _) = i.kind { // If this is a tuple or unit-like struct, register the constructor. @@ -374,8 +377,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { ti.hir_id.owner, self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap() ); - self.with_dep_node_owner(ti.hir_id.owner, ti, |this| { - this.insert(ti.span, ti.hir_id, Node::TraitItem(ti)); + self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| { + this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash); this.with_parent(ti.hir_id, |this| { intravisit::walk_trait_item(this, ti); @@ -388,8 +391,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { ii.hir_id.owner, self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap() ); - self.with_dep_node_owner(ii.hir_id.owner, ii, |this| { - this.insert(ii.span, ii.hir_id, Node::ImplItem(ii)); + self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| { + this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash); this.with_parent(ii.hir_id, |this| { intravisit::walk_impl_item(this, ii); @@ -508,8 +511,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { let node_id = self.hir_to_node_id[¯o_def.hir_id]; let def_index = self.definitions.opt_def_index(node_id).unwrap(); - self.with_dep_node_owner(def_index, macro_def, |this| { - this.insert(macro_def.span, macro_def.hir_id, Node::MacroDef(macro_def)); + self.with_dep_node_owner(def_index, macro_def, |this, hash| { + this.insert_with_hash( + macro_def.span, + macro_def.hir_id, + Node::MacroDef(macro_def), + hash, + ); }); } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 2142e61ca98..c5e2c847b0d 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -8,6 +8,7 @@ pub mod map; use crate::ich::StableHashingContext; use crate::ty::query::Providers; use crate::ty::TyCtxt; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; @@ -17,21 +18,14 @@ use rustc_hir::ItemLocalId; use rustc_hir::Node; use rustc_index::vec::IndexVec; -#[derive(HashStable)] pub struct HirOwner<'tcx> { parent: HirId, node: Node<'tcx>, } -#[derive(Clone)] -pub struct HirItem<'tcx> { - parent: ItemLocalId, - node: Node<'tcx>, -} - -impl<'a, 'tcx> HashStable> for HirItem<'tcx> { +impl<'a, 'tcx> HashStable> for HirOwner<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - let HirItem { parent, node } = self; + let HirOwner { parent, node } = self; hcx.while_hashing_hir_bodies(false, |hcx| { parent.hash_stable(hcx, hasher); node.hash_stable(hcx, hasher); @@ -39,20 +33,24 @@ impl<'a, 'tcx> HashStable> for HirItem<'tcx> { } } +#[derive(Clone)] +pub struct HirItem<'tcx> { + parent: ItemLocalId, + node: Node<'tcx>, +} + pub struct HirOwnerItems<'tcx> { - owner: Node<'tcx>, + hash: Fingerprint, items: IndexVec>>, bodies: FxHashMap>, } impl<'a, 'tcx> HashStable> for HirOwnerItems<'tcx> { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - // We ignore the `items` and `bodies` fields since these refer to information reachable - // when hashing `owner` with its bodies. - let HirOwnerItems { owner, items: _, bodies: _ } = *self; - hcx.while_hashing_hir_bodies(true, |hcx| { - owner.hash_stable(hcx, hasher); - }); + // We ignore the `items` and `bodies` fields since these refer to information included in + // `hash` which is hashed in the collector and used for the crate hash. + let HirOwnerItems { hash, items: _, bodies: _ } = *self; + hash.hash_stable(hcx, hasher); } } From 396aeb83c0bbb495e4cf1feb3a6dead8e9ce6972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Mon, 10 Feb 2020 17:00:49 +0100 Subject: [PATCH 1132/1250] Optimize the HIR map --- src/librustc/hir/map/collector.rs | 70 ++++++++++++++++--------------- src/librustc/hir/map/mod.rs | 18 ++++---- src/librustc/hir/mod.rs | 7 ++-- 3 files changed, 49 insertions(+), 46 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 58f755693f7..da2a8c05af5 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -1,6 +1,6 @@ use crate::arena::Arena; use crate::hir::map::definitions::{self, DefPathHash}; -use crate::hir::map::{Entry, Map}; +use crate::hir::map::{Entry, HirOwnerData, Map}; use crate::hir::{HirItem, HirOwner, HirOwnerItems}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; @@ -14,7 +14,7 @@ use rustc_hir::def_id::CRATE_DEF_INDEX; use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; -use rustc_index::vec::IndexVec; +use rustc_index::vec::{Idx, IndexVec}; use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::SourceMap; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -31,8 +31,7 @@ pub(super) struct NodeCollector<'a, 'hir> { /// Source map source_map: &'a SourceMap, - owner_map: FxHashMap>, - owner_items_map: FxHashMap>, + map: IndexVec>, /// The parent of this node parent_node: hir::HirId, @@ -49,6 +48,15 @@ pub(super) struct NodeCollector<'a, 'hir> { hir_body_nodes: Vec<(DefPathHash, Fingerprint)>, } +fn insert_vec_map(map: &mut IndexVec>, k: K, v: V) { + let i = k.index(); + let len = map.len(); + if i >= len { + map.extend(repeat(None).take(i - len + 1)); + } + map[k] = Some(v); +} + fn hash( hcx: &mut StableHashingContext<'_>, input: impl for<'a> HashStable>, @@ -126,14 +134,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { hir_to_node_id, hcx, hir_body_nodes, - owner_map: FxHashMap::with_capacity_and_hasher( - definitions.def_index_count(), - Default::default(), - ), - owner_items_map: FxHashMap::with_capacity_and_hasher( - definitions.def_index_count(), - Default::default(), - ), + map: (0..definitions.def_index_count()) + .map(|_| HirOwnerData { signature: None, with_bodies: None }) + .collect(), }; collector.insert_entry( hir::CRATE_HIR_ID, @@ -149,14 +152,10 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64, - ) -> ( - FxHashMap>, - FxHashMap>, - Svh, - ) { + ) -> (IndexVec>, Svh) { // Insert bodies into the map for (id, body) in self.krate.bodies.iter() { - let bodies = &mut self.owner_items_map.get_mut(&id.hir_id.owner).unwrap().bodies; + let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies; assert!(bodies.insert(id.hir_id.local_id, body).is_none()); } @@ -196,39 +195,42 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { let crate_hash: Fingerprint = stable_hasher.finish(); let svh = Svh::new(crate_hash.to_smaller_hash()); - (self.owner_map, self.owner_items_map, svh) + (self.map, svh) } fn insert_entry(&mut self, id: HirId, entry: Entry<'hir>, hash: Fingerprint) { let i = id.local_id.as_u32() as usize; - let owner = HirOwner { parent: entry.parent, node: entry.node }; - let arena = self.arena; - let items = self.owner_items_map.entry(id.owner).or_insert_with(|| { - arena.alloc(HirOwnerItems { + let data = &mut self.map[id.owner]; + + if data.with_bodies.is_none() { + data.with_bodies = Some(arena.alloc(HirOwnerItems { hash, items: IndexVec::new(), bodies: FxHashMap::default(), - }) - }); + })); + } + + let items = data.with_bodies.as_mut().unwrap(); if i == 0 { // Overwrite the dummy hash with the real HIR owner hash. items.hash = hash; - self.owner_map.insert(id.owner, self.arena.alloc(owner)); - // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert - //assert!(self.owner_map.insert(id.owner, self.arena.alloc(owner)).is_none()); + // FIXME: feature(impl_trait_in_bindings) broken and trigger this assert + //assert!(data.signature.is_none()); + + data.signature = + Some(self.arena.alloc(HirOwner { parent: entry.parent, node: entry.node })); } else { - let len = items.items.len(); - if i >= len { - items.items.extend(repeat(None).take(i - len + 1)); - } assert_eq!(entry.parent.owner, id.owner); - items.items[id.local_id] = - Some(HirItem { parent: entry.parent.local_id, node: entry.node }); + insert_vec_map( + &mut items.items, + id.local_id, + HirItem { parent: entry.parent.local_id, node: entry.node }, + ); } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 8b13f008a89..3bdd2b1ac3c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -15,6 +15,7 @@ use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; use rustc_hir::*; +use rustc_index::vec::IndexVec; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::kw; @@ -128,12 +129,16 @@ fn is_body_owner<'hir>(node: Node<'hir>, hir_id: HirId) -> bool { } } +pub(super) struct HirOwnerData<'hir> { + pub(super) signature: Option<&'hir HirOwner<'hir>>, + pub(super) with_bodies: Option<&'hir mut HirOwnerItems<'hir>>, +} + pub struct IndexedHir<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - pub(super) owner_map: FxHashMap>, - pub(super) owner_items_map: FxHashMap>, + pub(super) map: IndexVec>, /// The reverse mapping of `node_to_hir_id`. pub(super) hir_to_node_id: FxHashMap, @@ -1036,7 +1041,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); - let (owner_map, owner_items_map, crate_hash) = { + let (map, crate_hash) = { let hcx = tcx.create_stable_hashing_context(); let mut collector = NodeCollector::root( @@ -1054,12 +1059,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; - let map = tcx.arena.alloc(IndexedHir { - crate_hash, - owner_map, - owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(), - hir_to_node_id, - }); + let map = tcx.arena.alloc(IndexedHir { crate_hash, map, hir_to_node_id }); map } diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index c5e2c847b0d..3b69fc8d8f2 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -78,8 +78,9 @@ pub fn provide(providers: &mut Providers<'_>) { let module = hir.as_local_hir_id(id).unwrap(); &tcx.untracked_crate.modules[&module] }; - providers.hir_owner = |tcx, id| *tcx.index_hir(id.krate).owner_map.get(&id.index).unwrap(); - providers.hir_owner_items = - |tcx, id| *tcx.index_hir(id.krate).owner_items_map.get(&id.index).unwrap(); + providers.hir_owner = |tcx, id| tcx.index_hir(id.krate).map[id.index].signature.unwrap(); + providers.hir_owner_items = |tcx, id| { + tcx.index_hir(id.krate).map[id.index].with_bodies.as_ref().map(|items| &**items).unwrap() + }; map::provide(providers); } From 739a1ef11336f61e3bc6dc80fecabb39f8f7b742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 15:11:33 +0100 Subject: [PATCH 1133/1250] Create the `hir_to_node_id` map before `TyCtxt` --- src/librustc/hir/map/collector.rs | 14 +++++--------- src/librustc/hir/map/definitions.rs | 16 ++++++++++++++++ src/librustc/hir/map/mod.rs | 26 ++++---------------------- 3 files changed, 25 insertions(+), 31 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index da2a8c05af5..e8233c0446d 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -4,7 +4,6 @@ use crate::hir::map::{Entry, HirOwnerData, Map}; use crate::hir::{HirItem, HirOwner, HirOwnerItems}; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStore; -use rustc_ast::ast::NodeId; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -39,7 +38,6 @@ pub(super) struct NodeCollector<'a, 'hir> { current_dep_node_owner: DefIndex, definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, hcx: StableHashingContext<'a>, @@ -98,7 +96,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { arena: &'hir Arena<'hir>, krate: &'hir Crate<'hir>, definitions: &'a definitions::Definitions, - hir_to_node_id: &'a FxHashMap, mut hcx: StableHashingContext<'a>, ) -> NodeCollector<'a, 'hir> { let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); @@ -131,7 +128,6 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { parent_node: hir::CRATE_HIR_ID, current_dep_node_owner: CRATE_DEF_INDEX, definitions, - hir_to_node_id, hcx, hir_body_nodes, map: (0..definitions.def_index_count()) @@ -244,7 +240,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { // Make sure that the DepNode of some node coincides with the HirId // owner of that node. if cfg!(debug_assertions) { - let node_id = self.hir_to_node_id[&hir_id]; + let node_id = self.definitions.hir_to_node_id(hir_id); assert_eq!(self.definitions.node_to_hir_id(node_id), hir_id); if hir_id.owner != self.current_dep_node_owner { @@ -345,7 +341,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { debug!("visit_item: {:?}", i); debug_assert_eq!( i.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&i.hir_id]).unwrap() + self.definitions.opt_def_index(self.definitions.hir_to_node_id(i.hir_id)).unwrap() ); self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| { this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash); @@ -377,7 +373,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!( ti.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ti.hir_id]).unwrap() + self.definitions.opt_def_index(self.definitions.hir_to_node_id(ti.hir_id)).unwrap() ); self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| { this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash); @@ -391,7 +387,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!( ii.hir_id.owner, - self.definitions.opt_def_index(self.hir_to_node_id[&ii.hir_id]).unwrap() + self.definitions.opt_def_index(self.definitions.hir_to_node_id(ii.hir_id)).unwrap() ); self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| { this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash); @@ -510,7 +506,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) { - let node_id = self.hir_to_node_id[¯o_def.hir_id]; + let node_id = self.definitions.hir_to_node_id(macro_def.hir_id); let def_index = self.definitions.opt_def_index(node_id).unwrap(); self.with_dep_node_owner(def_index, macro_def, |this, hash| { diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 50117f73d48..42ccf7e7250 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -80,7 +80,11 @@ pub struct Definitions { table: DefPathTable, node_to_def_index: NodeMap, def_index_to_node: IndexVec, + pub(super) node_to_hir_id: IndexVec, + /// The reverse mapping of `node_to_hir_id`. + pub(super) hir_to_node_id: FxHashMap, + /// If `ExpnId` is an ID of some macro expansion, /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. parent_modules_of_macro_defs: FxHashMap, @@ -346,6 +350,11 @@ impl Definitions { } } + #[inline] + pub fn hir_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId { + self.hir_to_node_id[&hir_id] + } + #[inline] pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId { self.node_to_hir_id[node_id] @@ -472,6 +481,13 @@ impl Definitions { "trying to initialize `NodeId` -> `HirId` mapping twice" ); self.node_to_hir_id = mapping; + + // Build the reverse mapping of `node_to_hir_id`. + self.hir_to_node_id = self + .node_to_hir_id + .iter_enumerated() + .map(|(node_id, &hir_id)| (hir_id, node_id)) + .collect(); } pub fn expansion_that_defined(&self, index: DefIndex) -> ExpnId { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 3bdd2b1ac3c..bcbb6f3ec31 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -7,7 +7,6 @@ use crate::hir::{HirOwner, HirOwnerItems}; use crate::ty::query::Providers; use crate::ty::TyCtxt; use rustc_ast::ast::{self, Name, NodeId}; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; @@ -139,9 +138,6 @@ pub struct IndexedHir<'hir> { pub crate_hash: Svh, pub(super) map: IndexVec>, - - /// The reverse mapping of `node_to_hir_id`. - pub(super) hir_to_node_id: FxHashMap, } #[derive(Copy, Clone)] @@ -251,7 +247,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId { - self.tcx.index_hir(LOCAL_CRATE).hir_to_node_id[&hir_id] + self.tcx.definitions.hir_to_node_id(hir_id) } #[inline] @@ -1033,25 +1029,11 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe let _prof_timer = tcx.sess.prof.generic_activity("build_hir_map"); - // Build the reverse mapping of `node_to_hir_id`. - let hir_to_node_id = tcx - .definitions - .node_to_hir_id - .iter_enumerated() - .map(|(node_id, &hir_id)| (hir_id, node_id)) - .collect(); - let (map, crate_hash) = { let hcx = tcx.create_stable_hashing_context(); - let mut collector = NodeCollector::root( - tcx.sess, - &**tcx.arena, - tcx.untracked_crate, - &tcx.definitions, - &hir_to_node_id, - hcx, - ); + let mut collector = + NodeCollector::root(tcx.sess, &**tcx.arena, tcx.untracked_crate, &tcx.definitions, hcx); intravisit::walk_crate(&mut collector, tcx.untracked_crate); let crate_disambiguator = tcx.sess.local_crate_disambiguator(); @@ -1059,7 +1041,7 @@ pub(super) fn index_hir<'tcx>(tcx: TyCtxt<'tcx>, cnum: CrateNum) -> &'tcx Indexe collector.finalize_and_compute_crate_hash(crate_disambiguator, &*tcx.cstore, cmdline_args) }; - let map = tcx.arena.alloc(IndexedHir { crate_hash, map, hir_to_node_id }); + let map = tcx.arena.alloc(IndexedHir { crate_hash, map }); map } From c0b60c428a051773dea79426cb4a6a03737ca902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 15:34:10 +0100 Subject: [PATCH 1134/1250] Replace `HirBody` with `hir_owner_items` in tests --- .../persist/dirty_clean.rs | 5 +- .../rmeta/decoder/cstore_impl.rs | 2 +- .../incremental/hashes/call_expressions.rs | 22 ++--- .../incremental/hashes/closure_expressions.rs | 12 +-- src/test/incremental/hashes/consts.rs | 18 ++-- .../incremental/hashes/enum_constructors.rs | 30 +++---- src/test/incremental/hashes/enum_defs.rs | 54 ++++++------ .../incremental/hashes/exported_vs_not.rs | 8 +- src/test/incremental/hashes/for_loops.rs | 22 ++--- .../incremental/hashes/function_interfaces.rs | 48 +++++------ src/test/incremental/hashes/if_expressions.rs | 16 ++-- .../hashes/indexing_expressions.rs | 28 +++---- src/test/incremental/hashes/inherent_impls.rs | 52 ++++++------ src/test/incremental/hashes/inline_asm.rs | 12 +-- .../incremental/hashes/let_expressions.rs | 24 +++--- .../incremental/hashes/loop_expressions.rs | 16 ++-- .../incremental/hashes/match_expressions.rs | 26 +++--- src/test/incremental/hashes/panic_exprs.rs | 18 ++-- src/test/incremental/hashes/statics.rs | 26 +++--- .../incremental/hashes/struct_constructors.rs | 18 ++-- src/test/incremental/hashes/struct_defs.rs | 84 +++++++++---------- src/test/incremental/hashes/trait_defs.rs | 8 +- src/test/incremental/hashes/trait_impls.rs | 8 +- src/test/incremental/hashes/type_defs.rs | 32 +++---- .../hashes/unary_and_binary_exprs.rs | 56 ++++++------- .../incremental/hashes/while_let_loops.rs | 18 ++-- src/test/incremental/hashes/while_loops.rs | 18 ++-- .../ich_method_call_trait_scope.rs | 4 +- src/test/incremental/ich_nested_items.rs | 4 +- src/test/incremental/ich_resolve_results.rs | 8 +- src/test/incremental/source_loc_macros.rs | 10 +-- .../spans_significant_w_debuginfo.rs | 2 +- src/test/incremental/string_constant.rs | 2 +- 33 files changed, 356 insertions(+), 355 deletions(-) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c2274a7424e..cfc0a5e1498 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -53,8 +53,9 @@ const BASE_FN: &[&str] = &[ /// DepNodes for Hir, which is pretty much everything const BASE_HIR: &[&str] = &[ - // Hir and HirBody should be computed for all nodes - "Hir", "HirBody", + // hir_owner and hir_owner_items should be computed for all nodes + label_strs::hir_owner, + label_strs::hir_owner_items, ]; /// `impl` implementation of struct/trait diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index dcbfed8972c..86f64dc45b7 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -142,7 +142,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, cdata.get_deprecation(def_id.index).map(DeprecationEntry::external) } item_attrs => { cdata.get_item_attrs(def_id.index, tcx.sess) } - // FIXME(#38501) We've skipped a `read` on the `HirBody` of + // FIXME(#38501) We've skipped a `read` on the `hir_owner_items` of // a `fn` when encoding, so the dep-tracking wouldn't work. // This is only used by rustdoc anyway, which shouldn't have // incremental recompilation ever enabled. diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index 50d3657d417..e5478e5ec90 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -25,7 +25,7 @@ pub fn change_callee_function() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_callee_function() { callee2(1, 2) @@ -40,7 +40,7 @@ pub fn change_argument_function() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_function() { callee1(1, 3) @@ -57,8 +57,8 @@ mod change_callee_indirectly_function { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] pub fn change_callee_indirectly_function() { @@ -81,7 +81,7 @@ pub fn change_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_callee_method() { let s = Struct; @@ -98,7 +98,7 @@ pub fn change_argument_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_method() { let s = Struct; @@ -115,7 +115,7 @@ pub fn change_ufcs_callee_method() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_ufcs_callee_method() { let s = Struct; @@ -132,7 +132,7 @@ pub fn change_argument_method_ufcs() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_argument_method_ufcs() { let s = Struct; @@ -149,9 +149,9 @@ pub fn change_to_ufcs() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] -// One might think this would be expanded in the HirBody/Mir, but it actually +// One might think this would be expanded in the hir_owner_items/Mir, but it actually // results in slightly different Hir/Mir. pub fn change_to_ufcs() { let s = Struct; @@ -171,7 +171,7 @@ pub mod change_ufcs_callee_indirectly { #[cfg(not(cfail1))] use super::Struct2 as Struct; - #[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 08693560d0b..3d9db340f63 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -21,7 +21,7 @@ pub fn change_closure_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn change_closure_body() { let _ = || 3u32; @@ -37,7 +37,7 @@ pub fn add_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_parameter() { let x = 0u32; @@ -53,7 +53,7 @@ pub fn change_parameter_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_parameter_pattern() { let _ = |(x,): (u32,)| x; @@ -68,7 +68,7 @@ pub fn add_move() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_move() { let _ = move || 1; @@ -84,7 +84,7 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; @@ -101,7 +101,7 @@ pub fn change_parameter_type() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_parameter_type() { let closure = |x: u16| (x as u64) + 1; diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index 3d2eed89636..ef4598ab3b6 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,13 +39,13 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -57,7 +57,7 @@ const CONST_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -67,7 +67,7 @@ const CONST_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -77,7 +77,7 @@ const CONST_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 575b2e92966..703e62d5fe1 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -34,7 +34,7 @@ pub fn change_field_value_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_struct_like() -> Enum { Enum::Struct { @@ -57,7 +57,7 @@ pub fn change_field_order_struct_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] // FIXME(michaelwoerister):Interesting. I would have thought that that changes the MIR. And it // would if it were not all constants @@ -96,7 +96,7 @@ pub fn change_constructor_path_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_struct_like() { let _ = Enum2::Struct { @@ -119,7 +119,7 @@ pub fn change_constructor_variant_struct_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_struct_like() { let _ = Enum2::Struct2 { @@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -161,7 +161,7 @@ pub mod change_constructor_variant_indirectly_struct_like { #[cfg(not(cfail1))] use super::Enum2::Struct2 as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Enum2 { Variant { @@ -180,7 +180,7 @@ pub fn change_field_value_tuple_like() -> Enum { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_tuple_like() -> Enum { Enum::Tuple(0, 1, 3) @@ -197,7 +197,7 @@ pub fn change_constructor_path_tuple_like() { #[cfg(not(cfail1))] #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,mir_built,typeck_tables_of" + except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_tuple_like() { @@ -215,7 +215,7 @@ pub fn change_constructor_variant_tuple_like() { #[cfg(not(cfail1))] #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,mir_built,typeck_tables_of" + except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_tuple_like() { @@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -251,7 +251,7 @@ pub mod change_constructor_variant_indirectly_tuple_like { #[cfg(not(cfail1))] use super::Enum2::Tuple2 as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Enum2 { Variant(0, 1, 2) @@ -278,7 +278,7 @@ pub fn change_constructor_path_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_c_like() { let _ = Clike2::B; @@ -293,7 +293,7 @@ pub fn change_constructor_variant_c_like() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_variant_c_like() { let _ = Clike::C; @@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,\ + except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -328,7 +328,7 @@ pub mod change_constructor_variant_indirectly_c_like { #[cfg(not(cfail1))] use super::Clike::B as Variant; - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn function() -> Clike { Variant diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 7256c1aa153..3925d222701 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -26,7 +26,7 @@ enum EnumVisibility { A } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub enum EnumVisibility { A @@ -42,7 +42,7 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameCStyleVariant { Variant1, @@ -59,7 +59,7 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -76,7 +76,7 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -93,7 +93,7 @@ enum EnumChangeValueCStyleVariant0 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant0 { Variant1, @@ -109,7 +109,7 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -125,7 +125,7 @@ enum EnumAddCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddCStyleVariant { Variant1, @@ -142,7 +142,7 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveCStyleVariant { Variant1, @@ -157,7 +157,7 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddTupleStyleVariant { Variant1, @@ -174,7 +174,7 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -189,7 +189,7 @@ enum EnumAddStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddStructStyleVariant { Variant1, @@ -206,7 +206,7 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveStructStyleVariant { Variant1, @@ -221,7 +221,7 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -238,7 +238,7 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -257,7 +257,7 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -272,7 +272,7 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -289,7 +289,7 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -304,7 +304,7 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -319,7 +319,7 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -335,7 +335,7 @@ enum EnumAddMustUse { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[must_use] enum EnumAddMustUse { @@ -353,7 +353,7 @@ enum EnumAddReprC { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] #[repr(C)] enum EnumAddReprC { @@ -531,7 +531,7 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -552,7 +552,7 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -577,7 +577,7 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum TupleStyle { Variant1( @@ -595,7 +595,7 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum StructStyle { Variant1 { @@ -618,7 +618,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum { Variant1(T) @@ -634,7 +634,7 @@ mod change_trait_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum where T: Trait { Variant1(T) diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index ef275cabeaf..76d33aa2085 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -7,7 +7,7 @@ #![crate_type="rlib"] // Case 1: The function body is not exported to metadata. If the body changes, -// the hash of the HirBody node should change, but not the hash of +// the hash of the hir_owner_items node should change, but not the hash of // either the Hir or the Metadata node. #[cfg(cfail1)] @@ -16,7 +16,7 @@ pub fn body_not_exported_to_metadata() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn body_not_exported_to_metadata() -> u32 { 2 @@ -35,7 +35,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn body_exported_to_metadata_because_of_inline() -> u32 { @@ -55,7 +55,7 @@ pub fn body_exported_to_metadata_because_of_generic() -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn body_exported_to_metadata_because_of_generic() -> u32 { diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 70820dfaea4..3e54dafd9ac 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_iteration_variable_name() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iteration_variable_name() { let mut _x = 0; @@ -71,7 +71,7 @@ pub fn change_iteration_variable_pattern() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_iteration_variable_pattern() { let mut _x = 0; @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -139,7 +139,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -162,7 +162,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -187,7 +187,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -212,7 +212,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -237,7 +237,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -262,7 +262,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 9cc2d3bcf60..3109af2d393 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -23,7 +23,7 @@ pub fn add_parameter() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn add_parameter(p: i32) {} @@ -34,7 +34,7 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] pub fn add_return_type() -> () {} @@ -46,7 +46,7 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter(p: i64) {} @@ -58,7 +58,7 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -70,7 +70,7 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -82,7 +82,7 @@ pub fn make_unsafe() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub unsafe fn make_unsafe() {} @@ -93,7 +93,7 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} @@ -105,7 +105,7 @@ pub fn type_parameter() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] + except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn type_parameter() {} @@ -116,7 +116,7 @@ pub fn type_parameter() {} pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, generics_of")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, generics_of")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} @@ -127,7 +127,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -138,7 +138,7 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn builtin_bound() {} @@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] + except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -161,7 +161,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -172,7 +172,7 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_builtin_bound() {} @@ -184,7 +184,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, generics_of, type_of, predicates_of")] + except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -195,7 +195,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} pub fn inline() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[inline] pub fn inline() {} @@ -208,7 +208,7 @@ pub fn inline() {} pub fn inline_never() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[inline(never)] pub fn inline_never() {} @@ -220,7 +220,7 @@ pub fn inline_never() {} pub fn no_mangle() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[no_mangle] pub fn no_mangle() {} @@ -232,7 +232,7 @@ pub fn no_mangle() {} pub fn linkage() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[linkage = "weak_odr"] pub fn linkage() {} @@ -246,7 +246,7 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn return_impl_trait() -> impl Clone { 0 @@ -280,7 +280,7 @@ pub mod change_return_type_indirectly { use super::ReferencedType2 as ReturnType; #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_return_type() -> ReturnType { ReturnType {} @@ -297,7 +297,7 @@ pub mod change_parameter_type_indirectly { use super::ReferencedType2 as ParameterType; #[rustc_clean(cfg = "cfail2", - except = "Hir, HirBody, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_parameter_type(p: ParameterType) {} } @@ -314,7 +314,7 @@ pub mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound(p: T) {} } @@ -328,7 +328,7 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound_where(p: T) where diff --git a/src/test/incremental/hashes/if_expressions.rs b/src/test/incremental/hashes/if_expressions.rs index 4b73f1371f8..93bdc0322bb 100644 --- a/src/test/incremental/hashes/if_expressions.rs +++ b/src/test/incremental/hashes/if_expressions.rs @@ -25,7 +25,7 @@ pub fn change_condition(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_condition(x: bool) -> u32 { if !x { @@ -46,7 +46,7 @@ pub fn change_then_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_then_branch(x: bool) -> u32 { if x { @@ -69,7 +69,7 @@ pub fn change_else_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_else_branch(x: bool) -> u32 { if x { @@ -94,7 +94,7 @@ pub fn add_else_branch(x: bool) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch(x: bool) -> u32 { let mut ret = 1; @@ -120,7 +120,7 @@ pub fn change_condition_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_condition_if_let(x: Option) -> u32 { if let Some(_) = x { @@ -143,7 +143,7 @@ pub fn change_then_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_then_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -166,7 +166,7 @@ pub fn change_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_else_branch_if_let(x: Option) -> u32 { if let Some(x) = x { @@ -191,7 +191,7 @@ pub fn add_else_branch_if_let(x: Option) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_else_branch_if_let(x: Option) -> u32 { let mut ret = 1; diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 08cf19d7760..2a0eacd4dc1 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -22,8 +22,8 @@ fn change_simple_index(slice: &[u32]) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_simple_index(slice: &[u32]) -> u32 { slice[4] } @@ -39,8 +39,8 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_lower_bound(slice: &[u32]) -> &[u32] { &slice[2..5] } @@ -56,8 +56,8 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -73,8 +73,8 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn add_lower_bound(slice: &[u32]) -> &[u32] { &slice[3..4] } @@ -90,8 +90,8 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn add_upper_bound(slice: &[u32]) -> &[u32] { &slice[3..7] } @@ -107,8 +107,8 @@ fn change_mutability(slice: &mut [u32]) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_mutability(slice: &mut [u32]) -> u32 { (&slice[3..5])[0] } @@ -124,8 +124,8 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { #[cfg(not(cfail1))] #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { &slice[3..=7] } diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 24d436f5f97..f4fb601d07b 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -23,7 +23,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -44,7 +44,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn method_body() { @@ -68,7 +68,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + except="hir_owner_items,optimized_mir,promoted_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] #[inline] @@ -85,10 +85,10 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="associated_item,Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="associated_item,Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] fn method_privacy() { } } @@ -100,7 +100,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] @@ -120,7 +120,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn method_selfmutness(&mut self) { } @@ -135,7 +135,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -160,7 +160,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn add_method_parameter(&self, _: i32) { } @@ -178,7 +178,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_method_parameter_name(&self, b: i64) { } } @@ -197,7 +197,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,optimized_mir,mir_built,typeck_tables_of")] + except="Hir,hir_owner_items,fn_sig,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_method_return_type(&self) -> u8 { 0 } } @@ -214,7 +214,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn make_method_inline(&self) -> u8 { 0 } @@ -232,7 +232,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] + #[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_method_parameter_order(&self, b: i64, a: i64) { } } @@ -251,7 +251,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub unsafe fn make_method_unsafe(&self) { } @@ -269,7 +269,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } } @@ -286,7 +286,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -312,7 +312,7 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -340,7 +340,7 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,generics_of,predicates_of,type_of", + except="Hir,hir_owner_items,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] pub fn add_type_parameter_to_method(&self) { } @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,HirBody,generics_of,predicates_of,type_of,typeck_tables_of" + except="Hir,hir_owner_items,generics_of,predicates_of,type_of,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -387,7 +387,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of,predicates_of,\ + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,generics_of,predicates_of,\ type_of")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -414,7 +414,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,predicates_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -431,7 +431,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[no_mangle] pub fn add_no_mangle_to_method(&self) { } @@ -448,7 +448,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,generics_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,generics_of")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean( @@ -468,7 +468,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")] @@ -485,7 +485,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -502,7 +502,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/src/test/incremental/hashes/inline_asm.rs b/src/test/incremental/hashes/inline_asm.rs index c50ee73d714..a77123110ae 100644 --- a/src/test/incremental/hashes/inline_asm.rs +++ b/src/test/incremental/hashes/inline_asm.rs @@ -33,7 +33,7 @@ pub fn change_template(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_template(a: i32) -> i32 { @@ -69,7 +69,7 @@ pub fn change_output(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_output(a: i32) -> i32 { @@ -105,7 +105,7 @@ pub fn change_input(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input(_a: i32, _b: i32) -> i32 { @@ -140,7 +140,7 @@ pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_input_constraint(_a: i32, _b: i32) -> i32 { @@ -175,7 +175,7 @@ pub fn change_clobber(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_clobber(_a: i32) -> i32 { @@ -210,7 +210,7 @@ pub fn change_options(_a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] pub fn change_options(_a: i32) -> i32 { diff --git a/src/test/incremental/hashes/let_expressions.rs b/src/test/incremental/hashes/let_expressions.rs index 68545b7daaa..2d9cf4203dc 100644 --- a/src/test/incremental/hashes/let_expressions.rs +++ b/src/test/incremental/hashes/let_expressions.rs @@ -22,7 +22,7 @@ pub fn change_name() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name() { let _y = 2u64; @@ -38,7 +38,7 @@ pub fn add_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_type() { let _x: u32 = 2u32; @@ -54,7 +54,7 @@ pub fn change_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_type() { let _x: u8 = 2; @@ -70,7 +70,7 @@ pub fn change_mutability_of_reference_type() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_reference_type() { let _x: &mut u64; @@ -86,7 +86,7 @@ pub fn change_mutability_of_slot() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_slot() { let _x: u64 = 0; @@ -102,7 +102,7 @@ pub fn change_simple_binding_to_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_simple_binding_to_pattern() { let (_a, _b) = (0u8, 'x'); @@ -118,7 +118,7 @@ pub fn change_name_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_in_pattern() { let (_a, _c) = (1u8, 'y'); @@ -134,7 +134,7 @@ pub fn add_ref_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_ref_in_pattern() { let (ref _a, _b) = (1u8, 'y'); @@ -150,7 +150,7 @@ pub fn add_amp_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_amp_in_pattern() { let (&_a, _b) = (&1u8, 'y'); @@ -166,7 +166,7 @@ pub fn change_mutability_of_binding_in_pattern() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_binding_in_pattern() { let (mut _a, _b) = (99u8, 'q'); @@ -182,7 +182,7 @@ pub fn add_initializer() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,typeck_tables_of,mir_built,optimized_mir")] + except="hir_owner_items,typeck_tables_of,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn add_initializer() { let _x: i16 = 3i16; @@ -198,7 +198,7 @@ pub fn change_initializer() { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_initializer() { let _x = 5u16; diff --git a/src/test/incremental/hashes/loop_expressions.rs b/src/test/incremental/hashes/loop_expressions.rs index a2222db4c59..7ce43559cff 100644 --- a/src/test/incremental/hashes/loop_expressions.rs +++ b/src/test/incremental/hashes/loop_expressions.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -47,7 +47,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -118,7 +118,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -143,7 +143,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -168,7 +168,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -193,7 +193,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/hashes/match_expressions.rs b/src/test/incremental/hashes/match_expressions.rs index 840b2222d90..30934c7c1d1 100644 --- a/src/test/incremental/hashes/match_expressions.rs +++ b/src/test/incremental/hashes/match_expressions.rs @@ -26,7 +26,7 @@ pub fn add_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_arm(x: u32) -> u32 { match x { @@ -51,7 +51,7 @@ pub fn change_order_of_arms(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_order_of_arms(x: u32) -> u32 { match x { @@ -75,7 +75,7 @@ pub fn add_guard_clause(x: u32, y: bool) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -99,7 +99,7 @@ pub fn change_guard_clause(x: u32, y: bool) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_guard_clause(x: u32, y: bool) -> u32 { match x { @@ -123,7 +123,7 @@ pub fn add_at_binding(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_at_binding(x: u32) -> u32 { match x { @@ -147,7 +147,7 @@ pub fn change_name_of_at_binding(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_of_at_binding(x: u32) -> u32 { match x { @@ -170,7 +170,7 @@ pub fn change_simple_name_to_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_simple_name_to_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -193,7 +193,7 @@ pub fn change_name_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_name_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -216,7 +216,7 @@ pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_mutability_of_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -238,7 +238,7 @@ pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_ref_to_binding_in_pattern(x: u32) -> u32 { match (x, x & 1) { @@ -260,7 +260,7 @@ pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", -except="HirBody,mir_built,optimized_mir,typeck_tables_of")] +except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_amp_to_binding_in_pattern(x: u32) -> u32 { match (&x, x & 1) { @@ -283,7 +283,7 @@ pub fn change_rhs_of_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir")] + except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_rhs_of_arm(x: u32) -> u32 { match x { @@ -307,7 +307,7 @@ pub fn add_alternative_to_arm(x: u32) -> u32 { #[cfg(not(cfail1))] #[rustc_clean(cfg="cfail2", - except="HirBody,mir_built,optimized_mir,typeck_tables_of")] + except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_alternative_to_arm(x: u32) -> u32 { match x { diff --git a/src/test/incremental/hashes/panic_exprs.rs b/src/test/incremental/hashes/panic_exprs.rs index 70b0a5ab78c..b46d1fac124 100644 --- a/src/test/incremental/hashes/panic_exprs.rs +++ b/src/test/incremental/hashes/panic_exprs.rs @@ -18,7 +18,7 @@ // Indexing expression -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn indexing(slice: &[u8]) -> u8 { #[cfg(cfail1)] @@ -33,7 +33,7 @@ pub fn indexing(slice: &[u8]) -> u8 { // Arithmetic overflow plus -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_plus(val: i32) -> i32 { #[cfg(cfail1)] @@ -48,7 +48,7 @@ pub fn arithmetic_overflow_plus(val: i32) -> i32 { // Arithmetic overflow minus -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_minus(val: i32) -> i32 { #[cfg(cfail1)] @@ -63,7 +63,7 @@ pub fn arithmetic_overflow_minus(val: i32) -> i32 { // Arithmetic overflow mult -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_mult(val: i32) -> i32 { #[cfg(cfail1)] @@ -78,7 +78,7 @@ pub fn arithmetic_overflow_mult(val: i32) -> i32 { // Arithmetic overflow negation -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn arithmetic_overflow_negation(val: i32) -> i32 { #[cfg(cfail1)] @@ -93,7 +93,7 @@ pub fn arithmetic_overflow_negation(val: i32) -> i32 { // Division by zero -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn division_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -107,7 +107,7 @@ pub fn division_by_zero(val: i32) -> i32 { } // Division by zero -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn mod_by_zero(val: i32) -> i32 { #[cfg(cfail1)] @@ -122,7 +122,7 @@ pub fn mod_by_zero(val: i32) -> i32 { // shift left -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_left(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] @@ -137,7 +137,7 @@ pub fn shift_left(val: i32, shift: usize) -> i32 { // shift right -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn shift_right(val: i32, shift: usize) -> i32 { #[cfg(cfail1)] diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index d70ebb08b71..1238259921d 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -21,7 +21,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub static STATIC_VISIBILITY: u8 = 0; @@ -31,7 +31,7 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] static mut STATIC_MUTABILITY: u8 = 0; @@ -41,7 +41,7 @@ static mut STATIC_MUTABILITY: u8 = 0; static STATIC_LINKAGE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[linkage="weak_odr"] static STATIC_LINKAGE: u8 = 0; @@ -52,7 +52,7 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[no_mangle] static STATIC_NO_MANGLE: u8 = 0; @@ -63,7 +63,7 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[thread_local] static STATIC_THREAD_LOCAL: u8 = 0; @@ -74,7 +74,7 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -84,13 +84,13 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_2: Option = None; // Change value between simple literals -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_1: i16 = { #[cfg(cfail1)] @@ -102,7 +102,7 @@ static STATIC_CHANGE_VALUE_1: i16 = { // Change value between expressions -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_2: i16 = { #[cfg(cfail1)] @@ -112,7 +112,7 @@ static STATIC_CHANGE_VALUE_2: i16 = { { 1 + 2 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_3: i16 = { #[cfg(cfail1)] @@ -122,7 +122,7 @@ static STATIC_CHANGE_VALUE_3: i16 = { { 2 * 3 } }; -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_VALUE_4: i16 = { #[cfg(cfail1)] @@ -144,11 +144,11 @@ mod static_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody,type_of")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index 7ae1798c7a2..0a4b8ae68c2 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -31,7 +31,7 @@ pub fn change_field_value_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_regular_struct() -> RegularStruct { RegularStruct { @@ -54,7 +54,7 @@ pub fn change_field_order_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_field_order_regular_struct() -> RegularStruct { RegularStruct { @@ -82,7 +82,7 @@ pub fn add_field_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_field_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -117,7 +117,7 @@ pub fn change_field_label_regular_struct() -> RegularStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_field_label_regular_struct() -> RegularStruct { let struct1 = RegularStruct { @@ -152,7 +152,7 @@ pub fn change_constructor_path_regular_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_regular_struct() { let _ = RegularStruct2 { @@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { @@ -196,7 +196,7 @@ pub fn change_field_value_tuple_struct() -> TupleStruct { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,optimized_mir,mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_field_value_tuple_struct() -> TupleStruct { TupleStruct(0, 1, 3) @@ -213,7 +213,7 @@ pub fn change_constructor_path_tuple_struct() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody,mir_built,typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_constructor_path_tuple_struct() { let _ = TupleStruct2(0, 1, 2); @@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,HirBody,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index e0c56964831..8bdc7f806d6 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -25,12 +25,12 @@ pub struct LayoutPacked; #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -42,12 +42,12 @@ struct LayoutC; #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -62,12 +62,12 @@ struct TupleStructFieldType(i32); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -85,12 +85,12 @@ struct TupleStructAddField(i32); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -107,12 +107,12 @@ struct TupleStructFieldVisibility(char); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -126,12 +126,12 @@ struct RecordStructFieldType { x: f32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -149,12 +149,12 @@ struct RecordStructFieldName { x: f32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -168,12 +168,12 @@ struct RecordStructAddField { x: f32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -189,12 +189,12 @@ struct RecordStructFieldVisibility { x: f32 } #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -210,12 +210,12 @@ struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -229,12 +229,12 @@ struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -248,12 +248,12 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -270,12 +270,12 @@ struct AddTypeParameter(T1, T1); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -294,12 +294,12 @@ struct AddTypeParameterBound(T); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -313,12 +313,12 @@ struct AddTypeParameterBoundWhereClause(T); #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -333,12 +333,12 @@ struct AddTypeParameterBoundWhereClause( // addresses taken into account by the hashing algorithm). // Note: there is no #[cfg(...)], so this is ALWAYS compiled #[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="HirBody", cfg="cfail2")] +#[rustc_clean(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -352,12 +352,12 @@ struct Visibility; #[cfg(not(cfail1))] #[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] -#[rustc_clean(label="HirBody", cfg="cfail3")] +#[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -374,12 +374,12 @@ mod tuple_struct_change_field_type_indirectly { use super::ReferencedType2 as FieldType; #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -397,12 +397,12 @@ mod record_struct_change_field_type_indirectly { use super::ReferencedType2 as FieldType; #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -425,12 +425,12 @@ mod change_trait_bound_indirectly { use super::ReferencedTrait2 as Trait; #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] @@ -445,12 +445,12 @@ mod change_trait_bound_indirectly_in_where_clause { use super::ReferencedTrait2 as Trait; #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] #[rustc_clean(label="predicates_of", cfg="cfail3")] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index 3006cdccfbb..d3e94640268 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -140,8 +140,8 @@ trait TraitChangeMethodParameterName { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn with_default(y: i32) {} } @@ -260,8 +260,8 @@ trait TraitChangeModeSelfOwnToMut: Sized { trait TraitChangeModeSelfOwnToMut: Sized { #[rustc_dirty(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn method(mut self) {} } diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index fa28b2ebedd..3e8d884be1f 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -64,8 +64,8 @@ impl ChangeMethodBodyTrait for Foo { impl ChangeMethodBodyTrait for Foo { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn method_name() { () } @@ -91,8 +91,8 @@ impl ChangeMethodBodyTraitInlined for Foo { impl ChangeMethodBodyTraitInlined for Foo { #[rustc_clean(label="Hir", cfg="cfail2")] #[rustc_clean(label="Hir", cfg="cfail3")] - #[rustc_dirty(label="HirBody", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail3")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[inline] fn method_name() { panic!() diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index 264e8f926ff..b50eeb46f96 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,HirBody")] +#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] + #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 776a0273ca7..9b63003482f 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -21,7 +21,7 @@ pub fn const_negation() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn const_negation() -> i32 { -1 @@ -36,7 +36,7 @@ pub fn const_bitwise_not() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn const_bitwise_not() -> i32 { !99 @@ -51,7 +51,7 @@ pub fn var_negation(x: i32, y: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_negation(x: i32, y: i32) -> i32 { -y @@ -66,7 +66,7 @@ pub fn var_bitwise_not(x: i32, y: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_bitwise_not(x: i32, y: i32) -> i32 { !y @@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y @@ -96,7 +96,7 @@ pub fn first_const_add() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn first_const_add() -> i32 { 2 + 3 @@ -111,7 +111,7 @@ pub fn second_const_add() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn second_const_add() -> i32 { 1 + 3 @@ -126,7 +126,7 @@ pub fn first_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn first_var_add(a: i32, b: i32) -> i32 { b + 2 @@ -141,7 +141,7 @@ pub fn second_var_add(a: i32, b: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn second_var_add(a: i32, b: i32) -> i32 { 1 + b @@ -156,7 +156,7 @@ pub fn plus_to_minus(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_minus(a: i32) -> i32 { 1 - a @@ -171,7 +171,7 @@ pub fn plus_to_mult(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_mult(a: i32) -> i32 { 1 * a @@ -186,7 +186,7 @@ pub fn plus_to_div(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_div(a: i32) -> i32 { 1 / a @@ -201,7 +201,7 @@ pub fn plus_to_mod(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn plus_to_mod(a: i32) -> i32 { 1 % a @@ -216,7 +216,7 @@ pub fn and_to_or(a: bool, b: bool) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn and_to_or(a: bool, b: bool) -> bool { a || b @@ -231,7 +231,7 @@ pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_bitwise_or(a: i32) -> i32 { 1 | a @@ -246,7 +246,7 @@ pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_bitwise_xor(a: i32) -> i32 { 1 ^ a @@ -261,7 +261,7 @@ pub fn bitwise_and_to_lshift(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_lshift(a: i32) -> i32 { a << 1 @@ -276,7 +276,7 @@ pub fn bitwise_and_to_rshift(a: i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn bitwise_and_to_rshift(a: i32) -> i32 { a >> 1 @@ -291,7 +291,7 @@ pub fn eq_to_uneq(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_uneq(a: i32) -> bool { a != 1 @@ -306,7 +306,7 @@ pub fn eq_to_lt(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_lt(a: i32) -> bool { a < 1 @@ -321,7 +321,7 @@ pub fn eq_to_gt(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_gt(a: i32) -> bool { a > 1 @@ -336,7 +336,7 @@ pub fn eq_to_le(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_le(a: i32) -> bool { a <= 1 @@ -351,7 +351,7 @@ pub fn eq_to_ge(a: i32) -> bool { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn eq_to_ge(a: i32) -> bool { a >= 1 @@ -368,7 +368,7 @@ pub fn type_cast(a: u8) -> u64 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn type_cast(a: u8) -> u64 { let b = a as u32; @@ -385,7 +385,7 @@ pub fn value_cast(a: u32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn value_cast(a: u32) -> i32 { 2 as i32 @@ -403,7 +403,7 @@ pub fn place() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn place() -> i32 { let mut x = 10; @@ -423,7 +423,7 @@ pub fn rvalue() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn rvalue() -> i32 { let mut x = 10; @@ -440,7 +440,7 @@ pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { } #[cfg(not(cfail1))] -#[rustc_clean(except="HirBody,optimized_mir,mir_built", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn index_to_slice(s: &[u8], i: usize, j: usize) -> u8 { s[j] diff --git a/src/test/incremental/hashes/while_let_loops.rs b/src/test/incremental/hashes/while_let_loops.rs index 615f1fe1fd0..908f60440fa 100644 --- a/src/test/incremental/hashes/while_let_loops.rs +++ b/src/test/incremental/hashes/while_let_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -141,7 +141,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -216,7 +216,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] 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 a427ffb96e3..365ec5fa567 100644 --- a/src/test/incremental/hashes/while_loops.rs +++ b/src/test/incremental/hashes/while_loops.rs @@ -25,7 +25,7 @@ pub fn change_loop_body() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_body() { let mut _x = 0; @@ -48,7 +48,7 @@ pub fn change_loop_condition() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_loop_condition() { let mut _x = 0; @@ -70,7 +70,7 @@ pub fn add_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir, typeck_tables_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir, typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn add_break() { let mut _x = 0; @@ -93,7 +93,7 @@ pub fn add_loop_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label() { let mut _x = 0; @@ -116,7 +116,7 @@ pub fn add_loop_label_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_break() { let mut _x = 0; @@ -141,7 +141,7 @@ pub fn change_break_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_break_label() { let mut _x = 0; @@ -166,7 +166,7 @@ pub fn add_loop_label_to_continue() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_loop_label_to_continue() { let mut _x = 0; @@ -191,7 +191,7 @@ pub fn change_continue_label() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_label() { let mut _x = 0; @@ -216,7 +216,7 @@ pub fn change_continue_to_break() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, optimized_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_continue_to_break() { let mut _x = 0; diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs index 9dfd2ae2511..9d731636142 100644 --- a/src/test/incremental/ich_method_call_trait_scope.rs +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -27,14 +27,14 @@ mod mod3 { use Trait2; #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_dirty(label="typeck_tables_of", cfg="rpass2")] fn bar() { ().method(); } #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_clean(label="typeck_tables_of", cfg="rpass2")] fn baz() { 22; // no method call, traits in scope don't matter diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index b2b7e663151..54db7a2116d 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -8,13 +8,13 @@ #![feature(rustc_attrs)] #[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_dirty(label="HirBody", cfg="cfail2")] +#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] pub fn foo() { #[cfg(cfail1)] pub fn baz() { } // order is different... #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="HirBody", cfg="cfail2")] + #[rustc_clean(label="hir_owner_items", cfg="cfail2")] pub fn bar() { } // but that doesn't matter. #[cfg(cfail2)] diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 0e4ab6b78e2..723c367af9e 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -29,17 +29,17 @@ mod mod3 { use mod2::Foo; #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_clean(label="Hir", cfg="rpass3")] - #[rustc_dirty(label="HirBody", cfg="rpass3")] + #[rustc_dirty(label="hir_owner_items", cfg="rpass3")] fn in_expr() { Foo(0); } #[rustc_clean(label="Hir", cfg="rpass2")] - #[rustc_clean(label="HirBody", cfg="rpass2")] + #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_clean(label="Hir", cfg="rpass3")] - #[rustc_dirty(label="HirBody", cfg="rpass3")] + #[rustc_dirty(label="hir_owner_items", cfg="rpass3")] fn in_type() { test::(); } diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs index 51ea7d6d447..ea81d3e5862 100644 --- a/src/test/incremental/source_loc_macros.rs +++ b/src/test/incremental/source_loc_macros.rs @@ -8,25 +8,25 @@ #![feature(rustc_attrs)] #[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn line_same() { let _ = line!(); } #[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn col_same() { let _ = column!(); } #[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_clean(label="HirBody", cfg="rpass2")] +#[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn file_same() { let _ = file!(); } #[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_items", cfg="rpass2")] fn line_different() { #[cfg(rpass1)] { @@ -39,7 +39,7 @@ fn line_different() { } #[rustc_clean(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_items", cfg="rpass2")] fn col_different() { #[cfg(rpass1)] { diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index e6fdc7cb3a0..1a1ab95598d 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -13,5 +13,5 @@ pub fn main() {} #[cfg(rpass2)] #[rustc_dirty(label="Hir", cfg="rpass2")] -#[rustc_dirty(label="HirBody", cfg="rpass2")] +#[rustc_dirty(label="hir_owner_items", cfg="rpass2")] pub fn main() {} diff --git a/src/test/incremental/string_constant.rs b/src/test/incremental/string_constant.rs index b88acd2af75..11a42262c16 100644 --- a/src/test/incremental/string_constant.rs +++ b/src/test/incremental/string_constant.rs @@ -18,7 +18,7 @@ pub mod x { } #[cfg(cfail2)] - #[rustc_dirty(label="HirBody", cfg="cfail2")] + #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="optimized_mir", cfg="cfail2")] pub fn x() { println!("{}", "2"); From 274fb668b435b20e5132f02d4aa11a29500eff01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 16:00:15 +0100 Subject: [PATCH 1135/1250] Replace `Hir` with `hir_owner` in tests --- .../incremental/hashes/call_expressions.rs | 6 +- src/test/incremental/hashes/consts.rs | 10 +- .../incremental/hashes/enum_constructors.rs | 6 +- src/test/incremental/hashes/enum_defs.rs | 52 +-- .../incremental/hashes/exported_vs_not.rs | 6 +- .../incremental/hashes/function_interfaces.rs | 48 +- .../hashes/indexing_expressions.rs | 28 +- src/test/incremental/hashes/inherent_impls.rs | 44 +- src/test/incremental/hashes/statics.rs | 18 +- .../incremental/hashes/struct_constructors.rs | 4 +- src/test/incremental/hashes/struct_defs.rs | 84 ++-- src/test/incremental/hashes/trait_defs.rs | 416 +++++++++--------- src/test/incremental/hashes/trait_impls.rs | 148 +++---- src/test/incremental/hashes/type_defs.rs | 32 +- .../ich_method_call_trait_scope.rs | 4 +- src/test/incremental/ich_nested_items.rs | 4 +- src/test/incremental/ich_resolve_results.rs | 8 +- .../incremental/inlined_hir_34991/main.rs | 2 +- src/test/incremental/source_loc_macros.rs | 10 +- .../span_hash_stable/auxiliary/sub1.rs | 2 +- .../span_hash_stable/auxiliary/sub2.rs | 2 +- .../spans_significant_w_debuginfo.rs | 2 +- src/test/incremental/unchecked_dirty_clean.rs | 8 +- 23 files changed, 472 insertions(+), 472 deletions(-) diff --git a/src/test/incremental/hashes/call_expressions.rs b/src/test/incremental/hashes/call_expressions.rs index e5478e5ec90..87f108abadd 100644 --- a/src/test/incremental/hashes/call_expressions.rs +++ b/src/test/incremental/hashes/call_expressions.rs @@ -55,8 +55,8 @@ mod change_callee_indirectly_function { #[cfg(not(cfail1))] use super::callee2 as callee; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] @@ -152,7 +152,7 @@ pub fn change_to_ufcs() { #[rustc_clean(cfg="cfail2", except="hir_owner_items,mir_built,optimized_mir,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] // One might think this would be expanded in the hir_owner_items/Mir, but it actually -// results in slightly different Hir/Mir. +// results in slightly different hir_owner/Mir. pub fn change_to_ufcs() { let s = Struct; Struct::method1(&s, 'x', true); diff --git a/src/test/incremental/hashes/consts.rs b/src/test/incremental/hashes/consts.rs index ef4598ab3b6..8f77bb24f87 100644 --- a/src/test/incremental/hashes/consts.rs +++ b/src/test/incremental/hashes/consts.rs @@ -19,7 +19,7 @@ const CONST_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub const CONST_VISIBILITY: u8 = 0; @@ -29,7 +29,7 @@ pub const CONST_VISIBILITY: u8 = 0; const CONST_CHANGE_TYPE_1: i32 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_1: u32 = 0; @@ -39,7 +39,7 @@ const CONST_CHANGE_TYPE_1: u32 = 0; const CONST_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_2: Option = None; @@ -99,11 +99,11 @@ mod const_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] const CONST_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/enum_constructors.rs b/src/test/incremental/hashes/enum_constructors.rs index 703e62d5fe1..5ad6eeafc7f 100644 --- a/src/test/incremental/hashes/enum_constructors.rs +++ b/src/test/incremental/hashes/enum_constructors.rs @@ -139,7 +139,7 @@ pub mod change_constructor_path_indirectly_struct_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -232,7 +232,7 @@ pub mod change_constructor_path_indirectly_tuple_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] @@ -309,7 +309,7 @@ pub mod change_constructor_path_indirectly_c_like { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,\ + except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,\ typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] diff --git a/src/test/incremental/hashes/enum_defs.rs b/src/test/incremental/hashes/enum_defs.rs index 3925d222701..7be15b4bb15 100644 --- a/src/test/incremental/hashes/enum_defs.rs +++ b/src/test/incremental/hashes/enum_defs.rs @@ -26,7 +26,7 @@ enum EnumVisibility { A } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub enum EnumVisibility { A @@ -42,7 +42,7 @@ enum EnumChangeNameCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameCStyleVariant { Variant1, @@ -59,7 +59,7 @@ enum EnumChangeNameTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameTupleStyleVariant { Variant1, @@ -76,7 +76,7 @@ enum EnumChangeNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeNameStructStyleVariant { Variant1, @@ -109,7 +109,7 @@ enum EnumChangeValueCStyleVariant1 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeValueCStyleVariant1 { Variant1, @@ -125,7 +125,7 @@ enum EnumAddCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddCStyleVariant { Variant1, @@ -142,7 +142,7 @@ enum EnumRemoveCStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveCStyleVariant { Variant1, @@ -157,7 +157,7 @@ enum EnumAddTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddTupleStyleVariant { Variant1, @@ -174,7 +174,7 @@ enum EnumRemoveTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveTupleStyleVariant { Variant1, @@ -189,7 +189,7 @@ enum EnumAddStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddStructStyleVariant { Variant1, @@ -206,7 +206,7 @@ enum EnumRemoveStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumRemoveStructStyleVariant { Variant1, @@ -221,7 +221,7 @@ enum EnumChangeFieldTypeTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeTupleStyleVariant { Variant1(u32, @@ -238,7 +238,7 @@ enum EnumChangeFieldTypeStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldTypeStructStyleVariant { Variant1, @@ -257,7 +257,7 @@ enum EnumChangeFieldNameStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldNameStructStyleVariant { Variant1 { a: u32, c: u32 }, @@ -272,7 +272,7 @@ enum EnumChangeOrderTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumChangeOrderTupleStyleVariant { Variant1( @@ -289,7 +289,7 @@ enum EnumChangeFieldOrderStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumChangeFieldOrderStructStyleVariant { Variant1 { b: f32, a: u32 }, @@ -304,7 +304,7 @@ enum EnumAddFieldTupleStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldTupleStyleVariant { Variant1(u32, u32, u32), @@ -319,7 +319,7 @@ enum EnumAddFieldStructStyleVariant { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] enum EnumAddFieldStructStyleVariant { Variant1 { a: u32, b: u32, c: u32 }, @@ -335,7 +335,7 @@ enum EnumAddMustUse { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[must_use] enum EnumAddMustUse { @@ -353,7 +353,7 @@ enum EnumAddReprC { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] #[repr(C)] enum EnumAddReprC { @@ -531,7 +531,7 @@ enum EnumSwapUsageTypeParameters { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageTypeParameters { Variant1 { @@ -552,7 +552,7 @@ enum EnumSwapUsageLifetimeParameters<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum EnumSwapUsageLifetimeParameters<'a, 'b> { Variant1 { @@ -577,7 +577,7 @@ mod change_field_type_indirectly_tuple_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum TupleStyle { Variant1( @@ -595,7 +595,7 @@ mod change_field_type_indirectly_struct_style { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] enum StructStyle { Variant1 { @@ -618,7 +618,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum { Variant1(T) @@ -634,7 +634,7 @@ mod change_trait_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] enum Enum where T: Trait { Variant1(T) diff --git a/src/test/incremental/hashes/exported_vs_not.rs b/src/test/incremental/hashes/exported_vs_not.rs index 76d33aa2085..b546930ea8f 100644 --- a/src/test/incremental/hashes/exported_vs_not.rs +++ b/src/test/incremental/hashes/exported_vs_not.rs @@ -8,7 +8,7 @@ // Case 1: The function body is not exported to metadata. If the body changes, // the hash of the hir_owner_items node should change, but not the hash of -// either the Hir or the Metadata node. +// either the hir_owner or the Metadata node. #[cfg(cfail1)] pub fn body_not_exported_to_metadata() -> u32 { @@ -25,7 +25,7 @@ pub fn body_not_exported_to_metadata() -> u32 { // Case 2: The function body *is* exported to metadata because the function is -// marked as #[inline]. Only the hash of the Hir depnode should be +// marked as #[inline]. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. #[cfg(cfail1)] @@ -45,7 +45,7 @@ pub fn body_exported_to_metadata_because_of_inline() -> u32 { // Case 2: The function body *is* exported to metadata because the function is -// generic. Only the hash of the Hir depnode should be +// generic. Only the hash of the hir_owner depnode should be // unaffected by a change to the body. #[cfg(cfail1)] diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index 3109af2d393..a7d2d76cf26 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -23,7 +23,7 @@ pub fn add_parameter() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn add_parameter(p: i32) {} @@ -34,7 +34,7 @@ pub fn add_parameter(p: i32) {} pub fn add_return_type() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] pub fn add_return_type() -> () {} @@ -46,7 +46,7 @@ pub fn type_of_parameter(p: i32) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter(p: i64) {} @@ -58,7 +58,7 @@ pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter_ref(p: &mut i32) {} @@ -70,7 +70,7 @@ pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn order_of_parameters(p2: i64, p1: i32) {} @@ -82,7 +82,7 @@ pub fn make_unsafe() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub unsafe fn make_unsafe() {} @@ -93,7 +93,7 @@ pub unsafe fn make_unsafe() {} pub fn make_extern() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} @@ -105,7 +105,7 @@ pub fn type_parameter() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn type_parameter() {} @@ -116,7 +116,7 @@ pub fn type_parameter() {} pub fn lifetime_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, generics_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, generics_of")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} @@ -127,7 +127,7 @@ pub fn lifetime_parameter<'a>() {} pub fn trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} @@ -138,7 +138,7 @@ pub fn trait_bound() {} pub fn builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn builtin_bound() {} @@ -150,7 +150,7 @@ pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} @@ -161,7 +161,7 @@ pub fn lifetime_bound<'a, T: 'a>() {} pub fn second_trait_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} @@ -172,7 +172,7 @@ pub fn second_trait_bound() {} pub fn second_builtin_bound() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_builtin_bound() {} @@ -184,7 +184,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, generics_of, type_of, predicates_of")] + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} @@ -195,7 +195,7 @@ pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} pub fn inline() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[inline] pub fn inline() {} @@ -208,7 +208,7 @@ pub fn inline() {} pub fn inline_never() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[inline(never)] pub fn inline_never() {} @@ -220,7 +220,7 @@ pub fn inline_never() {} pub fn no_mangle() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[no_mangle] pub fn no_mangle() {} @@ -232,7 +232,7 @@ pub fn no_mangle() {} pub fn linkage() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items")] #[rustc_clean(cfg = "cfail3")] #[linkage = "weak_odr"] pub fn linkage() {} @@ -246,7 +246,7 @@ pub fn return_impl_trait() -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, typeck_tables_of, fn_sig")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn return_impl_trait() -> impl Clone { 0 @@ -280,7 +280,7 @@ pub mod change_return_type_indirectly { use super::ReferencedType2 as ReturnType; #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_return_type() -> ReturnType { ReturnType {} @@ -297,7 +297,7 @@ pub mod change_parameter_type_indirectly { use super::ReferencedType2 as ParameterType; #[rustc_clean(cfg = "cfail2", - except = "Hir, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_parameter_type(p: ParameterType) {} } @@ -314,7 +314,7 @@ pub mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound(p: T) {} } @@ -328,7 +328,7 @@ pub mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg = "cfail2", except = "Hir, hir_owner_items, predicates_of")] + #[rustc_clean(cfg = "cfail2", except = "hir_owner, hir_owner_items, predicates_of")] #[rustc_clean(cfg = "cfail3")] pub fn indirect_trait_bound_where(p: T) where diff --git a/src/test/incremental/hashes/indexing_expressions.rs b/src/test/incremental/hashes/indexing_expressions.rs index 2a0eacd4dc1..84c0298918e 100644 --- a/src/test/incremental/hashes/indexing_expressions.rs +++ b/src/test/incremental/hashes/indexing_expressions.rs @@ -20,8 +20,8 @@ fn change_simple_index(slice: &[u32]) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_simple_index(slice: &[u32]) -> u32 { @@ -37,8 +37,8 @@ fn change_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_lower_bound(slice: &[u32]) -> &[u32] { @@ -54,8 +54,8 @@ fn change_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_upper_bound(slice: &[u32]) -> &[u32] { @@ -71,8 +71,8 @@ fn add_lower_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn add_lower_bound(slice: &[u32]) -> &[u32] { @@ -88,8 +88,8 @@ fn add_upper_bound(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn add_upper_bound(slice: &[u32]) -> &[u32] { @@ -105,8 +105,8 @@ fn change_mutability(slice: &mut [u32]) -> u32 { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn change_mutability(slice: &mut [u32]) -> u32 { @@ -122,8 +122,8 @@ fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn exclusive_to_inclusive_range(slice: &[u32]) -> &[u32] { diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index f4fb601d07b..c0b80a92df6 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -23,7 +23,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail3")] @@ -85,10 +85,10 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="associated_item,Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="associated_item,hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] fn method_privacy() { } } @@ -100,7 +100,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] @@ -120,7 +120,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn method_selfmutness(&mut self) { } @@ -135,7 +135,7 @@ impl Foo { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,associated_item_def_ids")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,associated_item_def_ids")] #[rustc_clean(cfg="cfail3")] impl Foo { #[rustc_clean(cfg="cfail2")] @@ -160,7 +160,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub fn add_method_parameter(&self, _: i32) { } @@ -197,7 +197,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,fn_sig,optimized_mir,mir_built,typeck_tables_of")] + except="hir_owner,hir_owner_items,fn_sig,optimized_mir,mir_built,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub fn change_method_return_type(&self) -> u8 { 0 } } @@ -214,7 +214,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[inline] pub fn make_method_inline(&self) -> u8 { 0 } @@ -251,7 +251,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" + except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of,optimized_mir,mir_built" )] #[rustc_clean(cfg="cfail3")] pub unsafe fn make_method_unsafe(&self) { } @@ -269,7 +269,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern fn make_method_extern(&self) { } } @@ -286,7 +286,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,fn_sig,typeck_tables_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,fn_sig,typeck_tables_of")] #[rustc_clean(cfg="cfail3")] pub extern "system" fn change_method_calling_convention(&self) { } } @@ -312,7 +312,7 @@ impl Foo { // if we lower generics before the body, then the `HirId` for // things in the body will be affected. So if you start to see // `typeck_tables_of` appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_parameter_to_method<'a>(&self) { } } @@ -340,7 +340,7 @@ impl Foo { // appear dirty, that might be the cause. -nmatsakis #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,generics_of,predicates_of,type_of", + except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of", )] #[rustc_clean(cfg="cfail3")] pub fn add_type_parameter_to_method(&self) { } @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="Hir,hir_owner_items,generics_of,predicates_of,type_of,typeck_tables_of" + except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } @@ -387,7 +387,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,generics_of,predicates_of,\ + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of,predicates_of,\ type_of")] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_type_param_of_method<'a, T: 'a>(&self) { } @@ -414,7 +414,7 @@ impl Foo { // generics before the body, then the `HirId` for things in the // body will be affected. So if you start to see `typeck_tables_of` // appear dirty, that might be the cause. -nmatsakis - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,predicates_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,predicates_of")] #[rustc_clean(cfg="cfail3")] pub fn add_trait_bound_to_type_param_of_method(&self) { } } @@ -431,7 +431,7 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[no_mangle] pub fn add_no_mangle_to_method(&self) { } @@ -448,7 +448,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,generics_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,generics_of")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean( @@ -468,7 +468,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2", except="fn_sig,optimized_mir,mir_built,typeck_tables_of")] @@ -485,7 +485,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] @@ -502,7 +502,7 @@ impl Bar { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] impl Bar { #[rustc_clean(cfg="cfail2")] diff --git a/src/test/incremental/hashes/statics.rs b/src/test/incremental/hashes/statics.rs index 1238259921d..536b7932473 100644 --- a/src/test/incremental/hashes/statics.rs +++ b/src/test/incremental/hashes/statics.rs @@ -21,7 +21,7 @@ static STATIC_VISIBILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] pub static STATIC_VISIBILITY: u8 = 0; @@ -31,7 +31,7 @@ pub static STATIC_VISIBILITY: u8 = 0; static STATIC_MUTABILITY: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] static mut STATIC_MUTABILITY: u8 = 0; @@ -41,7 +41,7 @@ static mut STATIC_MUTABILITY: u8 = 0; static STATIC_LINKAGE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[linkage="weak_odr"] static STATIC_LINKAGE: u8 = 0; @@ -52,7 +52,7 @@ static STATIC_LINKAGE: u8 = 0; static STATIC_NO_MANGLE: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[no_mangle] static STATIC_NO_MANGLE: u8 = 0; @@ -63,7 +63,7 @@ static STATIC_NO_MANGLE: u8 = 0; static STATIC_THREAD_LOCAL: u8 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] #[thread_local] static STATIC_THREAD_LOCAL: u8 = 0; @@ -74,7 +74,7 @@ static STATIC_THREAD_LOCAL: u8 = 0; static STATIC_CHANGE_TYPE_1: i16 = 0; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_1: u64 = 0; @@ -84,7 +84,7 @@ static STATIC_CHANGE_TYPE_1: u64 = 0; static STATIC_CHANGE_TYPE_2: Option = None; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_2: Option = None; @@ -144,11 +144,11 @@ mod static_change_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as Type; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_1: Type = Type; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items,type_of")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items,type_of")] #[rustc_clean(cfg="cfail3")] static STATIC_CHANGE_TYPE_INDIRECTLY_2: Option = None; } diff --git a/src/test/incremental/hashes/struct_constructors.rs b/src/test/incremental/hashes/struct_constructors.rs index 0a4b8ae68c2..89b18eefd06 100644 --- a/src/test/incremental/hashes/struct_constructors.rs +++ b/src/test/incremental/hashes/struct_constructors.rs @@ -173,7 +173,7 @@ pub mod change_constructor_path_indirectly_regular_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { @@ -230,7 +230,7 @@ pub mod change_constructor_path_indirectly_tuple_struct { #[rustc_clean( cfg="cfail2", - except="fn_sig,Hir,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" + except="fn_sig,hir_owner,hir_owner_items,optimized_mir,mir_built,typeck_tables_of" )] #[rustc_clean(cfg="cfail3")] pub fn function() -> Struct { diff --git a/src/test/incremental/hashes/struct_defs.rs b/src/test/incremental/hashes/struct_defs.rs index 8bdc7f806d6..fa08b7ec1ed 100644 --- a/src/test/incremental/hashes/struct_defs.rs +++ b/src/test/incremental/hashes/struct_defs.rs @@ -24,12 +24,12 @@ pub struct LayoutPacked; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -41,12 +41,12 @@ pub struct LayoutPacked; struct LayoutC; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -61,12 +61,12 @@ struct LayoutC; struct TupleStructFieldType(i32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -84,12 +84,12 @@ struct TupleStructFieldType( struct TupleStructAddField(i32); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -106,12 +106,12 @@ struct TupleStructAddField( struct TupleStructFieldVisibility(char); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -125,12 +125,12 @@ struct TupleStructFieldVisibility(pub char); struct RecordStructFieldType { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -148,12 +148,12 @@ struct RecordStructFieldType { struct RecordStructFieldName { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -167,12 +167,12 @@ struct RecordStructFieldName { y: f32 } struct RecordStructAddField { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -188,12 +188,12 @@ struct RecordStructAddField { struct RecordStructFieldVisibility { x: f32 } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -209,12 +209,12 @@ struct RecordStructFieldVisibility { struct AddLifetimeParameter<'a>(&'a f32, &'a f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -228,12 +228,12 @@ struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64); struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -247,12 +247,12 @@ struct AddLifetimeParameterBound<'a, 'b: 'a>( struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -269,12 +269,12 @@ struct AddLifetimeParameterBoundWhereClause<'a, 'b>( struct AddTypeParameter(T1, T1); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_dirty(label="type_of", cfg="cfail2")] #[rustc_dirty(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -293,12 +293,12 @@ struct AddTypeParameter( struct AddTypeParameterBound(T); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -312,12 +312,12 @@ struct AddTypeParameterBound( struct AddTypeParameterBoundWhereClause(T); #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -332,12 +332,12 @@ struct AddTypeParameterBoundWhereClause( // fingerprint is stable (i.e., that there are no random influences like memory // addresses taken into account by the hashing algorithm). // Note: there is no #[cfg(...)], so this is ALWAYS compiled -#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -351,12 +351,12 @@ pub struct EmptyStruct; struct Visibility; #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -373,12 +373,12 @@ mod tuple_struct_change_field_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -396,12 +396,12 @@ mod record_struct_change_field_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as FieldType; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_clean(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -424,12 +424,12 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] @@ -444,12 +444,12 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="type_of", cfg="cfail2")] #[rustc_clean(label="generics_of", cfg="cfail2")] #[rustc_dirty(label="predicates_of", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[rustc_clean(label="type_of", cfg="cfail3")] #[rustc_clean(label="generics_of", cfg="cfail3")] diff --git a/src/test/incremental/hashes/trait_defs.rs b/src/test/incremental/hashes/trait_defs.rs index d3e94640268..df41b73f92c 100644 --- a/src/test/incremental/hashes/trait_defs.rs +++ b/src/test/incremental/hashes/trait_defs.rs @@ -25,8 +25,8 @@ trait TraitVisibility { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait TraitVisibility { } @@ -36,8 +36,8 @@ pub trait TraitVisibility { } trait TraitUnsafety { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] unsafe trait TraitUnsafety { } @@ -48,8 +48,8 @@ trait TraitAddMethod { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait TraitAddMethod { fn method(); } @@ -63,8 +63,8 @@ trait TraitChangeMethodName { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodName { fn methodChanged(); } @@ -78,11 +78,11 @@ trait TraitAddReturnType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> u32; } @@ -95,11 +95,11 @@ trait TraitChangeReturnType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> u64; } @@ -112,11 +112,11 @@ trait TraitAddParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: u32); } @@ -130,16 +130,16 @@ trait TraitChangeMethodParameterName { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterName { // FIXME(#38501) This should preferably always be clean. - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(b: u32); - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn with_default(y: i32) {} @@ -154,11 +154,11 @@ trait TraitChangeMethodParameterType { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: i64); } @@ -171,11 +171,11 @@ trait TraitChangeMethodParameterTypeRef { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParameterTypeRef { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: &mut i32); } @@ -188,11 +188,11 @@ trait TraitChangeMethodParametersOrder { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeMethodParametersOrder { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(b: i64, a: i32); } @@ -205,11 +205,11 @@ trait TraitAddMethodAutoImplementation { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddMethodAutoImplementation { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() { } } @@ -223,8 +223,8 @@ trait TraitChangeOrderOfMethods { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeOrderOfMethods { fn method1(); fn method0(); @@ -239,11 +239,11 @@ trait TraitChangeModeSelfRefToMut { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfRefToMut { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(&mut self); } @@ -255,11 +255,11 @@ trait TraitChangeModeSelfOwnToMut: Sized { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfOwnToMut: Sized { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn method(mut self) {} @@ -273,11 +273,11 @@ trait TraitChangeModeSelfOwnToRef { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeModeSelfOwnToRef { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(&self); } @@ -290,11 +290,11 @@ trait TraitAddUnsafeModifier { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddUnsafeModifier { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] unsafe fn method(); } @@ -307,11 +307,11 @@ trait TraitAddExternModifier { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddExternModifier { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] extern fn method(); } @@ -324,11 +324,11 @@ trait TraitChangeExternCToRustIntrinsic { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeExternCToRustIntrinsic { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] extern "stdcall" fn method(); } @@ -341,11 +341,11 @@ trait TraitAddTypeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTypeParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -358,11 +358,11 @@ trait TraitAddLifetimeParameterToMethod { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeParameterToMethod { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a>(); } @@ -379,11 +379,11 @@ trait TraitAddTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -396,11 +396,11 @@ trait TraitAddBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -413,11 +413,11 @@ trait TraitAddLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToMethodLifetimeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a, 'b: 'a>(a: &'a u32, b: &'b u32); } @@ -430,11 +430,11 @@ trait TraitAddSecondTraitBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -447,11 +447,11 @@ trait TraitAddSecondBuiltinBoundToMethodTypeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -464,11 +464,11 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method<'a, 'b, 'c: 'a + 'b>(a: &'a u32, b: &'b u32, c: &'c u32); } @@ -478,14 +478,14 @@ trait TraitAddSecondLifetimeBoundToMethodLifetimeParameter { #[cfg(cfail1)] trait TraitAddAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddAssociatedType { type Associated; @@ -506,11 +506,11 @@ trait TraitAddTraitBoundToAssociatedType { // Apparently the type bound contributes to the predicates of the trait, but // does not change the associated item itself. #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated: ReferencedTrait0; fn method(); @@ -527,11 +527,11 @@ trait TraitAddLifetimeBoundToAssociatedType<'a> { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToAssociatedType<'a> { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated: 'a; fn method(); @@ -548,11 +548,11 @@ trait TraitAddDefaultToAssociatedType { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddDefaultToAssociatedType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] type Associated = ReferenceType0; fn method(); @@ -567,8 +567,8 @@ trait TraitAddAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddAssociatedConstant { const Value: u32; @@ -586,15 +586,15 @@ trait TraitAddInitializerToAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddInitializerToAssociatedConstant { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] const Value: u32 = 1; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -609,15 +609,15 @@ trait TraitChangeTypeOfAssociatedConstant { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTypeOfAssociatedConstant { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] const Value: f64; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(); } @@ -628,8 +628,8 @@ trait TraitChangeTypeOfAssociatedConstant { trait TraitAddSuperTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSuperTrait : ReferencedTrait0 { } @@ -639,8 +639,8 @@ trait TraitAddSuperTrait : ReferencedTrait0 { } trait TraitAddBuiltiBound { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltiBound : Send { } @@ -650,8 +650,8 @@ trait TraitAddBuiltiBound : Send { } trait TraitAddStaticLifetimeBound { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticLifetimeBound : 'static { } @@ -661,16 +661,16 @@ trait TraitAddStaticLifetimeBound : 'static { } trait TraitAddTraitAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitAsSecondBound : ReferencedTrait0 + ReferencedTrait1 { } #[cfg(cfail1)] trait TraitAddTraitAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } @@ -680,16 +680,16 @@ trait TraitAddTraitAsSecondBoundFromBuiltin : Send + ReferencedTrait0 { } trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundAsSecondBound : ReferencedTrait0 + Send { } #[cfg(cfail1)] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } @@ -699,16 +699,16 @@ trait TraitAddBuiltinBoundAsSecondBoundFromBuiltin: Send + Copy { } trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticBoundAsSecondBound : ReferencedTrait0 + 'static { } #[cfg(cfail1)] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } @@ -718,8 +718,8 @@ trait TraitAddStaticBoundAsSecondBoundFromBuiltin : Send + 'static { } trait TraitAddTypeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTypeParameterToTrait { } @@ -729,8 +729,8 @@ trait TraitAddTypeParameterToTrait { } trait TraitAddLifetimeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeParameterToTrait<'a> { } @@ -740,8 +740,8 @@ trait TraitAddLifetimeParameterToTrait<'a> { } trait TraitAddTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToTypeParameterOfTrait { } @@ -751,8 +751,8 @@ trait TraitAddTraitBoundToTypeParameterOfTrait { } trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } @@ -762,8 +762,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTrait<'a, T: 'a> { } trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } @@ -773,8 +773,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b> { } trait TraitAddBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToTypeParameterOfTrait { } @@ -784,8 +784,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTrait { } trait TraitAddSecondTypeParameterToTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTypeParameterToTrait { } @@ -795,8 +795,8 @@ trait TraitAddSecondTypeParameterToTrait { } trait TraitAddSecondLifetimeParameterToTrait<'a> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } @@ -806,8 +806,8 @@ trait TraitAddSecondLifetimeParameterToTrait<'a, 'b> { } trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } @@ -817,8 +817,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } @@ -828,8 +828,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTrait<'a, 'b, T: 'a + 'b> { } trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b, 'b, 'c> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> { } @@ -839,8 +839,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTrait<'a: 'b + 'c, 'b, 'c> trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTrait { } @@ -855,8 +855,8 @@ struct ReferenceType1 {} trait TraitAddTraitBoundToTypeParameterOfTraitWhere { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } @@ -866,8 +866,8 @@ trait TraitAddTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } @@ -877,8 +877,8 @@ trait TraitAddLifetimeBoundToTypeParameterOfTraitWhere<'a, T> where T: 'a { } trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b { } @@ -888,8 +888,8 @@ trait TraitAddLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b> where 'a: 'b trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } @@ -899,8 +899,8 @@ trait TraitAddBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere where T: ReferencedTrait0 + ReferencedTrait1 { } @@ -911,8 +911,8 @@ trait TraitAddSecondTraitBoundToTypeParameterOfTraitWhere trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: 'a + 'b { } @@ -922,8 +922,8 @@ trait TraitAddSecondLifetimeBoundToTypeParameterOfTraitWhere<'a, 'b, T> where T: trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> where 'a: 'b + 'c { } @@ -933,8 +933,8 @@ trait TraitAddSecondLifetimeBoundToLifetimeParameterOfTraitWhere<'a, 'b, 'c> whe trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitAddSecondBuiltinBoundToTypeParameterOfTraitWhere where T: Send + Sync { } @@ -945,11 +945,11 @@ mod change_return_type_of_method_indirectly_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ReturnType; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeReturnType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method() -> ReturnType; } } @@ -963,11 +963,11 @@ mod change_method_parameter_type_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferenceType1 as ArgType; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeArgType { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: ArgType); } } @@ -981,11 +981,11 @@ mod change_method_parameter_type_bound_indirectly_by_use { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameter { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: T); } } @@ -1000,11 +1000,11 @@ mod change_method_parameter_type_bound_indirectly_by_use_where { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeBoundOfMethodTypeParameterWhere { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method(a: T) where T: Bound; } } @@ -1018,8 +1018,8 @@ mod change_method_type_parameter_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTraitBound { fn method(a: T); } @@ -1035,8 +1035,8 @@ mod change_method_type_parameter_bound_indirectly_where { #[cfg(not(cfail1))] use super::ReferencedTrait1 as Bound; - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] trait TraitChangeTraitBoundWhere where T: Bound { fn method(a: T); } diff --git a/src/test/incremental/hashes/trait_impls.rs b/src/test/incremental/hashes/trait_impls.rs index 3e8d884be1f..70e066870b6 100644 --- a/src/test/incremental/hashes/trait_impls.rs +++ b/src/test/incremental/hashes/trait_impls.rs @@ -30,18 +30,18 @@ impl ChangeMethodNameTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait ChangeMethodNameTrait { - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name2(); } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodNameTrait for Foo { - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name2() { } } @@ -59,11 +59,11 @@ impl ChangeMethodBodyTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodBodyTrait for Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] fn method_name() { @@ -86,11 +86,11 @@ impl ChangeMethodBodyTraitInlined for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodBodyTraitInlined for Foo { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail3")] #[inline] @@ -117,11 +117,11 @@ pub trait ChangeMethodSelfnessTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodSelfnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self) { () } @@ -145,11 +145,11 @@ pub trait RemoveMethodSelfnessTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl RemoveMethodSelfnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name() {} } @@ -171,11 +171,11 @@ pub trait ChangeMethodSelfmutnessTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeMethodSelfmutnessTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&mut self) {} } @@ -197,8 +197,8 @@ pub trait ChangeItemKindTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeItemKindTrait for Foo { type name = (); } @@ -223,8 +223,8 @@ pub trait RemoveItemTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl RemoveItemTrait for Foo { type TypeName = (); } @@ -248,8 +248,8 @@ pub trait AddItemTrait { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddItemTrait for Foo { type TypeName = (); fn method_name() { } @@ -268,17 +268,17 @@ impl ChangeHasValueTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] pub trait ChangeHasValueTrait { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name() { } } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeHasValueTrait for Foo { fn method_name() { } } @@ -295,11 +295,11 @@ impl AddDefaultTrait for Foo { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddDefaultTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] default fn method_name() { } } @@ -321,11 +321,11 @@ pub trait AddArgumentTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddArgumentTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self, _x: u32) { } } @@ -347,11 +347,11 @@ pub trait ChangeArgumentTypeTrait { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeArgumentTypeTrait for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn method_name(&self, _x: char) { } } @@ -370,11 +370,11 @@ impl AddTypeParameterToImpl for Bar { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddTypeParameterToImpl for Bar { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(t: T) -> T { t } } @@ -391,11 +391,11 @@ impl ChangeSelfTypeOfImpl for u32 { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl ChangeSelfTypeOfImpl for u64 { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -412,11 +412,11 @@ impl AddLifetimeBoundToImplParameter for T { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddLifetimeBoundToImplParameter for T { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -433,11 +433,11 @@ impl AddTraitBoundToImplParameter for T { } #[cfg(not(cfail1))] -#[rustc_dirty(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_dirty(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddTraitBoundToImplParameter for T { - #[rustc_clean(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] fn id(self) -> Self { self } } @@ -454,11 +454,11 @@ impl AddNoMangleToMethod for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl AddNoMangleToMethod for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[no_mangle] fn add_no_mangle_to_method(&self) { } } @@ -475,11 +475,11 @@ impl MakeMethodInline for Foo { } #[cfg(not(cfail1))] -#[rustc_clean(label="Hir", cfg="cfail2")] -#[rustc_clean(label="Hir", cfg="cfail3")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail3")] impl MakeMethodInline for Foo { - #[rustc_dirty(label="Hir", cfg="cfail2")] - #[rustc_clean(label="Hir", cfg="cfail3")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail3")] #[inline] fn make_method_inline(&self) -> u8 { 0 } } diff --git a/src/test/incremental/hashes/type_defs.rs b/src/test/incremental/hashes/type_defs.rs index b50eeb46f96..bbe1514ba9f 100644 --- a/src/test/incremental/hashes/type_defs.rs +++ b/src/test/incremental/hashes/type_defs.rs @@ -24,7 +24,7 @@ type ChangePrimitiveType = i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangePrimitiveType = i64; @@ -35,7 +35,7 @@ type ChangePrimitiveType = i64; type ChangeMutability = &'static i32; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeMutability = &'static mut i32; @@ -46,7 +46,7 @@ type ChangeMutability = &'static mut i32; type ChangeLifetime<'a> = (&'static i32, &'a i32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeLifetime<'a> = (&'a i32, &'a i32); @@ -60,7 +60,7 @@ struct Struct2; type ChangeTypeStruct = Struct1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeStruct = Struct2; @@ -71,7 +71,7 @@ type ChangeTypeStruct = Struct2; type ChangeTypeTuple = (u32, u64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeTuple = (u32, i64); @@ -91,7 +91,7 @@ enum Enum2 { type ChangeTypeEnum = Enum1; #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTypeEnum = Enum2; @@ -102,7 +102,7 @@ type ChangeTypeEnum = Enum2; type AddTupleField = (i32, i64); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTupleField = (i32, i64, i16); @@ -113,7 +113,7 @@ type AddTupleField = (i32, i64, i16); type ChangeNestedTupleField = (i32, (i64, i16)); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeNestedTupleField = (i32, (i64, i8)); @@ -124,7 +124,7 @@ type ChangeNestedTupleField = (i32, (i64, i8)); type AddTypeParam = (T1, T1); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParam = (T1, T2); @@ -135,7 +135,7 @@ type AddTypeParam = (T1, T2); type AddTypeParamBound = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBound = (T1, u32); @@ -146,7 +146,7 @@ type AddTypeParamBound = (T1, u32); type AddTypeParamBoundWhereClause where T1: Clone = (T1, u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); @@ -157,7 +157,7 @@ type AddTypeParamBoundWhereClause where T1: Clone+Copy = (T1, u32); type AddLifetimeParam<'a> = (&'a u32, &'a u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); @@ -168,7 +168,7 @@ type AddLifetimeParam<'a, 'b> = (&'a u32, &'b u32); type AddLifetimeParamBound<'a, 'b> = (&'a u32, &'b u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBound<'a, 'b: 'a> = (&'a u32, &'b u32); @@ -181,7 +181,7 @@ where 'b: 'a = (&'a u32, &'b u32, &'c u32); #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] +#[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type AddLifetimeParamBoundWhereClause<'a, 'b, 'c> where 'b: 'a, @@ -200,7 +200,7 @@ mod change_trait_bound_indirectly { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly = (T, u32); } @@ -214,7 +214,7 @@ mod change_trait_bound_indirectly_in_where_clause { #[cfg(not(cfail1))] use super::ReferencedTrait2 as Trait; - #[rustc_clean(cfg="cfail2", except="Hir,hir_owner_items")] + #[rustc_clean(cfg="cfail2", except="hir_owner,hir_owner_items")] #[rustc_clean(cfg="cfail3")] type ChangeTraitBoundIndirectly where T : Trait = (T, u32); } diff --git a/src/test/incremental/ich_method_call_trait_scope.rs b/src/test/incremental/ich_method_call_trait_scope.rs index 9d731636142..a9ec66346ac 100644 --- a/src/test/incremental/ich_method_call_trait_scope.rs +++ b/src/test/incremental/ich_method_call_trait_scope.rs @@ -26,14 +26,14 @@ mod mod3 { #[cfg(rpass2)] use Trait2; - #[rustc_clean(label="Hir", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_dirty(label="typeck_tables_of", cfg="rpass2")] fn bar() { ().method(); } - #[rustc_clean(label="Hir", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] #[rustc_clean(label="typeck_tables_of", cfg="rpass2")] fn baz() { diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index 54db7a2116d..c30cfc49bdc 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -7,13 +7,13 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(label="Hir", cfg="cfail2")] +#[rustc_clean(label="hir_owner", cfg="cfail2")] #[rustc_dirty(label="hir_owner_items", cfg="cfail2")] pub fn foo() { #[cfg(cfail1)] pub fn baz() { } // order is different... - #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] #[rustc_clean(label="hir_owner_items", cfg="cfail2")] pub fn bar() { } // but that doesn't matter. diff --git a/src/test/incremental/ich_resolve_results.rs b/src/test/incremental/ich_resolve_results.rs index 723c367af9e..c4674faabf5 100644 --- a/src/test/incremental/ich_resolve_results.rs +++ b/src/test/incremental/ich_resolve_results.rs @@ -28,17 +28,17 @@ mod mod3 { #[cfg(rpass3)] use mod2::Foo; - #[rustc_clean(label="Hir", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] - #[rustc_clean(label="Hir", cfg="rpass3")] + #[rustc_clean(label="hir_owner", cfg="rpass3")] #[rustc_dirty(label="hir_owner_items", cfg="rpass3")] fn in_expr() { Foo(0); } - #[rustc_clean(label="Hir", cfg="rpass2")] + #[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] - #[rustc_clean(label="Hir", cfg="rpass3")] + #[rustc_clean(label="hir_owner", cfg="rpass3")] #[rustc_dirty(label="hir_owner_items", cfg="rpass3")] fn in_type() { test::(); diff --git a/src/test/incremental/inlined_hir_34991/main.rs b/src/test/incremental/inlined_hir_34991/main.rs index 819b8434b08..bb76a0bb8fe 100644 --- a/src/test/incremental/inlined_hir_34991/main.rs +++ b/src/test/incremental/inlined_hir_34991/main.rs @@ -1,6 +1,6 @@ // Regression test for #34991: an ICE occurred here because we inline // some of the vector routines and give them a local def-id `X`. This -// got hashed after codegen (`Hir(X)`). When we load back up, we get an +// got hashed after codegen (`hir_owner(X)`). When we load back up, we get an // error because the `X` is remapped to the original def-id (in // libstd), and we can't hash a HIR node from std. diff --git a/src/test/incremental/source_loc_macros.rs b/src/test/incremental/source_loc_macros.rs index ea81d3e5862..a360a66a64b 100644 --- a/src/test/incremental/source_loc_macros.rs +++ b/src/test/incremental/source_loc_macros.rs @@ -7,25 +7,25 @@ #![feature(rustc_attrs)] -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn line_same() { let _ = line!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn col_same() { let _ = column!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_clean(label="hir_owner_items", cfg="rpass2")] fn file_same() { let _ = file!(); } -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_dirty(label="hir_owner_items", cfg="rpass2")] fn line_different() { #[cfg(rpass1)] @@ -38,7 +38,7 @@ fn line_different() { } } -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] #[rustc_dirty(label="hir_owner_items", cfg="rpass2")] fn col_different() { #[cfg(rpass1)] diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs index 54fbe4465e3..2927ddec4e5 100644 --- a/src/test/incremental/span_hash_stable/auxiliary/sub1.rs +++ b/src/test/incremental/span_hash_stable/auxiliary/sub1.rs @@ -1,4 +1,4 @@ -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] pub struct SomeType { pub x: u32, pub y: i64, diff --git a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs index 34957616856..aa635077db8 100644 --- a/src/test/incremental/span_hash_stable/auxiliary/sub2.rs +++ b/src/test/incremental/span_hash_stable/auxiliary/sub2.rs @@ -1,4 +1,4 @@ -#[rustc_clean(label="Hir", cfg="rpass2")] +#[rustc_clean(label="hir_owner", cfg="rpass2")] pub struct SomeOtherType { pub a: i32, pub b: u64, diff --git a/src/test/incremental/spans_significant_w_debuginfo.rs b/src/test/incremental/spans_significant_w_debuginfo.rs index 1a1ab95598d..b87d829132b 100644 --- a/src/test/incremental/spans_significant_w_debuginfo.rs +++ b/src/test/incremental/spans_significant_w_debuginfo.rs @@ -12,6 +12,6 @@ pub fn main() {} #[cfg(rpass2)] -#[rustc_dirty(label="Hir", cfg="rpass2")] +#[rustc_dirty(label="hir_owner", cfg="rpass2")] #[rustc_dirty(label="hir_owner_items", cfg="rpass2")] pub fn main() {} diff --git a/src/test/incremental/unchecked_dirty_clean.rs b/src/test/incremental/unchecked_dirty_clean.rs index 66bdb670167..3bc8818aa6f 100644 --- a/src/test/incremental/unchecked_dirty_clean.rs +++ b/src/test/incremental/unchecked_dirty_clean.rs @@ -10,13 +10,13 @@ fn main() { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute { // empty block } - #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute { // empty block @@ -24,11 +24,11 @@ fn main() { } struct _Struct { - #[rustc_dirty(label="Hir", cfg="cfail2")] + #[rustc_dirty(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute _field1: i32, - #[rustc_clean(label="Hir", cfg="cfail2")] + #[rustc_clean(label="hir_owner", cfg="cfail2")] //[cfail2]~^ ERROR found unchecked `#[rustc_dirty]` / `#[rustc_clean]` attribute _field2: i32, } From 10b23e3fd32e9f017c1193b7c6bc20da8e61b9ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 16:01:24 +0100 Subject: [PATCH 1136/1250] Format function_interfaces.rs --- .../incremental/hashes/function_interfaces.rs | 86 +++++++++---------- 1 file changed, 40 insertions(+), 46 deletions(-) diff --git a/src/test/incremental/hashes/function_interfaces.rs b/src/test/incremental/hashes/function_interfaces.rs index a7d2d76cf26..bfd53628466 100644 --- a/src/test/incremental/hashes/function_interfaces.rs +++ b/src/test/incremental/hashes/function_interfaces.rs @@ -9,25 +9,24 @@ // revisions: cfail1 cfail2 cfail3 // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans - #![allow(warnings)] #![feature(linkage)] #![feature(rustc_attrs)] #![crate_type = "rlib"] - // Add Parameter --------------------------------------------------------------- #[cfg(cfail1)] pub fn add_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn add_parameter(p: i32) {} - // Add Return Type ------------------------------------------------------------- #[cfg(cfail1)] @@ -38,55 +37,58 @@ pub fn add_return_type() {} #[rustc_clean(cfg = "cfail3")] pub fn add_return_type() -> () {} - // Change Parameter Type ------------------------------------------------------- #[cfg(cfail1)] pub fn type_of_parameter(p: i32) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter(p: i64) {} - // Change Parameter Type Reference --------------------------------------------- #[cfg(cfail1)] pub fn type_of_parameter_ref(p: &i32) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_of_parameter_ref(p: &mut i32) {} - // Change Parameter Order ------------------------------------------------------ #[cfg(cfail1)] pub fn order_of_parameters(p1: i32, p2: i64) {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub fn order_of_parameters(p2: i64, p1: i32) {} - // Unsafe ---------------------------------------------------------------------- #[cfg(cfail1)] pub fn make_unsafe() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" +)] #[rustc_clean(cfg = "cfail3")] pub unsafe fn make_unsafe() {} - // Extern ---------------------------------------------------------------------- #[cfg(cfail1)] @@ -97,19 +99,19 @@ pub fn make_extern() {} #[rustc_clean(cfg = "cfail3")] pub extern "C" fn make_extern() {} - // Type Parameter -------------------------------------------------------------- #[cfg(cfail1)] pub fn type_parameter() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn type_parameter() {} - // Lifetime Parameter ---------------------------------------------------------- #[cfg(cfail1)] @@ -120,7 +122,6 @@ pub fn lifetime_parameter() {} #[rustc_clean(cfg = "cfail3")] pub fn lifetime_parameter<'a>() {} - // Trait Bound ----------------------------------------------------------------- #[cfg(cfail1)] @@ -131,7 +132,6 @@ pub fn trait_bound() {} #[rustc_clean(cfg = "cfail3")] pub fn trait_bound() {} - // Builtin Bound --------------------------------------------------------------- #[cfg(cfail1)] @@ -142,19 +142,19 @@ pub fn builtin_bound() {} #[rustc_clean(cfg = "cfail3")] pub fn builtin_bound() {} - // Lifetime Bound -------------------------------------------------------------- #[cfg(cfail1)] pub fn lifetime_bound<'a, T>() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn lifetime_bound<'a, T: 'a>() {} - // Second Trait Bound ---------------------------------------------------------- #[cfg(cfail1)] @@ -165,7 +165,6 @@ pub fn second_trait_bound() {} #[rustc_clean(cfg = "cfail3")] pub fn second_trait_bound() {} - // Second Builtin Bound -------------------------------------------------------- #[cfg(cfail1)] @@ -176,19 +175,19 @@ pub fn second_builtin_bound() {} #[rustc_clean(cfg = "cfail3")] pub fn second_builtin_bound() {} - // Second Lifetime Bound ------------------------------------------------------- #[cfg(cfail1)] pub fn second_lifetime_bound<'a, 'b, T: 'a>() {} #[cfg(not(cfail1))] -#[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of")] +#[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, generics_of, type_of, predicates_of" +)] #[rustc_clean(cfg = "cfail3")] pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {} - // Inline ---------------------------------------------------------------------- #[cfg(cfail1)] @@ -200,7 +199,6 @@ pub fn inline() {} #[inline] pub fn inline() {} - // Inline Never ---------------------------------------------------------------- #[cfg(cfail1)] @@ -213,7 +211,6 @@ pub fn inline_never() {} #[inline(never)] pub fn inline_never() {} - // No Mangle ------------------------------------------------------------------- #[cfg(cfail1)] @@ -225,7 +222,6 @@ pub fn no_mangle() {} #[no_mangle] pub fn no_mangle() {} - // Linkage --------------------------------------------------------------------- #[cfg(cfail1)] @@ -237,7 +233,6 @@ pub fn linkage() {} #[linkage = "weak_odr"] pub fn linkage() {} - // Return Impl Trait ----------------------------------------------------------- #[cfg(cfail1)] @@ -252,7 +247,6 @@ pub fn return_impl_trait() -> impl Clone { 0 } - // Change Return Impl Trait ---------------------------------------------------- #[cfg(cfail1)] @@ -267,7 +261,6 @@ pub fn change_return_impl_trait() -> impl Copy { 0u32 } - // Change Return Type Indirectly ----------------------------------------------- pub struct ReferencedType1; @@ -279,15 +272,16 @@ pub mod change_return_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as ReturnType; - #[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + #[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" + )] #[rustc_clean(cfg = "cfail3")] pub fn indirect_return_type() -> ReturnType { ReturnType {} } } - // Change Parameter Type Indirectly -------------------------------------------- pub mod change_parameter_type_indirectly { @@ -296,13 +290,14 @@ pub mod change_parameter_type_indirectly { #[cfg(not(cfail1))] use super::ReferencedType2 as ParameterType; - #[rustc_clean(cfg = "cfail2", - except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig")] + #[rustc_clean( + cfg = "cfail2", + except = "hir_owner, hir_owner_items, mir_built, optimized_mir, typeck_tables_of, fn_sig" + )] #[rustc_clean(cfg = "cfail3")] pub fn indirect_parameter_type(p: ParameterType) {} } - // Change Trait Bound Indirectly ----------------------------------------------- pub trait ReferencedTrait1 {} @@ -319,7 +314,6 @@ pub mod change_trait_bound_indirectly { pub fn indirect_trait_bound(p: T) {} } - // Change Trait Bound Indirectly In Where Clause ------------------------------- pub mod change_trait_bound_indirectly_in_where_clause { From 6258c0144df5f47bfa4aed7d7fa0d6aa86990e46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 18:11:32 +0100 Subject: [PATCH 1137/1250] Reintroduce workaround for #62649 --- src/librustc/dep_graph/graph.rs | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 8a8ae60c813..97114b9e313 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -654,18 +654,25 @@ impl DepGraph { continue; } } else { + // FIXME: This match is just a workaround for incremental bugs and should + // be removed. https://github.com/rust-lang/rust/issues/62649 is one such + // bug that must be fixed before removing this. match dep_dep_node.kind { - DepKind::CrateMetadata => { + DepKind::hir_owner + | DepKind::hir_owner_items + | DepKind::CrateMetadata => { if let Some(def_id) = dep_dep_node.extract_def_id(tcx) { if def_id_corresponds_to_hir_dep_node(tcx, def_id) { - // The `DefPath` has corresponding node, - // and that node should have been marked - // either red or green in `data.colors`. - bug!( - "DepNode {:?} should have been \ + if dep_dep_node.kind == DepKind::CrateMetadata { + // The `DefPath` has corresponding node, + // and that node should have been marked + // either red or green in `data.colors`. + bug!( + "DepNode {:?} should have been \ pre-marked as red or green but wasn't.", - dep_dep_node - ); + dep_dep_node + ); + } } else { // This `DefPath` does not have a // corresponding `DepNode` (e.g. a From 7118f71ea1f7ad0fb1cf8e2a0c9d512c534604c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 12 Feb 2020 18:50:30 +0100 Subject: [PATCH 1138/1250] Update ich_nested_items.rs --- src/test/incremental/ich_nested_items.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/test/incremental/ich_nested_items.rs b/src/test/incremental/ich_nested_items.rs index c30cfc49bdc..a9232190eef 100644 --- a/src/test/incremental/ich_nested_items.rs +++ b/src/test/incremental/ich_nested_items.rs @@ -7,18 +7,21 @@ #![crate_type = "rlib"] #![feature(rustc_attrs)] -#[rustc_clean(label="hir_owner", cfg="cfail2")] -#[rustc_dirty(label="hir_owner_items", cfg="cfail2")] +#[rustc_clean(label = "hir_owner", cfg = "cfail2")] +#[rustc_dirty(label = "hir_owner_items", cfg = "cfail2")] pub fn foo() { #[cfg(cfail1)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - #[rustc_clean(label="hir_owner", cfg="cfail2")] - #[rustc_clean(label="hir_owner_items", cfg="cfail2")] - pub fn bar() { } // but that doesn't matter. + // FIXME: Make "hir_owner" use `rustc_clean` here. Currently "hir_owner" includes a reference to + // the parent node, which is the statement holding this item. Changing the position of + // `bar` in `foo` will update that reference and make `hir_owner(bar)` dirty. + #[rustc_dirty(label = "hir_owner", cfg = "cfail2")] + #[rustc_clean(label = "hir_owner_items", cfg = "cfail2")] + pub fn bar() {} // but that doesn't matter. #[cfg(cfail2)] - pub fn baz() { } // order is different... + pub fn baz() {} // order is different... - pub fn bap() { } // neither does adding a new item + pub fn bap() {} // neither does adding a new item } From 8b8041efc054a8340d9672dae16b76edd07b52cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 13 Feb 2020 11:17:49 +0100 Subject: [PATCH 1139/1250] Update tests --- src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs | 4 ++-- src/test/ui-fulldeps/auxiliary/lint-for-crate.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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 4936bdb1ece..52620b2464b 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate-rpass.rs @@ -29,10 +29,10 @@ macro_rules! fake_lint_pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for $struct { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { $( - if !attr::contains_name(&krate.attrs, $attr) { + if !attr::contains_name(&krate.item.attrs, $attr) { cx.lint(CRATE_NOT_OKAY, |lint| { let msg = format!("crate is not marked with #![{}]", $attr); - lint.build(&msg).set_span(krate.span).emit() + lint.build(&msg).set_span(krate.item.span).emit() }); } )* diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs index 32b7ed9dfe2..6978d02c09d 100644 --- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs +++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs @@ -27,10 +27,10 @@ declare_lint_pass!(Pass => [CRATE_NOT_OKAY]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_crate(&mut self, cx: &LateContext, krate: &rustc_hir::Crate) { - if !attr::contains_name(&krate.attrs, Symbol::intern("crate_okay")) { + if !attr::contains_name(&krate.item.attrs, Symbol::intern("crate_okay")) { cx.lint(CRATE_NOT_OKAY, |lint| { lint.build("crate is not marked with #![crate_okay]") - .set_span(krate.span) + .set_span(krate.item.span) .emit() }); } From 2af085d34f902616fb15fb6c7b70115b45f43689 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Thu, 20 Feb 2020 19:24:44 +0100 Subject: [PATCH 1140/1250] Don't try to print missing HIR ids --- src/librustc/hir/map/hir_id_validator.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index c4c23c1a754..796f4895472 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -111,9 +111,9 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { trace!("missing hir id {:#?}", hir_id); missing_items.push(format!( - "[local_id: {}, node:{}]", + "[local_id: {}, owner: {}]", local_id, - self.hir_map.node_to_string(hir_id) + self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate() )); } self.error(|| { From 31183c39dfc89b9a9470e12c2dd0932c636d8124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Tue, 10 Mar 2020 08:26:13 +0100 Subject: [PATCH 1141/1250] Add test for #69596 --- src/test/incremental/issue-69596.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/incremental/issue-69596.rs diff --git a/src/test/incremental/issue-69596.rs b/src/test/incremental/issue-69596.rs new file mode 100644 index 00000000000..dc587fdc44b --- /dev/null +++ b/src/test/incremental/issue-69596.rs @@ -0,0 +1,21 @@ +// revisions: rpass1 rpass2 + +#![allow(unused_imports)] + +#[macro_export] +macro_rules! a_macro { + () => {}; +} + +#[cfg(rpass1)] +use a_macro as same_name; + +mod same_name {} + +mod needed_mod { + fn _crash() { + use super::same_name; + } +} + +fn main() {} From 14fdd85a5aa3768e5896d9ca638488722f7e9e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 11 Mar 2020 15:20:24 +0100 Subject: [PATCH 1142/1250] Add some comments to the new queries --- src/librustc/query/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 866fe8c88a8..ff3a82e5363 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -55,20 +55,33 @@ rustc_queries! { desc { "get the crate HIR" } } + // The indexed HIR. This can be conveniently accessed by `tcx.hir()`. + // Avoid calling this query directly. query index_hir(_: CrateNum) -> &'tcx map::IndexedHir<'tcx> { eval_always no_hash desc { "index HIR" } } + // The items in a module. + // This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. + // Avoid calling this query directly. query hir_module_items(key: DefId) -> &'tcx hir::ModuleItems { eval_always } + // An HIR item with a `DefId` that can own other HIR items which do not themselves have + // a `DefId`. + // This can be conveniently accessed by methods on `tcx.hir()`. + // Avoid calling this query directly. query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { eval_always } + // The HIR items which do not themselves have a `DefId` and are owned by another HIR item + // with a `DefId`. + // This can be conveniently accessed by methods on `tcx.hir()`. + // Avoid calling this query directly. query hir_owner_items(key: DefId) -> &'tcx HirOwnerItems<'tcx> { eval_always } From 68dc24fcbebbd529e44d9ecba9bcdeff68268555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Gerber?= Date: Sat, 14 Mar 2020 23:04:33 +0100 Subject: [PATCH 1143/1250] Clean up path separator in rustdoc book --- src/doc/rustdoc/src/command-line-arguments.md | 4 ++-- src/doc/rustdoc/src/what-is-rustdoc.md | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 2e32ce31eca..ddbe26389fd 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -79,8 +79,8 @@ Rustdoc only supports HTML output, and so this flag is redundant today. Using this flag looks like this: ```bash -$ rustdoc src/lib.rs -o target\\doc -$ rustdoc src/lib.rs --output target\\doc +$ rustdoc src/lib.rs -o target/doc +$ rustdoc src/lib.rs --output target/doc ``` By default, `rustdoc`'s output appears in a directory named `doc` in diff --git a/src/doc/rustdoc/src/what-is-rustdoc.md b/src/doc/rustdoc/src/what-is-rustdoc.md index bbcacb7f3d5..adcebc832bc 100644 --- a/src/doc/rustdoc/src/what-is-rustdoc.md +++ b/src/doc/rustdoc/src/what-is-rustdoc.md @@ -78,8 +78,8 @@ $ cargo doc Internally, this calls out to `rustdoc` like this: ```bash -$ rustdoc --crate-name docs srclib.rs -o \docs\target\doc -L -dependency=docs\target\debug\deps +$ rustdoc --crate-name docs src/lib.rs -o /docs/target/doc -L +dependency=/docs/target/debug/deps ``` You can see this with `cargo doc --verbose`. @@ -128,4 +128,4 @@ Cargo currently does not understand standalone Markdown files, unfortunately. ## Summary This covers the simplest use-cases of `rustdoc`. The rest of this book will -explain all of the options that `rustdoc` has, and how to use them. \ No newline at end of file +explain all of the options that `rustdoc` has, and how to use them. From ecb84c975d653afc9da356baf2a7aa21ac476f22 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 11 Mar 2020 13:06:54 +0100 Subject: [PATCH 1144/1250] Clean up E0412 and E0422 explanations --- src/librustc_error_codes/error_codes/E0412.md | 2 +- src/librustc_error_codes/error_codes/E0422.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0412.md b/src/librustc_error_codes/error_codes/E0412.md index 60a09610d86..d9ebc852bba 100644 --- a/src/librustc_error_codes/error_codes/E0412.md +++ b/src/librustc_error_codes/error_codes/E0412.md @@ -1,4 +1,4 @@ -The type name used is not in scope. +A used type name is not in scope. Erroneous code examples: diff --git a/src/librustc_error_codes/error_codes/E0422.md b/src/librustc_error_codes/error_codes/E0422.md index a91ea6a9e22..828a52e7341 100644 --- a/src/librustc_error_codes/error_codes/E0422.md +++ b/src/librustc_error_codes/error_codes/E0422.md @@ -1,4 +1,5 @@ -You are trying to use an identifier that is either undefined or not a struct. +An identifier that is neither defined nor a struct was used. + Erroneous code example: ```compile_fail,E0422 From 6f75d3fcc04e6da1f10424e29da978a81698e81b Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Fri, 13 Dec 2019 13:20:16 -0800 Subject: [PATCH 1145/1250] Simplify `Qualif` interface --- .../transform/check_consts/qualifs.rs | 335 ++++++++---------- .../transform/check_consts/resolver.rs | 31 +- .../transform/check_consts/validation.rs | 2 +- src/librustc_mir/transform/promote_consts.rs | 12 +- 4 files changed, 178 insertions(+), 202 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/qualifs.rs b/src/librustc_mir/transform/check_consts/qualifs.rs index baff8383c20..9359ec16533 100644 --- a/src/librustc_mir/transform/check_consts/qualifs.rs +++ b/src/librustc_mir/transform/check_consts/qualifs.rs @@ -1,7 +1,9 @@ -//! A copy of the `Qualif` trait in `qualify_consts.rs` that is suitable for the new validator. +//! Structural const qualification. +//! +//! See the `Qualif` trait for more info. use rustc::mir::*; -use rustc::ty::{self, Ty}; +use rustc::ty::{self, AdtDef, Ty}; use rustc_span::DUMMY_SP; use super::Item as ConstCx; @@ -14,11 +16,16 @@ pub fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> ConstQualifs } /// A "qualif"(-ication) is a way to look for something "bad" in the MIR that would disqualify some -/// code for promotion or prevent it from evaluating at compile time. So `return true` means -/// "I found something bad, no reason to go on searching". `false` is only returned if we -/// definitely cannot find anything bad anywhere. +/// code for promotion or prevent it from evaluating at compile time. /// -/// The default implementations proceed structurally. +/// Normally, we would determine what qualifications apply to each type and error when an illegal +/// operation is performed on such a type. However, this was found to be too imprecise, especially +/// in the presence of `enum`s. If only a single variant of an enum has a certain qualification, we +/// needn't reject code unless it actually constructs and operates on the qualifed variant. +/// +/// To accomplish this, const-checking and promotion use a value-based analysis (as opposed to a +/// type-based one). Qualifications propagate structurally across variables: If a local (or a +/// projection of a local) is assigned a qualifed value, that local itself becomes qualifed. pub trait Qualif { /// The name of the file used to debug the dataflow analysis that computes this qualif. const ANALYSIS_NAME: &'static str; @@ -26,157 +33,27 @@ pub trait Qualif { /// Whether this `Qualif` is cleared when a local is moved from. const IS_CLEARED_ON_MOVE: bool = false; + /// Extracts the field of `ConstQualifs` that corresponds to this `Qualif`. fn in_qualifs(qualifs: &ConstQualifs) -> bool; - /// Return the qualification that is (conservatively) correct for any value - /// of the type. - fn in_any_value_of_ty(_cx: &ConstCx<'_, 'tcx>, _ty: Ty<'tcx>) -> bool; - - fn in_projection_structurally( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - if let [proj_base @ .., elem] = place.projection { - let base_qualif = Self::in_place( - cx, - per_local, - PlaceRef { local: place.local, projection: proj_base }, - ); - let qualif = base_qualif - && Self::in_any_value_of_ty( - cx, - Place::ty_from(place.local, proj_base, *cx.body, cx.tcx) - .projection_ty(cx.tcx, elem) - .ty, - ); - match elem { - ProjectionElem::Deref - | ProjectionElem::Subslice { .. } - | ProjectionElem::Field(..) - | ProjectionElem::ConstantIndex { .. } - | ProjectionElem::Downcast(..) => qualif, - - ProjectionElem::Index(local) => qualif || per_local(*local), - } - } else { - bug!("This should be called if projection is not empty"); - } - } - - fn in_projection( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - Self::in_projection_structurally(cx, per_local, place) - } - - fn in_place( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - place: PlaceRef<'tcx>, - ) -> bool { - match place { - PlaceRef { local, projection: [] } => per_local(local), - PlaceRef { local: _, projection: [.., _] } => Self::in_projection(cx, per_local, place), - } - } - - fn in_operand( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - operand: &Operand<'tcx>, - ) -> bool { - match *operand { - Operand::Copy(ref place) | Operand::Move(ref place) => { - Self::in_place(cx, per_local, place.as_ref()) - } - - Operand::Constant(ref constant) => { - // Check the qualifs of the value of `const` items. - if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val { - assert!(promoted.is_none()); - // Don't peek inside trait associated constants. - if cx.tcx.trait_of_item(def_id).is_none() { - let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id); - if !Self::in_qualifs(&qualifs) { - return false; - } - - // Just in case the type is more specific than - // the definition, e.g., impl associated const - // with type parameters, take it into account. - } - } - // Otherwise use the qualifs of the type. - Self::in_any_value_of_ty(cx, constant.literal.ty) - } - } - } - - fn in_rvalue_structurally( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - match *rvalue { - Rvalue::NullaryOp(..) => false, - - Rvalue::Discriminant(ref place) | Rvalue::Len(ref place) => { - Self::in_place(cx, per_local, place.as_ref()) - } - - Rvalue::Use(ref operand) - | Rvalue::Repeat(ref operand, _) - | Rvalue::UnaryOp(_, ref operand) - | Rvalue::Cast(_, ref operand, _) => Self::in_operand(cx, per_local, operand), - - Rvalue::BinaryOp(_, ref lhs, ref rhs) - | Rvalue::CheckedBinaryOp(_, ref lhs, ref rhs) => { - Self::in_operand(cx, per_local, lhs) || Self::in_operand(cx, per_local, rhs) - } - - Rvalue::Ref(_, _, ref place) | Rvalue::AddressOf(_, ref place) => { - // Special-case reborrows to be more like a copy of the reference. - if let [proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { - let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty; - if let ty::Ref(..) = base_ty.kind { - return Self::in_place( - cx, - per_local, - PlaceRef { local: place.local, projection: proj_base }, - ); - } - } - - Self::in_place(cx, per_local, place.as_ref()) - } - - Rvalue::Aggregate(_, ref operands) => { - operands.iter().any(|o| Self::in_operand(cx, per_local, o)) - } - } - } - - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - Self::in_rvalue_structurally(cx, per_local, rvalue) - } - - fn in_call( - cx: &ConstCx<'_, 'tcx>, - _per_local: &mut impl FnMut(Local) -> bool, - _callee: &Operand<'tcx>, - _args: &[Operand<'tcx>], - return_ty: Ty<'tcx>, - ) -> bool { - // Be conservative about the returned value of a const fn. - Self::in_any_value_of_ty(cx, return_ty) - } + /// Returns `true` if *any* value of the given type could possibly have this `Qualif`. + /// + /// This function determines `Qualif`s when we cannot do a value-based analysis. Since qualif + /// propagation is context-insenstive, this includes function arguments and values returned + /// from a call to another function. + /// + /// It also determines the `Qualif`s for primitive types. + fn in_any_value_of_ty(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool; + + /// Returns `true` if this `Qualif` is inherent to the given struct or enum. + /// + /// By default, `Qualif`s propagate into ADTs in a structural way: An ADT only becomes + /// qualified if part of it is assigned a value with that `Qualif`. However, some ADTs *always* + /// have a certain `Qualif`, regardless of whether their fields have it. For example, a type + /// with a custom `Drop` impl is inherently `NeedsDrop`. + /// + /// Returning `true` for `in_adt_inherently` but `false` for `in_any_value_of_ty` is unsound. + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool; } /// Constant containing interior mutability (`UnsafeCell`). @@ -197,26 +74,10 @@ impl Qualif for HasMutInterior { !ty.is_freeze(cx.tcx, cx.param_env, DUMMY_SP) } - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - match *rvalue { - Rvalue::Aggregate(ref kind, _) => { - if let AggregateKind::Adt(def, ..) = **kind { - if Some(def.did) == cx.tcx.lang_items().unsafe_cell_type() { - let ty = rvalue.ty(*cx.body, cx.tcx); - assert_eq!(Self::in_any_value_of_ty(cx, ty), true); - return true; - } - } - } - - _ => {} - } - - Self::in_rvalue_structurally(cx, per_local, rvalue) + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool { + // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently. + // It arises structurally for all other types. + Some(adt.did) == cx.tcx.lang_items().unsafe_cell_type() } } @@ -238,19 +99,127 @@ impl Qualif for NeedsDrop { ty.needs_drop(cx.tcx, cx.param_env) } - fn in_rvalue( - cx: &ConstCx<'_, 'tcx>, - per_local: &mut impl FnMut(Local) -> bool, - rvalue: &Rvalue<'tcx>, - ) -> bool { - if let Rvalue::Aggregate(ref kind, _) = *rvalue { + fn in_adt_inherently(cx: &ConstCx<'_, 'tcx>, adt: &AdtDef) -> bool { + adt.has_dtor(cx.tcx) + } +} + +// FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return. + +/// Returns `true` if this `Rvalue` contains qualif `Q`. +pub fn in_rvalue(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, rvalue: &Rvalue<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + match rvalue { + Rvalue::NullaryOp(..) => Q::in_any_value_of_ty(cx, rvalue.ty(*cx.body, cx.tcx)), + + Rvalue::Discriminant(place) | Rvalue::Len(place) => { + in_place::(cx, in_local, place.as_ref()) + } + + Rvalue::Use(operand) + | Rvalue::Repeat(operand, _) + | Rvalue::UnaryOp(_, operand) + | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), + + Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => { + in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) + } + + Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => { + // Special-case reborrows to be more like a copy of the reference. + if let &[ref proj_base @ .., ProjectionElem::Deref] = place.projection.as_ref() { + let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx).ty; + if let ty::Ref(..) = base_ty.kind { + return in_place::( + cx, + in_local, + PlaceRef { local: place.local, projection: proj_base }, + ); + } + } + + in_place::(cx, in_local, place.as_ref()) + } + + Rvalue::Aggregate(kind, operands) => { + // Return early if we know that the struct or enum being constructed is always + // qualified. if let AggregateKind::Adt(def, ..) = **kind { - if def.has_dtor(cx.tcx) { + if Q::in_adt_inherently(cx, def) { return true; } } + + // Otherwise, proceed structurally... + operands.iter().any(|o| in_operand::(cx, in_local, o)) } + } +} - Self::in_rvalue_structurally(cx, per_local, rvalue) +/// Returns `true` if this `Place` contains qualif `Q`. +pub fn in_place(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, place: PlaceRef<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + let mut projection = place.projection; + while let [ref proj_base @ .., proj_elem] = projection { + match *proj_elem { + ProjectionElem::Index(index) if in_local(index) => return true, + + ProjectionElem::Deref + | ProjectionElem::Field(_, _) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } + | ProjectionElem::Downcast(_, _) + | ProjectionElem::Index(_) => {} + } + + let base_ty = Place::ty_from(place.local, proj_base, *cx.body, cx.tcx); + let proj_ty = base_ty.projection_ty(cx.tcx, proj_elem).ty; + if !Q::in_any_value_of_ty(cx, proj_ty) { + return false; + } + + projection = proj_base; + } + + assert!(projection.is_empty()); + in_local(place.local) +} + +/// Returns `true` if this `Operand` contains qualif `Q`. +pub fn in_operand(cx: &ConstCx<'_, 'tcx>, in_local: &mut F, operand: &Operand<'tcx>) -> bool +where + Q: Qualif, + F: FnMut(Local) -> bool, +{ + let constant = match operand { + Operand::Copy(place) | Operand::Move(place) => { + return in_place::(cx, in_local, place.as_ref()); + } + + Operand::Constant(c) => c, + }; + + // Check the qualifs of the value of `const` items. + if let ty::ConstKind::Unevaluated(def_id, _, promoted) = constant.literal.val { + assert!(promoted.is_none()); + // Don't peek inside trait associated constants. + if cx.tcx.trait_of_item(def_id).is_none() { + let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def_id); + if !Q::in_qualifs(&qualifs) { + return false; + } + + // Just in case the type is more specific than + // the definition, e.g., impl associated const + // with type parameters, take it into account. + } } + // Otherwise use the qualifs of the type. + Q::in_any_value_of_ty(cx, constant.literal.ty) } diff --git a/src/librustc_mir/transform/check_consts/resolver.rs b/src/librustc_mir/transform/check_consts/resolver.rs index 3e14cc6d32a..e42f64b5c73 100644 --- a/src/librustc_mir/transform/check_consts/resolver.rs +++ b/src/librustc_mir/transform/check_consts/resolver.rs @@ -8,7 +8,7 @@ use rustc_index::bit_set::BitSet; use std::marker::PhantomData; -use super::{Item, Qualif}; +use super::{qualifs, Item, Qualif}; use crate::dataflow::{self as old_dataflow, generic as dataflow}; /// A `Visitor` that propagates qualifs between locals. This defines the transfer function of @@ -66,18 +66,15 @@ where fn apply_call_return_effect( &mut self, _block: BasicBlock, - func: &mir::Operand<'tcx>, - args: &[mir::Operand<'tcx>], + _func: &mir::Operand<'tcx>, + _args: &[mir::Operand<'tcx>], return_place: &mir::Place<'tcx>, ) { + // We cannot reason about another function's internals, so use conservative type-based + // qualification for the result of a function call. let return_ty = return_place.ty(*self.item.body, self.item.tcx).ty; - let qualif = Q::in_call( - self.item, - &mut |l| self.qualifs_per_local.contains(l), - func, - args, - return_ty, - ); + let qualif = Q::in_any_value_of_ty(self.item, return_ty); + if !return_place.is_indirect() { self.assign_qualif_direct(return_place, qualif); } @@ -110,7 +107,11 @@ where rvalue: &mir::Rvalue<'tcx>, location: Location, ) { - let qualif = Q::in_rvalue(self.item, &mut |l| self.qualifs_per_local.contains(l), rvalue); + let qualif = qualifs::in_rvalue::( + self.item, + &mut |l| self.qualifs_per_local.contains(l), + rvalue, + ); if !place.is_indirect() { self.assign_qualif_direct(place, qualif); } @@ -125,8 +126,12 @@ where // here; that occurs in `apply_call_return_effect`. if let mir::TerminatorKind::DropAndReplace { value, location: dest, .. } = kind { - let qualif = - Q::in_operand(self.item, &mut |l| self.qualifs_per_local.contains(l), value); + let qualif = qualifs::in_operand::( + self.item, + &mut |l| self.qualifs_per_local.contains(l), + value, + ); + if !dest.is_indirect() { self.assign_qualif_direct(dest, qualif); } diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index adffd444eb6..48367fc2465 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -344,7 +344,7 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> { Rvalue::Ref(_, BorrowKind::Shared, ref place) | Rvalue::Ref(_, BorrowKind::Shallow, ref place) | Rvalue::AddressOf(Mutability::Not, ref place) => { - let borrowed_place_has_mut_interior = HasMutInterior::in_place( + let borrowed_place_has_mut_interior = qualifs::in_place::( &self.item, &mut |local| self.qualifs.has_mut_interior(local, location), place.as_ref(), diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7dd134a35d9..1336206e186 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -407,15 +407,17 @@ impl<'tcx> Validator<'_, 'tcx> { // FIXME(eddyb) maybe cache this? fn qualif_local(&self, local: Local) -> bool { - let per_local = &mut |l| self.qualif_local::(l); - if let TempState::Defined { location: loc, .. } = self.temps[local] { let num_stmts = self.body[loc.block].statements.len(); if loc.statement_index < num_stmts { let statement = &self.body[loc.block].statements[loc.statement_index]; match &statement.kind { - StatementKind::Assign(box (_, rhs)) => Q::in_rvalue(&self.item, per_local, rhs), + StatementKind::Assign(box (_, rhs)) => qualifs::in_rvalue::( + &self.item, + &mut |l| self.qualif_local::(l), + rhs, + ), _ => { span_bug!( statement.source_info.span, @@ -427,9 +429,9 @@ impl<'tcx> Validator<'_, 'tcx> { } else { let terminator = self.body[loc.block].terminator(); match &terminator.kind { - TerminatorKind::Call { func, args, .. } => { + TerminatorKind::Call { .. } => { let return_ty = self.body.local_decls[local].ty; - Q::in_call(&self.item, per_local, func, args, return_ty) + Q::in_any_value_of_ty(&self.item, return_ty) } kind => { span_bug!(terminator.source_info.span, "{:?} not promotable", kind); From 131433a2c0bb67d84671c7a97eeddfbc6983b913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Gerber?= Date: Sat, 14 Mar 2020 23:31:34 +0100 Subject: [PATCH 1146/1250] Change fenced code block type in rustdoc book --- src/doc/rustdoc/src/documentation-tests.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md index 96fa4344b04..78181156e25 100644 --- a/src/doc/rustdoc/src/documentation-tests.md +++ b/src/doc/rustdoc/src/documentation-tests.md @@ -314,7 +314,7 @@ only shows the part you care about. `should_panic` tells `rustdoc` that the code should compile correctly, but not actually pass as a test. -```text +```rust /// ```no_run /// loop { /// println!("Hello, world"); From 6d521ecc62013efb62d541b783441c715e7a0e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Gerber?= Date: Sat, 14 Mar 2020 23:40:29 +0100 Subject: [PATCH 1147/1250] Fix punctuation in rustdoc book --- src/doc/rustdoc/src/advanced-features.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index 47bef3cdde1..7c12d23e649 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -4,7 +4,7 @@ The features listed on this page fall outside the rest of the main categories. ## `#[cfg(doc)]`: Documenting platform-/feature-specific information -For conditional compilation, Rustdoc treats your crate the same way the compiler does: Only things +For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things from the host target are available (or from the given `--target` if present), and everything else is "filtered out" from the crate. This can cause problems if your crate is providing different things on different targets and you want your documentation to reflect all the available items you From 138d29d358233d6ffc6c0d0bd0dcc3107e93b591 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 14 Mar 2020 23:51:45 +0100 Subject: [PATCH 1148/1250] Update ui tests --- src/test/ui/lint/use_suggestion_json.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/lint/use_suggestion_json.stderr b/src/test/ui/lint/use_suggestion_json.stderr index 0dc0d247af5..7176f17bc3f 100644 --- a/src/test/ui/lint/use_suggestion_json.stderr +++ b/src/test/ui/lint/use_suggestion_json.stderr @@ -2,7 +2,7 @@ "message": "cannot find type `Iter` in this scope", "code": { "code": "E0412", - "explanation": "The type name used is not in scope. + "explanation": "A used type name is not in scope. Erroneous code examples: From d7e6649326080219fbdad6465468086e46e69377 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Sat, 14 Mar 2020 15:59:10 -0700 Subject: [PATCH 1149/1250] Return feature gate as a `Symbol` --- .../transform/check_consts/ops.rs | 59 ++++++++++--------- .../transform/check_consts/validation.rs | 2 +- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index 9ba44a4d18e..d06a2aa44f2 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -2,7 +2,6 @@ use rustc::session::config::nightly_options; use rustc::session::parse::feature_err; -use rustc::ty::TyCtxt; use rustc_errors::struct_span_err; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; @@ -15,9 +14,9 @@ pub trait NonConstOp: std::fmt::Debug { /// Whether this operation can be evaluated by miri. const IS_SUPPORTED_IN_MIRI: bool = true; - /// Returns a boolean indicating whether the feature gate that would allow this operation is - /// enabled, or `None` if such a feature gate does not exist. - fn feature_gate(_tcx: TyCtxt<'tcx>) -> Option { + /// Returns the `Symbol` corresponding to the feature gate that would enable this operation, + /// or `None` if such a feature gate does not exist. + fn feature_gate() -> Option { None } @@ -25,8 +24,11 @@ pub trait NonConstOp: std::fmt::Debug { /// /// This check should assume that we are not in a non-const `fn`, where all operations are /// legal. + /// + /// By default, it returns `true` if and only if this operation has a corresponding feature + /// gate and that gate is enabled. fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool { - Self::feature_gate(item.tcx).unwrap_or(false) + Self::feature_gate().map_or(false, |gate| item.tcx.features().enabled(gate)) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -55,8 +57,8 @@ pub trait NonConstOp: std::fmt::Debug { #[derive(Debug)] pub struct Downcast; impl NonConstOp for Downcast { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_if_match) + fn feature_gate() -> Option { + Some(sym::const_if_match) } } @@ -147,8 +149,8 @@ impl NonConstOp for HeapAllocation { #[derive(Debug)] pub struct IfOrMatch; impl NonConstOp for IfOrMatch { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_if_match) + fn feature_gate() -> Option { + Some(sym::const_if_match) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -175,8 +177,8 @@ impl NonConstOp for LiveDrop { #[derive(Debug)] pub struct Loop; impl NonConstOp for Loop { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_loop) + fn feature_gate() -> Option { + Some(sym::const_loop) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -203,8 +205,8 @@ impl NonConstOp for CellBorrow { #[derive(Debug)] pub struct MutBorrow; impl NonConstOp for MutBorrow { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -238,8 +240,8 @@ impl NonConstOp for MutBorrow { #[derive(Debug)] pub struct MutAddressOf; impl NonConstOp for MutAddressOf { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -256,16 +258,16 @@ impl NonConstOp for MutAddressOf { #[derive(Debug)] pub struct MutDeref; impl NonConstOp for MutDeref { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_mut_refs) + fn feature_gate() -> Option { + Some(sym::const_mut_refs) } } #[derive(Debug)] pub struct Panic; impl NonConstOp for Panic { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_panic) + fn feature_gate() -> Option { + Some(sym::const_panic) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -282,8 +284,8 @@ impl NonConstOp for Panic { #[derive(Debug)] pub struct RawPtrComparison; impl NonConstOp for RawPtrComparison { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_compare_raw_pointers) + fn feature_gate() -> Option { + Some(sym::const_compare_raw_pointers) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -300,8 +302,8 @@ impl NonConstOp for RawPtrComparison { #[derive(Debug)] pub struct RawPtrDeref; impl NonConstOp for RawPtrDeref { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_raw_ptr_deref) + fn feature_gate() -> Option { + Some(sym::const_raw_ptr_deref) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -318,8 +320,8 @@ impl NonConstOp for RawPtrDeref { #[derive(Debug)] pub struct RawPtrToIntCast; impl NonConstOp for RawPtrToIntCast { - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_raw_ptr_to_usize_cast) + fn feature_gate() -> Option { + Some(sym::const_raw_ptr_to_usize_cast) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { @@ -386,11 +388,12 @@ pub struct UnionAccess; impl NonConstOp for UnionAccess { fn is_allowed_in_item(&self, item: &Item<'_, '_>) -> bool { // Union accesses are stable in all contexts except `const fn`. - item.const_kind() != ConstKind::ConstFn || Self::feature_gate(item.tcx).unwrap() + item.const_kind() != ConstKind::ConstFn + || item.tcx.features().enabled(Self::feature_gate().unwrap()) } - fn feature_gate(tcx: TyCtxt<'_>) -> Option { - Some(tcx.features().const_fn_union) + fn feature_gate() -> Option { + Some(sym::const_fn_union) } fn emit_error(&self, item: &Item<'_, '_>, span: Span) { diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs index adffd444eb6..bfd97fcff3f 100644 --- a/src/librustc_mir/transform/check_consts/validation.rs +++ b/src/librustc_mir/transform/check_consts/validation.rs @@ -213,7 +213,7 @@ impl Validator<'a, 'mir, 'tcx> { // If an operation is supported in miri (and is not already controlled by a feature gate) it // can be turned on with `-Zunleash-the-miri-inside-of-you`. - let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate(self.tcx).is_none(); + let is_unleashable = O::IS_SUPPORTED_IN_MIRI && O::feature_gate().is_none(); if is_unleashable && self.tcx.sess.opts.debugging_opts.unleash_the_miri_inside_of_you { self.tcx.sess.span_warn(span, "skipping const checks"); From 2093d83afc56d54d061e733a4892c5a5f195e58e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 22:22:29 +0300 Subject: [PATCH 1150/1250] def_collector: Fully visit async functions --- src/librustc_resolve/def_collector.rs | 83 +++++-------------- src/test/ui/async-await/expansion-in-attrs.rs | 13 +++ 2 files changed, 35 insertions(+), 61 deletions(-) create mode 100644 src/test/ui/async-await/expansion-in-attrs.rs diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 0d276e68614..1d6542f25db 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -2,7 +2,7 @@ use log::debug; use rustc::hir::map::definitions::*; use rustc_ast::ast::*; use rustc_ast::token::{self, Token}; -use rustc_ast::visit; +use rustc_ast::visit::{self, FnKind}; use rustc_expand::expand::AstFragment; use rustc_hir::def_id::DefIndex; use rustc_span::hygiene::ExpnId; @@ -38,42 +38,6 @@ impl<'a> DefCollector<'a> { self.parent_def = orig_parent_def; } - fn visit_async_fn( - &mut self, - id: NodeId, - name: Name, - span: Span, - header: &FnHeader, - generics: &'a Generics, - decl: &'a FnDecl, - body: Option<&'a Block>, - ) { - let (closure_id, return_impl_trait_id) = match header.asyncness { - Async::Yes { span: _, closure_id, return_impl_trait_id } => { - (closure_id, return_impl_trait_id) - } - _ => unreachable!(), - }; - - // For async functions, we need to create their inner defs inside of a - // closure to match their desugared representation. - let fn_def_data = DefPathData::ValueNs(name); - let fn_def = self.create_def(id, fn_def_data, span); - return self.with_parent(fn_def, |this| { - this.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); - - visit::walk_generics(this, generics); - visit::walk_fn_decl(this, decl); - - let closure_def = this.create_def(closure_id, DefPathData::ClosureExpr, span); - this.with_parent(closure_def, |this| { - if let Some(body) = body { - visit::walk_block(this, body); - } - }) - }); - } - fn collect_field(&mut self, field: &'a StructField, index: Option) { let index = |this: &Self| { index.unwrap_or_else(|| { @@ -117,17 +81,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { | ItemKind::ExternCrate(..) | ItemKind::ForeignMod(..) | ItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), - ItemKind::Fn(_, sig, generics, body) if sig.header.asyncness.is_async() => { - return self.visit_async_fn( - i.id, - i.ident.name, - i.span, - &sig.header, - generics, - &sig.decl, - body.as_deref(), - ); - } ItemKind::Static(..) | ItemKind::Const(..) | ItemKind::Fn(..) => { DefPathData::ValueNs(i.ident.name) } @@ -154,6 +107,27 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { }); } + fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) { + if let FnKind::Fn(_, _, sig, _, body) = fn_kind { + if let Async::Yes { closure_id, return_impl_trait_id, .. } = sig.header.asyncness { + self.create_def(return_impl_trait_id, DefPathData::ImplTrait, span); + + // For async functions, we need to create their inner defs inside of a + // closure to match their desugared representation. Besides that, + // we must mirror everything that `visit::walk_fn` below does. + self.visit_fn_header(&sig.header); + visit::walk_fn_decl(self, &sig.decl); + if let Some(body) = body { + let closure_def = self.create_def(closure_id, DefPathData::ClosureExpr, span); + self.with_parent(closure_def, |this| this.visit_block(body)); + } + return; + } + } + + visit::walk_fn(self, fn_kind, span); + } + fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { self.create_def(id, DefPathData::Misc, use_tree.span); visit::walk_use_tree(self, use_tree, id); @@ -215,19 +189,6 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { fn visit_assoc_item(&mut self, i: &'a AssocItem, ctxt: visit::AssocCtxt) { let def_data = match &i.kind { - AssocItemKind::Fn(_, FnSig { header, decl }, generics, body) - if header.asyncness.is_async() => - { - return self.visit_async_fn( - i.id, - i.ident.name, - i.span, - header, - generics, - decl, - body.as_deref(), - ); - } AssocItemKind::Fn(..) | AssocItemKind::Const(..) => DefPathData::ValueNs(i.ident.name), AssocItemKind::TyAlias(..) => DefPathData::TypeNs(i.ident.name), AssocItemKind::Macro(..) => return self.visit_macro_invoc(i.id), diff --git a/src/test/ui/async-await/expansion-in-attrs.rs b/src/test/ui/async-await/expansion-in-attrs.rs new file mode 100644 index 00000000000..af77c3463b5 --- /dev/null +++ b/src/test/ui/async-await/expansion-in-attrs.rs @@ -0,0 +1,13 @@ +// check-pass +// edition:2018 + +macro_rules! with_doc { + ($doc: expr) => { + #[doc = $doc] + async fn f() {} + }; +} + +with_doc!(concat!("")); + +fn main() {} From 5760db14f91352d543fe352c989faa80606e7a0a Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 15 Mar 2020 06:49:45 +0530 Subject: [PATCH 1151/1250] Update src/librustc_error_codes/error_codes/E0634.md Co-Authored-By: Dylan DPC --- src/librustc_error_codes/error_codes/E0634.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0634.md b/src/librustc_error_codes/error_codes/E0634.md index 5057aa6094e..9f61d882cb1 100644 --- a/src/librustc_error_codes/error_codes/E0634.md +++ b/src/librustc_error_codes/error_codes/E0634.md @@ -1,4 +1,4 @@ -A type has conflicting `packed` representation hint. +A type has conflicting `packed` representation hints. Erroneous code examples: From 2974685f09d7123c1605028dc1ae2422589d0f15 Mon Sep 17 00:00:00 2001 From: Ayush Mishra Date: Sun, 15 Mar 2020 06:49:54 +0530 Subject: [PATCH 1152/1250] Update src/librustc_error_codes/error_codes/E0634.md Co-Authored-By: Dylan DPC --- src/librustc_error_codes/error_codes/E0634.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0634.md b/src/librustc_error_codes/error_codes/E0634.md index 9f61d882cb1..0c4ed2596e2 100644 --- a/src/librustc_error_codes/error_codes/E0634.md +++ b/src/librustc_error_codes/error_codes/E0634.md @@ -11,7 +11,7 @@ struct Company(i32); struct Company(i32); ``` -You cannot use conflicting `packed` hint on a same type. If you want to pack a +You cannot use conflicting `packed` hints on a same type. If you want to pack a type to a given size, you should provide a size to packed: ``` From a4ffbaadc81f9768a262059af77cf35fb88784bf Mon Sep 17 00:00:00 2001 From: YI Date: Sat, 14 Mar 2020 11:57:04 +0800 Subject: [PATCH 1153/1250] Add more context to the literal overflow message --- src/librustc_lint/types.rs | 44 ++++++++++++++++--- .../ui/enum/enum-discrim-too-small2.stderr | 7 +++ src/test/ui/issues/issue-63364.stderr | 1 + .../ui/lint/deny-overflowing-literals.stderr | 1 + .../lint/lint-range-endpoint-overflow.stderr | 6 +++ src/test/ui/lint/lint-type-limits2.stderr | 1 + src/test/ui/lint/lint-type-limits3.stderr | 1 + src/test/ui/lint/lint-type-overflow.stderr | 35 +++++++++++++++ src/test/ui/lint/lint-type-overflow2.stderr | 9 ++++ src/test/ui/lint/type-overflow.stderr | 13 +++--- 10 files changed, 107 insertions(+), 11 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 86d93612e99..b5c0296e297 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -165,7 +165,7 @@ fn report_bin_hex_error( let mut err = lint.build(&format!("literal out of range for {}", t)); err.note(&format!( "the literal `{}` (decimal `{}`) does not fit into \ - an `{}` and will become `{}{}`", + the type `{}` and will become `{}{}`", repr_str, val, t, actually, t )); if let Some(sugg_ty) = get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative) @@ -242,7 +242,7 @@ fn lint_int_literal<'a, 'tcx>( v: u128, ) { let int_type = t.normalize(cx.sess().target.ptr_width); - let (_, max) = int_ty_range(int_type); + let (min, max) = int_ty_range(int_type); let max = max as u128; let negative = type_limits.negated_expr_id == e.hir_id; @@ -267,7 +267,19 @@ fn lint_int_literal<'a, 'tcx>( } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .ok() + .expect("must get snippet from literal"), + t.name_str(), + min, + max, + )) + .emit(); }); } } @@ -320,7 +332,19 @@ fn lint_uint_literal<'a, 'tcx>( return; } cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` whose range is `{}..={}`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .ok() + .expect("must get snippet from literal"), + t.name_str(), + min, + max, + )) + .emit() }); } } @@ -352,7 +376,17 @@ fn lint_literal<'a, 'tcx>( }; if is_infinite == Ok(true) { cx.struct_span_lint(OVERFLOWING_LITERALS, e.span, |lint| { - lint.build(&format!("literal out of range for `{}`", t.name_str())).emit() + lint.build(&format!("literal out of range for `{}`", t.name_str())) + .note(&format!( + "the literal `{}` does not fit into the type `{}` and will be converted to `std::{}::INFINITY`", + cx.sess() + .source_map() + .span_to_snippet(lit.span) + .expect("must get snippet from literal"), + t.name_str(), + t.name_str(), + )) + .emit(); }); } } diff --git a/src/test/ui/enum/enum-discrim-too-small2.stderr b/src/test/ui/enum/enum-discrim-too-small2.stderr index 3aa88df29f1..fadf6ab86b4 100644 --- a/src/test/ui/enum/enum-discrim-too-small2.stderr +++ b/src/test/ui/enum/enum-discrim-too-small2.stderr @@ -9,24 +9,31 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `223` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i16` --> $DIR/enum-discrim-too-small2.rs:15:12 | LL | Ci16 = 55555, | ^^^^^ + | + = note: the literal `55555` does not fit into the type `i16` whose range is `-32768..=32767` error: literal out of range for `i32` --> $DIR/enum-discrim-too-small2.rs:22:12 | LL | Ci32 = 3_000_000_000, | ^^^^^^^^^^^^^ + | + = note: the literal `3_000_000_000` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i64` --> $DIR/enum-discrim-too-small2.rs:29:12 | LL | Ci64 = 9223372036854775809, | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: aborting due to 4 previous errors diff --git a/src/test/ui/issues/issue-63364.stderr b/src/test/ui/issues/issue-63364.stderr index 60ff318f35a..0375359aeab 100644 --- a/src/test/ui/issues/issue-63364.stderr +++ b/src/test/ui/issues/issue-63364.stderr @@ -5,6 +5,7 @@ LL | for n in 100_000.. { | ^^^^^^^ | = note: `#[deny(overflowing_literals)]` on by default + = note: the literal `100_000` does not fit into the type `u16` whose range is `0..=65535` error: aborting due to previous error diff --git a/src/test/ui/lint/deny-overflowing-literals.stderr b/src/test/ui/lint/deny-overflowing-literals.stderr index 7f59495023e..127dd4127c2 100644 --- a/src/test/ui/lint/deny-overflowing-literals.stderr +++ b/src/test/ui/lint/deny-overflowing-literals.stderr @@ -5,6 +5,7 @@ LL | let x: u8 = 256; | ^^^ | = note: `#[deny(overflowing_literals)]` on by default + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: range endpoint is out of range for `u8` --> $DIR/deny-overflowing-literals.rs:5:14 diff --git a/src/test/ui/lint/lint-range-endpoint-overflow.stderr b/src/test/ui/lint/lint-range-endpoint-overflow.stderr index dff61e022eb..d2df7372741 100644 --- a/src/test/ui/lint/lint-range-endpoint-overflow.stderr +++ b/src/test/ui/lint/lint-range-endpoint-overflow.stderr @@ -15,18 +15,24 @@ error: literal out of range for `u8` | LL | let range_c = 0..=256; | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:7:19 | LL | let range_d = 256..5; | ^^^ + | + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:8:22 | LL | let range_e = 0..257; | ^^^ + | + = note: the literal `257` does not fit into the type `u8` whose range is `0..=255` error: range endpoint is out of range for `u8` --> $DIR/lint-range-endpoint-overflow.rs:9:20 diff --git a/src/test/ui/lint/lint-type-limits2.stderr b/src/test/ui/lint/lint-type-limits2.stderr index bf510823b56..1e3c88dfc46 100644 --- a/src/test/ui/lint/lint-type-limits2.stderr +++ b/src/test/ui/lint/lint-type-limits2.stderr @@ -17,6 +17,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: aborting due to previous error diff --git a/src/test/ui/lint/lint-type-limits3.stderr b/src/test/ui/lint/lint-type-limits3.stderr index 00441f99e60..150e9a2aa47 100644 --- a/src/test/ui/lint/lint-type-limits3.stderr +++ b/src/test/ui/lint/lint-type-limits3.stderr @@ -17,6 +17,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `200` does not fit into the type `i8` whose range is `-128..=127` error: aborting due to previous error diff --git a/src/test/ui/lint/lint-type-overflow.stderr b/src/test/ui/lint/lint-type-overflow.stderr index ec15313158d..7715c0d3a4d 100644 --- a/src/test/ui/lint/lint-type-overflow.stderr +++ b/src/test/ui/lint/lint-type-overflow.stderr @@ -9,108 +9,143 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `256` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `u8` --> $DIR/lint-type-overflow.rs:13:14 | LL | let x1 = 256_u8; | ^^^^^^ + | + = note: the literal `256_u8` does not fit into the type `u8` whose range is `0..=255` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:16:18 | LL | let x1: i8 = 128; | ^^^ + | + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:18:19 | LL | let x3: i8 = -129; | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:19:19 | LL | let x3: i8 = -(129); | ^^^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:20:20 | LL | let x3: i8 = -{129}; | ^^^ + | + = note: the literal `129` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:22:10 | LL | test(1000); | ^^^^ + | + = note: the literal `1000` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:24:13 | LL | let x = 128_i8; | ^^^^^^ + | + = note: the literal `128_i8` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i8` --> $DIR/lint-type-overflow.rs:28:14 | LL | let x = -129_i8; | ^^^^^^ + | + = note: the literal `129_i8` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:32:18 | LL | let x: i32 = 2147483648; | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:33:13 | LL | let x = 2147483648_i32; | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483648_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:36:19 | LL | let x: i32 = -2147483649; | ^^^^^^^^^^ + | + = note: the literal `2147483649` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:37:14 | LL | let x = -2147483649_i32; | ^^^^^^^^^^^^^^ + | + = note: the literal `2147483649_i32` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i32` --> $DIR/lint-type-overflow.rs:38:13 | LL | let x = 2147483648; | ^^^^^^^^^^ + | + = note: the literal `2147483648` does not fit into the type `i32` whose range is `-2147483648..=2147483647` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:40:13 | LL | let x = 9223372036854775808_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775808_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:42:13 | LL | let x = 18446744073709551615_i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `18446744073709551615_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:43:19 | LL | let x: i64 = -9223372036854775809; | ^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: literal out of range for `i64` --> $DIR/lint-type-overflow.rs:44:14 | LL | let x = -9223372036854775809_i64; | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `9223372036854775809_i64` does not fit into the type `i64` whose range is `-9223372036854775808..=9223372036854775807` error: aborting due to 18 previous errors diff --git a/src/test/ui/lint/lint-type-overflow2.stderr b/src/test/ui/lint/lint-type-overflow2.stderr index dfc691ab910..61e33b7a260 100644 --- a/src/test/ui/lint/lint-type-overflow2.stderr +++ b/src/test/ui/lint/lint-type-overflow2.stderr @@ -9,30 +9,39 @@ note: the lint level is defined here | LL | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `128` does not fit into the type `i8` whose range is `-128..=127` error: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:9:14 | LL | let x = -3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY` error: literal out of range for `f32` --> $DIR/lint-type-overflow2.rs:10:14 | LL | let x = 3.40282357e+38_f32; | ^^^^^^^^^^^^^^^^^^ + | + = note: the literal `3.40282357e+38_f32` does not fit into the type `f32` and will be converted to `std::f32::INFINITY` error: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:11:14 | LL | let x = -1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY` error: literal out of range for `f64` --> $DIR/lint-type-overflow2.rs:12:14 | LL | let x = 1.7976931348623159e+308_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `1.7976931348623159e+308_f64` does not fit into the type `f64` and will be converted to `std::f64::INFINITY` error: aborting due to 5 previous errors diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 2432eb78b87..a7a788b877a 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -9,6 +9,7 @@ note: the lint level is defined here | LL | #![warn(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `255i8` does not fit into the type `i8` whose range is `-128..=127` warning: literal out of range for i8 --> $DIR/type-overflow.rs:10:16 @@ -16,7 +17,7 @@ warning: literal out of range for i8 LL | let fail = 0b1000_0001i8; | ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8` | - = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8` + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into the type `i8` and will become `-127i8` warning: literal out of range for i64 --> $DIR/type-overflow.rs:12:16 @@ -24,7 +25,7 @@ warning: literal out of range for i64 LL | let fail = 0x8000_0000_0000_0000i64; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64` | - = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64` + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into the type `i64` and will become `-9223372036854775808i64` warning: literal out of range for u32 --> $DIR/type-overflow.rs:14:16 @@ -32,7 +33,7 @@ warning: literal out of range for u32 LL | let fail = 0x1_FFFF_FFFFu32; | ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64` | - = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32` + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into the type `u32` and will become `4294967295u32` warning: literal out of range for i128 --> $DIR/type-overflow.rs:16:22 @@ -40,7 +41,7 @@ warning: literal out of range for i128 LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128` + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into the type `i128` and will become `-170141183460469231731687303715884105728i128` = help: consider using `u128` instead warning: literal out of range for i32 @@ -49,7 +50,7 @@ warning: literal out of range for i32 LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32` + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into the type `i32` and will become `-2i32` = help: consider using `i128` instead warning: literal out of range for i8 @@ -58,5 +59,5 @@ warning: literal out of range for i8 LL | let fail = -0b1111_1111i8; | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` | - = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8` + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into the type `i8` and will become `-1i8` From 401a3f376263886f997013e7bfe266ef6b7568dd Mon Sep 17 00:00:00 2001 From: Lukas Kalbertodt Date: Sun, 15 Mar 2020 10:19:26 +0100 Subject: [PATCH 1154/1250] Fix "since" field for `Once::is_complete`'s `#[stable]` attribute It was accidentally merged with the wrong version. --- src/libstd/sync/once.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/sync/once.rs b/src/libstd/sync/once.rs index b99b4d8d9fd..1e6b6c430be 100644 --- a/src/libstd/sync/once.rs +++ b/src/libstd/sync/once.rs @@ -363,7 +363,7 @@ impl Once { /// assert!(handle.join().is_err()); /// assert_eq!(INIT.is_completed(), false); /// ``` - #[stable(feature = "once_is_completed", since = "1.44.0")] + #[stable(feature = "once_is_completed", since = "1.43.0")] #[inline] pub fn is_completed(&self) -> bool { // An `Acquire` load is enough because that makes all the initialization From 78f01eca3f4d6843125199578d3f2186655ddf62 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 19:44:11 +0300 Subject: [PATCH 1155/1250] resolve: Prevent fresh bindings from shadowing ambiguity items Correctly treat const generic parameters in fresh binding disambiguation --- .../hair/pattern/check_match.rs | 3 ++ src/librustc_mir_build/hair/pattern/mod.rs | 7 +++- src/librustc_resolve/late.rs | 39 +++++++++++------- src/librustc_resolve/lib.rs | 7 ---- src/librustc_typeck/check/pat.rs | 3 +- src/test/ui/binding/ambiguity-item.rs | 18 ++++++++ src/test/ui/binding/ambiguity-item.stderr | 41 +++++++++++++++++++ src/test/ui/binding/const-param.rs | 12 ++++++ src/test/ui/binding/const-param.stderr | 17 ++++++++ 9 files changed, 123 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/binding/ambiguity-item.rs create mode 100644 src/test/ui/binding/ambiguity-item.stderr create mode 100644 src/test/ui/binding/const-param.rs create mode 100644 src/test/ui/binding/const-param.stderr diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index d0eefb2e4d1..b817470b4c3 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -87,6 +87,9 @@ impl PatCtxt<'_, '_> { PatternError::AssocConstInPattern(span) => { self.span_e0158(span, "associated consts cannot be referenced in patterns") } + PatternError::ConstParamInPattern(span) => { + self.span_e0158(span, "const parameters cannot be referenced in patterns") + } PatternError::FloatBug => { // FIXME(#31407) this is only necessary because float parsing is buggy ::rustc::mir::interpret::struct_error( diff --git a/src/librustc_mir_build/hair/pattern/mod.rs b/src/librustc_mir_build/hair/pattern/mod.rs index f58216fbb4e..6786c356293 100644 --- a/src/librustc_mir_build/hair/pattern/mod.rs +++ b/src/librustc_mir_build/hair/pattern/mod.rs @@ -31,6 +31,7 @@ use std::fmt; #[derive(Clone, Debug)] crate enum PatternError { AssocConstInPattern(Span), + ConstParamInPattern(Span), StaticInPattern(Span), FloatBug, NonConstPath(Span), @@ -727,7 +728,11 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { | Res::SelfCtor(..) => PatKind::Leaf { subpatterns }, _ => { - self.errors.push(PatternError::NonConstPath(span)); + let pattern_error = match res { + Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span), + _ => PatternError::NonConstPath(span), + }; + self.errors.push(pattern_error); PatKind::Wild } }; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 97f3ad72ee3..30ba48f7970 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -1517,9 +1517,17 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ident: Ident, has_sub: bool, ) -> Option { - let binding = - self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?.item()?; - let res = binding.res(); + let ls_binding = self.resolve_ident_in_lexical_scope(ident, ValueNS, None, pat.span)?; + let (res, binding) = match ls_binding { + LexicalScopeBinding::Item(binding) if binding.is_ambiguity() => { + // For ambiguous bindings we don't know all their definitions and cannot check + // whether they can be shadowed by fresh bindings or not, so force an error. + self.r.record_use(ident, ValueNS, binding, false); + return None; + } + LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)), + LexicalScopeBinding::Res(res) => (res, None), + }; // An immutable (no `mut`) by-value (no `ref`) binding pattern without // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could @@ -1527,11 +1535,15 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { let is_syntactic_ambiguity = !has_sub && bm == BindingMode::ByValue(Mutability::Not); match res { - Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::Def(DefKind::Const, _) + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) + | Res::Def(DefKind::Const, _) + | Res::Def(DefKind::ConstParam, _) if is_syntactic_ambiguity => { // Disambiguate in favor of a unit struct/variant or constant pattern. - self.r.record_use(ident, ValueNS, binding, false); + if let Some(binding) = binding { + self.r.record_use(ident, ValueNS, binding, false); + } Some(res) } Res::Def(DefKind::Ctor(..), _) @@ -1547,23 +1559,20 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ResolutionError::BindingShadowsSomethingUnacceptable( pat_src.descr(), ident.name, - binding, + binding.expect("no binding for a ctor or static"), ), ); None } - Res::Def(DefKind::Fn, _) | Res::Err => { + Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => { // These entities are explicitly allowed to be shadowed by fresh bindings. None } - res => { - span_bug!( - ident.span, - "unexpected resolution for an \ - identifier in pattern: {:?}", - res - ); - } + _ => span_bug!( + ident.span, + "unexpected resolution for an identifier in pattern: {:?}", + res + ), } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 948b86225f3..37a800a0b7b 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -323,13 +323,6 @@ enum LexicalScopeBinding<'a> { } impl<'a> LexicalScopeBinding<'a> { - fn item(self) -> Option<&'a NameBinding<'a>> { - match self { - LexicalScopeBinding::Item(binding) => Some(binding), - _ => None, - } - } - fn res(self) -> Res { match self { LexicalScopeBinding::Item(binding) => binding.res(), diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index 60132dde9ca..fabf3dd1153 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -716,7 +716,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Res::Def(DefKind::Ctor(_, CtorKind::Const), _) | Res::SelfCtor(..) | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::AssocConst, _) => {} // OK + | Res::Def(DefKind::AssocConst, _) + | Res::Def(DefKind::ConstParam, _) => {} // OK _ => bug!("unexpected pattern resolution: {:?}", res), } diff --git a/src/test/ui/binding/ambiguity-item.rs b/src/test/ui/binding/ambiguity-item.rs new file mode 100644 index 00000000000..10613cc6164 --- /dev/null +++ b/src/test/ui/binding/ambiguity-item.rs @@ -0,0 +1,18 @@ +// Identifier pattern referring to an ambiguity item is an error (issue #46079). + +mod m { + pub fn f() {} +} +use m::*; + +mod n { + pub fn f() {} +} +use n::*; // OK, no conflict with `use m::*;` + +fn main() { + let v = f; //~ ERROR `f` is ambiguous + match v { + f => {} //~ ERROR `f` is ambiguous + } +} diff --git a/src/test/ui/binding/ambiguity-item.stderr b/src/test/ui/binding/ambiguity-item.stderr new file mode 100644 index 00000000000..615193c0d02 --- /dev/null +++ b/src/test/ui/binding/ambiguity-item.stderr @@ -0,0 +1,41 @@ +error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) + --> $DIR/ambiguity-item.rs:14:13 + | +LL | let v = f; + | ^ ambiguous name + | +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error[E0659]: `f` is ambiguous (glob import vs glob import in the same module) + --> $DIR/ambiguity-item.rs:16:9 + | +LL | f => {} + | ^ ambiguous name + | +note: `f` could refer to the function imported here + --> $DIR/ambiguity-item.rs:6:5 + | +LL | use m::*; + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate +note: `f` could also refer to the function imported here + --> $DIR/ambiguity-item.rs:11:5 + | +LL | use n::*; // OK, no conflict with `use m::*;` + | ^^^^ + = help: consider adding an explicit import of `f` to disambiguate + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0659`. diff --git a/src/test/ui/binding/const-param.rs b/src/test/ui/binding/const-param.rs new file mode 100644 index 00000000000..3c7f4d071f6 --- /dev/null +++ b/src/test/ui/binding/const-param.rs @@ -0,0 +1,12 @@ +// Identifier pattern referring to a const generic parameter is an error (issue #68853). + +#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete + +fn check() { + match 1 { + N => {} //~ ERROR const parameters cannot be referenced in patterns + _ => {} + } +} + +fn main() {} diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr new file mode 100644 index 00000000000..25b1c75c9a0 --- /dev/null +++ b/src/test/ui/binding/const-param.stderr @@ -0,0 +1,17 @@ +warning: the feature `const_generics` is incomplete and may cause the compiler to crash + --> $DIR/const-param.rs:3:12 + | +LL | #![feature(const_generics)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + +error[E0158]: const parameters cannot be referenced in patterns + --> $DIR/const-param.rs:7:9 + | +LL | N => {} + | ^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0158`. From b8ac984129f81f42d0ea9cd8fc0ca6a5c08c4f58 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 15 Mar 2020 11:51:09 +0100 Subject: [PATCH 1156/1250] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 974c8be95ec..a7891c05f7f 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 974c8be95ec17cd986251d7700cd432a39576939 +Subproject commit a7891c05f7fdb329f68c991abbb39dafc1f6b4a5 From a62dd0e3bab098a4dd389a7942c2f4861f83443f Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Feb 2020 17:07:36 +0000 Subject: [PATCH 1157/1250] Add `min_specialization` feature Currently the only difference between it and `specialization` is that it only allows specializing functions. --- src/librustc_ast_passes/feature_gate.rs | 20 +++++++++++++------ src/librustc_feature/active.rs | 5 +++++ .../traits/specialize/mod.rs | 4 +++- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 5f36149451d..f9f4c3efeb6 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -542,15 +542,12 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { } fn visit_assoc_item(&mut self, i: &'a ast::AssocItem, ctxt: AssocCtxt) { - if let ast::Defaultness::Default(_) = i.kind.defaultness() { - gate_feature_post!(&self, specialization, i.span, "specialization is unstable"); - } - - match i.kind { + let is_fn = match i.kind { ast::AssocItemKind::Fn(_, ref sig, _, _) => { if let (ast::Const::Yes(_), AssocCtxt::Trait) = (sig.header.constness, ctxt) { gate_feature_post!(&self, const_fn, i.span, "const fn is unstable"); } + true } ast::AssocItemKind::TyAlias(_, ref generics, _, ref ty) => { if let (Some(_), AssocCtxt::Trait) = (ty, ctxt) { @@ -565,8 +562,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { self.check_impl_trait(ty); } self.check_gat(generics, i.span); + false } - _ => {} + _ => false, + }; + if let ast::Defaultness::Default(_) = i.kind.defaultness() { + // Limit `min_specialization` to only specializing functions. + gate_feature_fn!( + &self, + |x: &Features| x.specialization || (is_fn && x.min_specialization), + i.span, + sym::specialization, + "specialization is unstable" + ); } visit::walk_assoc_item(self, i, ctxt) } diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs index 3a0fc6f8da1..9f1fee8fc09 100644 --- a/src/librustc_feature/active.rs +++ b/src/librustc_feature/active.rs @@ -301,6 +301,11 @@ declare_features! ( /// Allows specialization of implementations (RFC 1210). (active, specialization, "1.7.0", Some(31844), None), + /// A minimal, sound subset of specialization intended to be used by the + /// standard library until the soundness issues with specialization + /// are fixed. + (active, min_specialization, "1.7.0", Some(31844), None), + /// Allows using `#[naked]` on functions. (active, naked_functions, "1.9.0", Some(32408), None), diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index d1d4a58fdf2..770253e635e 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -161,7 +161,9 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId, // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. - if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) { + let features = tcx.features(); + let specialization_enabled = features.specialization || features.min_specialization; + if !specialization_enabled && (impl1_def_id.is_local() || impl2_def_id.is_local()) { return false; } From c24b4bf41098edd860d03463e00f2590293196dc Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Feb 2020 17:56:25 +0000 Subject: [PATCH 1158/1250] Add attributes to allow specializing on traits --- src/libcore/marker.rs | 1 + src/librustc/ty/trait_def.rs | 33 ++++++++++++++++++- src/librustc_feature/builtin_attrs.rs | 8 +++++ src/librustc_metadata/rmeta/decoder.rs | 2 ++ src/librustc_metadata/rmeta/encoder.rs | 1 + src/librustc_metadata/rmeta/mod.rs | 1 + src/librustc_span/symbol.rs | 3 ++ src/librustc_typeck/check/wfcheck.rs | 5 ++- src/librustc_typeck/coherence/mod.rs | 16 +++++++++ src/librustc_typeck/collect.rs | 17 +++++++++- .../auxiliary/specialization-trait.rs | 6 ++++ .../impl_specialization_trait.rs | 16 +++++++++ .../impl_specialization_trait.stderr | 10 ++++++ 13 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs create mode 100644 src/test/ui/specialization/min_specialization/impl_specialization_trait.rs create mode 100644 src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 2800f11cc01..2b908f07af8 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -90,6 +90,7 @@ impl !Send for *mut T {} ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>" )] #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable +#[cfg_attr(not(bootstrap), rustc_specialization_trait)] pub trait Sized { // Empty. } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 0cf1c397648..2b5d72de358 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -33,11 +33,33 @@ pub struct TraitDef { /// and thus `impl`s of it are allowed to overlap. pub is_marker: bool, + /// Used to determine whether the standard library is allowed to specialize + /// on this trait. + pub specialization_kind: TraitSpecializationKind, + /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: DefPathHash, } +/// Whether this trait is treated specially by the standard library +/// specialization lint. +#[derive(HashStable, PartialEq, Clone, Copy, RustcEncodable, RustcDecodable)] +pub enum TraitSpecializationKind { + /// The default. Specializing on this trait is not allowed. + None, + /// Specializing on this trait is allowed because it doesn't have any + /// methods. For example `Sized` or `FusedIterator`. + /// Applies to traits with the `rustc_unsafe_specialization_marker` + /// attribute. + Marker, + /// Specializing on this trait is allowed because all of the impls of this + /// trait are "always applicable". Always applicable means that if + /// `X<'x>: T<'y>` for any lifetimes, then `for<'a, 'b> X<'a>: T<'b>`. + /// Applies to traits with the `rustc_specialization_trait` attribute. + AlwaysApplicable, +} + #[derive(Default)] pub struct TraitImpls { blanket_impls: Vec, @@ -52,9 +74,18 @@ impl<'tcx> TraitDef { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, ) -> TraitDef { - TraitDef { def_id, unsafety, paren_sugar, has_auto_impl, is_marker, def_path_hash } + TraitDef { + def_id, + unsafety, + paren_sugar, + has_auto_impl, + is_marker, + specialization_kind, + def_path_hash, + } } pub fn ancestors( diff --git a/src/librustc_feature/builtin_attrs.rs b/src/librustc_feature/builtin_attrs.rs index e9a5364c658..83830b9d78a 100644 --- a/src/librustc_feature/builtin_attrs.rs +++ b/src/librustc_feature/builtin_attrs.rs @@ -530,6 +530,14 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_test_marker, Normal, template!(Word), "the `#[rustc_test_marker]` attribute is used internally to track tests", ), + rustc_attr!( + rustc_unsafe_specialization_marker, Normal, template!(Word), + "the `#[rustc_unsafe_specialization_marker]` attribute is used to check specializations" + ), + rustc_attr!( + rustc_specialization_trait, Normal, template!(Word), + "the `#[rustc_specialization_trait]` attribute is used to check specializations" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 1d8eb0cde46..0fab64978ee 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -651,6 +651,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.paren_sugar, data.has_auto_impl, data.is_marker, + data.specialization_kind, self.def_path_table.def_path_hash(item_id), ) } @@ -660,6 +661,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, false, false, + ty::trait_def::TraitSpecializationKind::None, self.def_path_table.def_path_hash(item_id), ), _ => bug!("def-index does not refer to trait or trait alias"), diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index ce62f15f85d..1d8b2c0f6f5 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1114,6 +1114,7 @@ impl EncodeContext<'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: self.tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, + specialization_kind: trait_def.specialization_kind, }; EntryKind::Trait(self.lazy(data)) diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 89e26b15d50..2672d772b1c 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -350,6 +350,7 @@ struct TraitData { paren_sugar: bool, has_auto_impl: bool, is_marker: bool, + specialization_kind: ty::trait_def::TraitSpecializationKind, } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index bca4bfee85a..389a8bb9920 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -453,6 +453,7 @@ symbols! { min_align_of, min_const_fn, min_const_unsafe_fn, + min_specialization, mips_target_feature, mmx_target_feature, module, @@ -654,6 +655,8 @@ symbols! { rustc_proc_macro_decls, rustc_promotable, rustc_regions, + rustc_unsafe_specialization_marker, + rustc_specialization_trait, rustc_stable, rustc_std_internal_symbol, rustc_symbol_name, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 026e68e10e0..2f1654c18d9 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -4,6 +4,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par use rustc::middle::lang_items; use rustc::session::parse::feature_err; use rustc::ty::subst::{InternalSubsts, Subst}; +use rustc::ty::trait_def::TraitSpecializationKind; use rustc::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; @@ -412,7 +413,9 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) { let trait_def_id = tcx.hir().local_def_id(item.hir_id); let trait_def = tcx.trait_def(trait_def_id); - if trait_def.is_marker { + if trait_def.is_marker + || matches!(trait_def.specialization_kind, TraitSpecializationKind::Marker) + { for associated_def_id in &*tcx.associated_item_def_ids(trait_def_id) { struct_span_err!( tcx.sess, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 0d0149f9673..27b2c19499c 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -76,6 +76,22 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt<'_>, impl_def_id: DefId, tra return; } + if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = + tcx.trait_def(trait_def_id).specialization_kind + { + if !tcx.features().specialization && !tcx.features().min_specialization { + let span = impl_header_span(tcx, impl_def_id); + tcx.sess + .struct_span_err( + span, + "implementing `rustc_specialization_trait` traits is unstable", + ) + .help("add `#![feature(min_specialization)]` to the crate attributes to enable") + .emit(); + return; + } + } + let trait_name = if did == li.fn_trait() { "Fn" } else if did == li.fn_mut_trait() { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cd63dacdcda..6597cc47689 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1032,8 +1032,23 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::TraitDef { } let is_marker = tcx.has_attr(def_id, sym::marker); + let spec_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) { + ty::trait_def::TraitSpecializationKind::Marker + } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) { + ty::trait_def::TraitSpecializationKind::AlwaysApplicable + } else { + ty::trait_def::TraitSpecializationKind::None + }; let def_path_hash = tcx.def_path_hash(def_id); - let def = ty::TraitDef::new(def_id, unsafety, paren_sugar, is_auto, is_marker, def_path_hash); + let def = ty::TraitDef::new( + def_id, + unsafety, + paren_sugar, + is_auto, + is_marker, + spec_kind, + def_path_hash, + ); tcx.arena.alloc(def) } diff --git a/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs new file mode 100644 index 00000000000..6ec0d261d51 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/auxiliary/specialization-trait.rs @@ -0,0 +1,6 @@ +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +pub trait SpecTrait { + fn method(&self); +} diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs new file mode 100644 index 00000000000..723ed71c3e9 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.rs @@ -0,0 +1,16 @@ +// Check that specialization traits can't be implemented without a feature. + +// gate-test-min_specialization + +// aux-build:specialization-trait.rs + +extern crate specialization_trait; + +struct A {} + +impl specialization_trait::SpecTrait for A { + //~^ ERROR implementing `rustc_specialization_trait` traits is unstable + fn method(&self) {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr new file mode 100644 index 00000000000..934103d49dc --- /dev/null +++ b/src/test/ui/specialization/min_specialization/impl_specialization_trait.stderr @@ -0,0 +1,10 @@ +error: implementing `rustc_specialization_trait` traits is unstable + --> $DIR/impl_specialization_trait.rs:11:1 + | +LL | impl specialization_trait::SpecTrait for A { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(min_specialization)]` to the crate attributes to enable + +error: aborting due to previous error + From 32d330df30c079c8d0bcdeff9049152a65c36b31 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Feb 2020 20:10:06 +0000 Subject: [PATCH 1159/1250] Avoid ICEs when we emit errors constructing the specialization graph --- src/librustc/traits/specialization_graph.rs | 29 +++++++++----- src/librustc/ty/trait_def.rs | 3 +- src/librustc_metadata/rmeta/encoder.rs | 13 ++++--- .../traits/project.rs | 24 +++++++----- .../traits/specialize/mod.rs | 38 ++++++++++--------- src/librustc_typeck/check/mod.rs | 28 ++++++++------ 6 files changed, 79 insertions(+), 56 deletions(-) diff --git a/src/librustc/traits/specialization_graph.rs b/src/librustc/traits/specialization_graph.rs index d481e578fc1..1847326a742 100644 --- a/src/librustc/traits/specialization_graph.rs +++ b/src/librustc/traits/specialization_graph.rs @@ -4,6 +4,7 @@ use crate::ty::{self, TyCtxt}; use rustc_ast::ast::Ident; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_errors::ErrorReported; use rustc_hir::def_id::{DefId, DefIdMap}; /// A per-trait graph of impls in specialization order. At the moment, this @@ -23,17 +24,20 @@ use rustc_hir::def_id::{DefId, DefIdMap}; /// has at most one parent. #[derive(RustcEncodable, RustcDecodable, HashStable)] pub struct Graph { - // All impls have a parent; the "root" impls have as their parent the `def_id` - // of the trait. + /// All impls have a parent; the "root" impls have as their parent the `def_id` + /// of the trait. pub parent: DefIdMap, - // The "root" impls are found by looking up the trait's def_id. + /// The "root" impls are found by looking up the trait's def_id. pub children: DefIdMap, + + /// Whether an error was emitted while constructing the graph. + pub has_errored: bool, } impl Graph { pub fn new() -> Graph { - Graph { parent: Default::default(), children: Default::default() } + Graph { parent: Default::default(), children: Default::default(), has_errored: false } } /// The parent of a given impl, which is the `DefId` of the trait when the @@ -179,17 +183,22 @@ impl<'tcx> Ancestors<'tcx> { } /// Walk up the specialization ancestors of a given impl, starting with that -/// impl itself. +/// impl itself. Returns `None` if an error was reported while building the +/// specialization graph. pub fn ancestors( tcx: TyCtxt<'tcx>, trait_def_id: DefId, start_from_impl: DefId, -) -> Ancestors<'tcx> { +) -> Result, ErrorReported> { let specialization_graph = tcx.specialization_graph_of(trait_def_id); - Ancestors { - trait_def_id, - specialization_graph, - current_source: Some(Node::Impl(start_from_impl)), + if specialization_graph.has_errored { + Err(ErrorReported) + } else { + Ok(Ancestors { + trait_def_id, + specialization_graph, + current_source: Some(Node::Impl(start_from_impl)), + }) } } diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs index 2b5d72de358..948f1b8501d 100644 --- a/src/librustc/ty/trait_def.rs +++ b/src/librustc/ty/trait_def.rs @@ -9,6 +9,7 @@ use rustc_hir::def_id::DefId; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; +use rustc_errors::ErrorReported; use rustc_macros::HashStable; /// A trait's definition with type information. @@ -92,7 +93,7 @@ impl<'tcx> TraitDef { &self, tcx: TyCtxt<'tcx>, of_impl: DefId, - ) -> specialization_graph::Ancestors<'tcx> { + ) -> Result, ErrorReported> { specialization_graph::ancestors(tcx, self.def_id, of_impl) } } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 1d8b2c0f6f5..3f079b286b4 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1077,12 +1077,13 @@ impl EncodeContext<'tcx> { let polarity = self.tcx.impl_polarity(def_id); let parent = if let Some(trait_ref) = trait_ref { let trait_def = self.tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| { - match node { - specialization_graph::Node::Impl(parent) => Some(parent), - _ => None, - } - }) + trait_def.ancestors(self.tcx, def_id).ok() + .and_then(|mut an| an.nth(1).and_then(|node| { + match node { + specialization_graph::Node::Impl(parent) => Some(parent), + _ => None, + } + })) } else { None }; diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index dde78aa4357..1ad91574212 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -21,6 +21,7 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_ast::ast::Ident; +use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; @@ -1010,7 +1011,8 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // NOTE: This should be kept in sync with the similar code in // `rustc::ty::instance::resolve_associated_item()`. let node_item = - assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id); + assoc_ty_def(selcx, impl_data.impl_def_id, obligation.predicate.item_def_id) + .map_err(|ErrorReported| ())?; let is_default = if node_item.node.is_from_trait() { // If true, the impl inherited a `type Foo = Bar` @@ -1405,7 +1407,10 @@ fn confirm_impl_candidate<'cx, 'tcx>( let trait_def_id = tcx.trait_id_of_impl(impl_def_id).unwrap(); let param_env = obligation.param_env; - let assoc_ty = assoc_ty_def(selcx, impl_def_id, assoc_item_id); + let assoc_ty = match assoc_ty_def(selcx, impl_def_id, assoc_item_id) { + Ok(assoc_ty) => assoc_ty, + Err(ErrorReported) => return Progress { ty: tcx.types.err, obligations: nested }, + }; if !assoc_ty.item.defaultness.has_value() { // This means that the impl is missing a definition for the @@ -1444,14 +1449,14 @@ fn assoc_ty_def( selcx: &SelectionContext<'_, '_>, impl_def_id: DefId, assoc_ty_def_id: DefId, -) -> specialization_graph::NodeItem { +) -> Result, ErrorReported> { let tcx = selcx.tcx(); let assoc_ty_name = tcx.associated_item(assoc_ty_def_id).ident; let trait_def_id = tcx.impl_trait_ref(impl_def_id).unwrap().def_id; let trait_def = tcx.trait_def(trait_def_id); // This function may be called while we are still building the - // specialization graph that is queried below (via TraidDef::ancestors()), + // specialization graph that is queried below (via TraitDef::ancestors()), // so, in order to avoid unnecessary infinite recursion, we manually look // for the associated item at the given impl. // If there is no such item in that impl, this function will fail with a @@ -1461,17 +1466,16 @@ fn assoc_ty_def( if matches!(item.kind, ty::AssocKind::Type | ty::AssocKind::OpaqueTy) && tcx.hygienic_eq(item.ident, assoc_ty_name, trait_def_id) { - return specialization_graph::NodeItem { + return Ok(specialization_graph::NodeItem { node: specialization_graph::Node::Impl(impl_def_id), item: *item, - }; + }); } } - if let Some(assoc_item) = - trait_def.ancestors(tcx, impl_def_id).leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) - { - assoc_item + let ancestors = trait_def.ancestors(tcx, impl_def_id)?; + if let Some(assoc_item) = ancestors.leaf_def(tcx, assoc_ty_name, ty::AssocKind::Type) { + Ok(assoc_item) } else { // This is saying that neither the trait nor // the impl contain a definition for this diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index 770253e635e..b763851b86e 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -130,24 +130,27 @@ pub fn find_associated_item<'tcx>( let trait_def_id = tcx.trait_id_of_impl(impl_data.impl_def_id).unwrap(); let trait_def = tcx.trait_def(trait_def_id); - let ancestors = trait_def.ancestors(tcx, impl_data.impl_def_id); - match ancestors.leaf_def(tcx, item.ident, item.kind) { - Some(node_item) => { - let substs = tcx.infer_ctxt().enter(|infcx| { - let param_env = param_env.with_reveal_all(); - let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); - let substs = translate_substs( - &infcx, - param_env, - impl_data.impl_def_id, - substs, - node_item.node, - ); - infcx.tcx.erase_regions(&substs) - }); - (node_item.item.def_id, substs) + if let Ok(ancestors) = trait_def.ancestors(tcx, impl_data.impl_def_id) { + match ancestors.leaf_def(tcx, item.ident, item.kind) { + Some(node_item) => { + let substs = tcx.infer_ctxt().enter(|infcx| { + let param_env = param_env.with_reveal_all(); + let substs = substs.rebase_onto(tcx, trait_def_id, impl_data.substs); + let substs = translate_substs( + &infcx, + param_env, + impl_data.impl_def_id, + substs, + node_item.node, + ); + infcx.tcx.erase_regions(&substs) + }); + (node_item.item.def_id, substs) + } + None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id), } - None => bug!("{:?} not found in {:?}", item, impl_data.impl_def_id), + } else { + (item.def_id, substs) } } @@ -382,6 +385,7 @@ pub(super) fn specialization_graph_provider( match used_to_be_allowed { None => { + sg.has_errored = true; let err = struct_span_err!(tcx.sess, impl_span, E0119, ""); decorate(LintDiagnosticBuilder::new(err)); } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1975b248999..9e20dcec1af 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1901,8 +1901,11 @@ fn check_specialization_validity<'tcx>( hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; - let mut ancestor_impls = trait_def - .ancestors(tcx, impl_id) + let ancestors = match trait_def.ancestors(tcx, impl_id) { + Ok(ancestors) => ancestors, + Err(_) => return, + }; + let mut ancestor_impls = ancestors .skip(1) .filter_map(|parent| { if parent.is_from_trait() { @@ -2083,16 +2086,17 @@ fn check_impl_items_against_trait<'tcx>( // Check for missing items from trait let mut missing_items = Vec::new(); - for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { - let is_implemented = trait_def - .ancestors(tcx, impl_id) - .leaf_def(tcx, trait_item.ident, trait_item.kind) - .map(|node_item| !node_item.node.is_from_trait()) - .unwrap_or(false); - - if !is_implemented && !traits::impl_is_default(tcx, impl_id) { - if !trait_item.defaultness.has_value() { - missing_items.push(*trait_item); + if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id) { + for trait_item in tcx.associated_items(impl_trait_ref.def_id).in_definition_order() { + let is_implemented = ancestors + .leaf_def(tcx, trait_item.ident, trait_item.kind) + .map(|node_item| !node_item.node.is_from_trait()) + .unwrap_or(false); + + if !is_implemented && !traits::impl_is_default(tcx, impl_id) { + if !trait_item.defaultness.has_value() { + missing_items.push(*trait_item); + } } } } From 0bbbe719e831c585e0e7bdd33b2432ac5ecb1b31 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Feb 2020 20:14:02 +0000 Subject: [PATCH 1160/1250] Implement soundness check for min_specialization --- .../constrained_generic_params.rs | 14 +- src/librustc_typeck/impl_wf_check.rs | 14 +- .../impl_wf_check/min_specialization.rs | 390 ++++++++++++++++++ src/librustc_typeck/lib.rs | 1 + .../dyn-trait-assoc-types.rs | 32 ++ .../dyn-trait-assoc-types.stderr | 20 + .../repeated_projection_type.rs | 24 ++ .../repeated_projection_type.stderr | 11 + .../min_specialization/repeating_lifetimes.rs | 19 + .../repeating_lifetimes.stderr | 11 + .../min_specialization/repeating_param.rs | 17 + .../min_specialization/repeating_param.stderr | 11 + .../min_specialization/spec-iter.rs | 20 + .../min_specialization/spec-reference.rs | 19 + .../specialization_marker.rs | 17 + .../specialization_marker.stderr | 15 + .../specialization_trait.rs | 26 ++ .../specialization_trait.stderr | 29 ++ .../specialize_on_marker.rs | 24 ++ .../specialize_on_spec_trait.rs | 27 ++ .../specialize_on_static.rs | 18 + .../specialize_on_static.stderr | 11 + .../min_specialization/specialize_on_trait.rs | 20 + .../specialize_on_trait.stderr | 11 + 24 files changed, 796 insertions(+), 5 deletions(-) create mode 100644 src/librustc_typeck/impl_wf_check/min_specialization.rs create mode 100644 src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs create mode 100644 src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr create mode 100644 src/test/ui/specialization/min_specialization/repeated_projection_type.rs create mode 100644 src/test/ui/specialization/min_specialization/repeated_projection_type.stderr create mode 100644 src/test/ui/specialization/min_specialization/repeating_lifetimes.rs create mode 100644 src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr create mode 100644 src/test/ui/specialization/min_specialization/repeating_param.rs create mode 100644 src/test/ui/specialization/min_specialization/repeating_param.stderr create mode 100644 src/test/ui/specialization/min_specialization/spec-iter.rs create mode 100644 src/test/ui/specialization/min_specialization/spec-reference.rs create mode 100644 src/test/ui/specialization/min_specialization/specialization_marker.rs create mode 100644 src/test/ui/specialization/min_specialization/specialization_marker.stderr create mode 100644 src/test/ui/specialization/min_specialization/specialization_trait.rs create mode 100644 src/test/ui/specialization/min_specialization/specialization_trait.stderr create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_marker.rs create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_static.rs create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_static.stderr create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_trait.rs create mode 100644 src/test/ui/specialization/min_specialization/specialize_on_trait.stderr diff --git a/src/librustc_typeck/constrained_generic_params.rs b/src/librustc_typeck/constrained_generic_params.rs index aff3768e35c..b16aa6ff3b2 100644 --- a/src/librustc_typeck/constrained_generic_params.rs +++ b/src/librustc_typeck/constrained_generic_params.rs @@ -79,10 +79,18 @@ impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { } fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> bool { - if let ty::ConstKind::Param(data) = c.val { - self.parameters.push(Parameter::from(data)); + match c.val { + ty::ConstKind::Unevaluated(..) if !self.include_nonconstraining => { + // Constant expressions are not injective + return c.ty.visit_with(self); + } + ty::ConstKind::Param(data) => { + self.parameters.push(Parameter::from(data)); + } + _ => {} } - false + + c.super_visit_with(self) } } diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 0a765a1f9c9..7ee25bbede2 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -9,6 +9,8 @@ //! fixed, but for the moment it's easier to do these checks early. use crate::constrained_generic_params as cgp; +use min_specialization::check_min_specialization; + use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -16,9 +18,11 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_span::Span; + use std::collections::hash_map::Entry::{Occupied, Vacant}; -use rustc_span::Span; +mod min_specialization; /// Checks that all the type/lifetime parameters on an impl also /// appear in the trait ref or self type (or are constrained by a @@ -60,7 +64,9 @@ pub fn impl_wf_check(tcx: TyCtxt<'_>) { } fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: DefId) { - tcx.hir().visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx }); + let min_specialization = tcx.features().min_specialization; + tcx.hir() + .visit_item_likes_in_module(module_def_id, &mut ImplWfCheck { tcx, min_specialization }); } pub fn provide(providers: &mut Providers<'_>) { @@ -69,6 +75,7 @@ pub fn provide(providers: &mut Providers<'_>) { struct ImplWfCheck<'tcx> { tcx: TyCtxt<'tcx>, + min_specialization: bool, } impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { @@ -77,6 +84,9 @@ impl ItemLikeVisitor<'tcx> for ImplWfCheck<'tcx> { let impl_def_id = self.tcx.hir().local_def_id(item.hir_id); enforce_impl_params_are_constrained(self.tcx, impl_def_id, items); enforce_impl_items_are_distinct(self.tcx, items); + if self.min_specialization { + check_min_specialization(self.tcx, impl_def_id, item.span); + } } } diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs new file mode 100644 index 00000000000..cd52dae5f9c --- /dev/null +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -0,0 +1,390 @@ +//! # Minimal Specialization +//! +//! This module contains the checks for sound specialization used when the +//! `min_specialization` feature is enabled. This requires that the impl is +//! *always applicable*. +//! +//! If `impl1` specializes `impl2` then `impl1` is always applicable if we know +//! that all the bounds of `impl2` are satisfied, and all of the bounds of +//! `impl1` are satisfied for some choice of lifetimes then we know that +//! `impl1` applies for any choice of lifetimes. +//! +//! ## Basic approach +//! +//! To enforce this requirement on specializations we take the following +//! approach: +//! +//! 1. Match up the substs for `impl2` so that the implemented trait and +//! self-type match those for `impl1`. +//! 2. Check for any direct use of `'static` in the substs of `impl2`. +//! 3. Check that all of the generic parameters of `impl1` occur at most once +//! in the *unconstrained* substs for `impl2`. A parameter is constrained if +//! its value is completely determined by an associated type projection +//! predicate. +//! 4. Check that all predicates on `impl1` also exist on `impl2` (after +//! matching substs). +//! +//! ## Example +//! +//! Suppose we have the following always applicable impl: +//! +//! ```rust +//! impl SpecExtend for std::vec::IntoIter { /* specialized impl */ } +//! impl> SpecExtend for I { /* default impl */ } +//! ``` +//! +//! We get that the subst for `impl2` are `[T, std::vec::IntoIter]`. `T` is +//! constrained to be `::Item`, so we check only +//! `std::vec::IntoIter` for repeated parameters, which it doesn't have. The +//! predicates of `impl1` are only `T: Sized`, which is also a predicate of +//! `impl2`. So this specialization is sound. +//! +//! ## Extensions +//! +//! Unfortunately not all specializations in the standard library are allowed +//! by this. So there are two extensions to these rules that allow specializing +//! on some traits: that is, using them as bounds on the specializing impl, +//! even when they don't occur in the base impl. +//! +//! ### rustc_specialization_trait +//! +//! If a trait is always applicable, then it's sound to specialize on it. We +//! check trait is always applicable in the same way as impls, except that step +//! 4 is now "all predicates on `impl1` are always applicable". We require that +//! `specialization` or `min_specialization` is enabled to implement these +//! traits. +//! +//! ### rustc_unsafe_specialization_marker +//! +//! There are also some specialization on traits with no methods, including the +//! stable `FusedIterator` trait. We allow marking marker traits with an +//! unstable attribute that means we ignore them in point 3 of the checks +//! above. This is unsound, in the sense that the specialized impl may be used +//! when it doesn't apply, but we allow it in the short term since it can't +//! cause use after frees with purely safe code in the same way as specializing +//! on traits with methods can. + +use crate::constrained_generic_params as cgp; + +use rustc::middle::region::ScopeTree; +use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; +use rustc::ty::trait_def::TraitSpecializationKind; +use rustc::ty::{self, InstantiatedPredicates, TyCtxt, TypeFoldable}; +use rustc_data_structures::fx::FxHashSet; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_infer::infer::outlives::env::OutlivesEnvironment; +use rustc_infer::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::traits::specialization_graph::Node; +use rustc_span::Span; +use rustc_trait_selection::traits::{self, translate_substs, wf}; + +pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: DefId, span: Span) { + if let Some(node) = parent_specialization_node(tcx, impl_def_id) { + tcx.infer_ctxt().enter(|infcx| { + check_always_applicable(&infcx, impl_def_id, node, span); + }); + } +} + +fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: DefId) -> Option { + let trait_ref = tcx.impl_trait_ref(impl1_def_id)?; + let trait_def = tcx.trait_def(trait_ref.def_id); + + let impl2_node = trait_def.ancestors(tcx, impl1_def_id).ok()?.nth(1)?; + + let always_applicable_trait = + matches!(trait_def.specialization_kind, TraitSpecializationKind::AlwaysApplicable); + if impl2_node.is_from_trait() && !always_applicable_trait { + // Implementing a normal trait isn't a specialization. + return None; + } + Some(impl2_node) +} + +/// Check that `impl1` is a sound specialization +fn check_always_applicable( + infcx: &InferCtxt<'_, '_>, + impl1_def_id: DefId, + impl2_node: Node, + span: Span, +) { + if let Some((impl1_substs, impl2_substs)) = + get_impl_substs(infcx, impl1_def_id, impl2_node, span) + { + let impl2_def_id = impl2_node.def_id(); + debug!( + "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)", + impl1_def_id, impl2_def_id, impl2_substs + ); + + let tcx = infcx.tcx; + + let parent_substs = if impl2_node.is_from_trait() { + impl2_substs.to_vec() + } else { + unconstrained_parent_impl_substs(tcx, impl2_def_id, impl2_substs) + }; + + check_static_lifetimes(tcx, &parent_substs, span); + check_duplicate_params(tcx, impl1_substs, &parent_substs, span); + + check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); + } +} + +/// Given a specializing impl `impl1`, and the base impl `impl2`, returns two +/// substitutions `(S1, S2)` that equate their trait references. The returned +/// types are expressed in terms of the generics of `impl1`. +/// +/// Example +/// +/// impl Foo for B { /* impl2 */ } +/// impl Foo> for C { /* impl1 */ } +/// +/// Would return `S1 = [C]` and `S2 = [Vec, C]`. +fn get_impl_substs<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + impl1_def_id: DefId, + impl2_node: Node, + span: Span, +) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> { + let tcx = infcx.tcx; + let param_env = tcx.param_env(impl1_def_id); + + let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id); + let impl2_substs = translate_substs(infcx, param_env, impl1_def_id, impl1_substs, impl2_node); + + // Conservatively use an empty `ParamEnv`. + let outlives_env = OutlivesEnvironment::new(ty::ParamEnv::empty()); + infcx.resolve_regions_and_report_errors( + impl1_def_id, + &ScopeTree::default(), + &outlives_env, + SuppressRegionErrors::default(), + ); + let impl2_substs = match infcx.fully_resolve(&impl2_substs) { + Ok(s) => s, + Err(_) => { + tcx.sess.struct_span_err(span, "could not resolve substs on overridden impl").emit(); + return None; + } + }; + Some((impl1_substs, impl2_substs)) +} + +/// Returns a list of all of the unconstrained subst of the given impl. +/// +/// For example given the impl: +/// +/// impl<'a, T, I> ... where &'a I: IntoIterator +/// +/// This would return the substs corresponding to `['a, I]`, because knowing +/// `'a` and `I` determines the value of `T`. +fn unconstrained_parent_impl_substs<'tcx>( + tcx: TyCtxt<'tcx>, + impl_def_id: DefId, + impl_substs: SubstsRef<'tcx>, +) -> Vec> { + let impl_generic_predicates = tcx.predicates_of(impl_def_id); + let mut unconstrained_parameters = FxHashSet::default(); + let mut constrained_params = FxHashSet::default(); + let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); + + // Unfortunately the functions in `constrained_generic_parameters` don't do + // what we want here. We want only a list of constrained parameters while + // the functions in `cgp` add the constrained parameters to a list of + // unconstrained parameters. + for (predicate, _) in impl_generic_predicates.predicates.iter() { + if let ty::Predicate::Projection(proj) = predicate { + let projection_ty = proj.skip_binder().projection_ty; + let projected_ty = proj.skip_binder().ty; + + let unbound_trait_ref = projection_ty.trait_ref(tcx); + if Some(unbound_trait_ref) == impl_trait_ref { + continue; + } + + unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true)); + + for param in cgp::parameters_for(&projected_ty, false) { + if !unconstrained_parameters.contains(¶m) { + constrained_params.insert(param.0); + } + } + + unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true)); + } + } + + impl_substs + .iter() + .enumerate() + .filter(|&(idx, _)| !constrained_params.contains(&(idx as u32))) + .map(|(_, arg)| *arg) + .collect() +} + +/// Check that parameters of the derived impl don't occur more than once in the +/// equated substs of the base impl. +/// +/// For example forbid the following: +/// +/// impl Tr for A { } +/// impl Tr for (B, B) { } +/// +/// Note that only consider the unconstrained parameters of the base impl: +/// +/// impl> Tr for I { } +/// impl Tr for Vec { } +/// +/// The substs for the parent impl here are `[T, Vec]`, which repeats `T`, +/// but `S` is constrained in the parent impl, so `parent_substs` is only +/// `[Vec]`. This means we allow this impl. +fn check_duplicate_params<'tcx>( + tcx: TyCtxt<'tcx>, + impl1_substs: SubstsRef<'tcx>, + parent_substs: &Vec>, + span: Span, +) { + let mut base_params = cgp::parameters_for(parent_substs, true); + base_params.sort_by_key(|param| param.0); + if let (_, [duplicate, ..]) = base_params.partition_dedup() { + let param = impl1_substs[duplicate.0 as usize]; + tcx.sess + .struct_span_err(span, &format!("specializing impl repeats parameter `{}`", param)) + .emit(); + } +} + +/// Check that `'static` lifetimes are not introduced by the specializing impl. +/// +/// For example forbid the following: +/// +/// impl Tr for A { } +/// impl Tr for &'static i32 { } +fn check_static_lifetimes<'tcx>( + tcx: TyCtxt<'tcx>, + parent_substs: &Vec>, + span: Span, +) { + if tcx.any_free_region_meets(parent_substs, |r| *r == ty::ReStatic) { + tcx.sess.struct_span_err(span, &format!("cannot specialize on `'static` lifetime")).emit(); + } +} + +/// Check whether predicates on the specializing impl (`impl1`) are allowed. +/// +/// Each predicate `P` must be: +/// +/// * global (not reference any parameters) +/// * `T: Tr` predicate where `Tr` is an always-applicable trait +/// * on the base `impl impl2` +/// * Currently this check is done using syntactic equality, which is +/// conservative but generally sufficient. +fn check_predicates<'tcx>( + tcx: TyCtxt<'tcx>, + impl1_def_id: DefId, + impl1_substs: SubstsRef<'tcx>, + impl2_node: Node, + impl2_substs: SubstsRef<'tcx>, + span: Span, +) { + let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); + let mut impl2_predicates = if impl2_node.is_from_trait() { + // Always applicable traits have to be always applicable without any + // assumptions. + InstantiatedPredicates::empty() + } else { + tcx.predicates_of(impl2_node.def_id()).instantiate(tcx, impl2_substs) + }; + debug!( + "check_always_applicable(\nimpl1_predicates={:?},\nimpl2_predicates={:?}\n)", + impl1_predicates, impl2_predicates, + ); + + // Since impls of always applicable traits don't get to assume anything, we + // can also assume their supertraits apply. + // + // For example, we allow: + // + // #[rustc_specialization_trait] + // trait AlwaysApplicable: Debug { } + // + // impl Tr for T { } + // impl Tr for T { } + // + // Specializing on `AlwaysApplicable` allows also specializing on `Debug` + // which is sound because we forbid impls like the following + // + // impl AlwaysApplicable for D { } + let always_applicable_traits: Vec<_> = impl1_predicates + .predicates + .iter() + .filter(|predicate| { + matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::AlwaysApplicable) + ) + }) + .copied() + .collect(); + impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits)); + + for predicate in impl1_predicates.predicates { + if !impl2_predicates.predicates.contains(&predicate) { + check_specialization_on(tcx, &predicate, span) + } + } +} + +fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) { + debug!("can_specialize_on(predicate = {:?})", predicate); + match predicate { + // Global predicates are either always true or always false, so we + // are fine to specialize on. + _ if predicate.is_global() => (), + // We allow specializing on explicitly marked traits with no associated + // items. + ty::Predicate::Trait(pred, hir::Constness::NotConst) => { + if !matches!( + trait_predicate_kind(tcx, predicate), + Some(TraitSpecializationKind::Marker) + ) { + tcx.sess + .struct_span_err( + span, + &format!( + "cannot specialize on trait `{}`", + tcx.def_path_str(pred.def_id()), + ), + ) + .emit() + } + } + _ => tcx + .sess + .struct_span_err(span, &format!("cannot specialize on `{:?}`", predicate)) + .emit(), + } +} + +fn trait_predicate_kind<'tcx>( + tcx: TyCtxt<'tcx>, + predicate: &ty::Predicate<'tcx>, +) -> Option { + match predicate { + ty::Predicate::Trait(pred, hir::Constness::NotConst) => { + Some(tcx.trait_def(pred.def_id()).specialization_kind) + } + ty::Predicate::Trait(_, hir::Constness::Const) + | ty::Predicate::RegionOutlives(_) + | ty::Predicate::TypeOutlives(_) + | ty::Predicate::Projection(_) + | ty::Predicate::WellFormed(_) + | ty::Predicate::Subtype(_) + | ty::Predicate::ObjectSafe(_) + | ty::Predicate::ClosureKind(..) + | ty::Predicate::ConstEvaluatable(..) => None, + } +} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4e7985dd988..bab354cff7c 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -64,6 +64,7 @@ This API is completely unstable and subject to change. #![feature(nll)] #![feature(try_blocks)] #![feature(never_type)] +#![feature(slice_partition_dedup)] #![recursion_limit = "256"] #[macro_use] diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs new file mode 100644 index 00000000000..03cab00b0fb --- /dev/null +++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.rs @@ -0,0 +1,32 @@ +// Test that associated types in trait objects are not considered to be +// constrained. + +#![feature(min_specialization)] + +trait Specializable { + fn f(); +} + +trait B { + type Y; +} + +trait C { + type Y; +} + +impl Specializable for A { + default fn f() {} +} + +impl<'a, T> Specializable for dyn B + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +impl<'a, T> Specializable for dyn C + 'a { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr new file mode 100644 index 00000000000..6345cee2c37 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/dyn-trait-assoc-types.stderr @@ -0,0 +1,20 @@ +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:22:1 + | +LL | / impl<'a, T> Specializable for dyn B + 'a { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: specializing impl repeats parameter `T` + --> $DIR/dyn-trait-assoc-types.rs:27:1 + | +LL | / impl<'a, T> Specializable for dyn C + 'a { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.rs b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs new file mode 100644 index 00000000000..f21f39f0669 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.rs @@ -0,0 +1,24 @@ +// Test that projection bounds can't be specialized on. + +#![feature(min_specialization)] + +trait X { + fn f(); +} +trait Id { + type This; +} +impl Id for T { + type This = T; +} + +impl X for T { + default fn f() {} +} + +impl> X for V { + //~^ ERROR cannot specialize on + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr new file mode 100644 index 00000000000..7cc4357a704 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeated_projection_type.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on `Binder(ProjectionPredicate(ProjectionTy { substs: [V], item_def_id: DefId(0:6 ~ repeated_projection_type[317d]::Id[0]::This[0]) }, (I,)))` + --> $DIR/repeated_projection_type.rs:19:1 + | +LL | / impl> X for V { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs new file mode 100644 index 00000000000..49bfacec0ae --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.rs @@ -0,0 +1,19 @@ +// Test that directly specializing on repeated lifetime parameters is not +// allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl<'a> X for (&'a u8, &'a u8) { + //~^ ERROR specializing impl repeats parameter `'a` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr new file mode 100644 index 00000000000..ce9309f7012 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_lifetimes.stderr @@ -0,0 +1,11 @@ +error: specializing impl repeats parameter `'a` + --> $DIR/repeating_lifetimes.rs:14:1 + | +LL | / impl<'a> X for (&'a u8, &'a u8) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/repeating_param.rs b/src/test/ui/specialization/min_specialization/repeating_param.rs new file mode 100644 index 00000000000..5a1c97fd321 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_param.rs @@ -0,0 +1,17 @@ +// Test that specializing on two type parameters being equal is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} +impl X for (T, T) { + //~^ ERROR specializing impl repeats parameter `T` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/repeating_param.stderr b/src/test/ui/specialization/min_specialization/repeating_param.stderr new file mode 100644 index 00000000000..8b4be1c4995 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/repeating_param.stderr @@ -0,0 +1,11 @@ +error: specializing impl repeats parameter `T` + --> $DIR/repeating_param.rs:12:1 + | +LL | / impl X for (T, T) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/spec-iter.rs b/src/test/ui/specialization/min_specialization/spec-iter.rs new file mode 100644 index 00000000000..e17e9dd5f13 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-iter.rs @@ -0,0 +1,20 @@ +// Check that we can specialize on a concrete iterator type. This requires us +// to consider which parameters in the parent impl are constrained. + +// check-pass + +#![feature(min_specialization)] + +trait SpecFromIter { + fn f(&self); +} + +impl<'a, T: 'a, I: Iterator> SpecFromIter for I { + default fn f(&self) {} +} + +impl<'a, T> SpecFromIter for std::slice::Iter<'a, T> { + fn f(&self) {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/spec-reference.rs b/src/test/ui/specialization/min_specialization/spec-reference.rs new file mode 100644 index 00000000000..377889e2cca --- /dev/null +++ b/src/test/ui/specialization/min_specialization/spec-reference.rs @@ -0,0 +1,19 @@ +// Check that lifetime parameters are allowed in specializing impls. + +// check-pass + +#![feature(min_specialization)] + +trait MySpecTrait { + fn f(); +} + +impl MySpecTrait for T { + default fn f() {} +} + +impl<'a, T: ?Sized> MySpecTrait for &'a T { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.rs b/src/test/ui/specialization/min_specialization/specialization_marker.rs new file mode 100644 index 00000000000..93462d02ea5 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_marker.rs @@ -0,0 +1,17 @@ +// Test that `rustc_unsafe_specialization_marker` is only allowed on marker traits. + +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker { + fn f(); + //~^ ERROR marker traits +} + +#[rustc_unsafe_specialization_marker] +trait SpecMarker2 { + type X; + //~^ ERROR marker traits +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_marker.stderr b/src/test/ui/specialization/min_specialization/specialization_marker.stderr new file mode 100644 index 00000000000..ffeced19821 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_marker.stderr @@ -0,0 +1,15 @@ +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:7:5 + | +LL | fn f(); + | ^^^^^^^ + +error[E0714]: marker traits cannot have associated items + --> $DIR/specialization_marker.rs:13:5 + | +LL | type X; + | ^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0714`. diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.rs b/src/test/ui/specialization/min_specialization/specialization_trait.rs new file mode 100644 index 00000000000..d597278d296 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_trait.rs @@ -0,0 +1,26 @@ +// Test that `rustc_specialization_trait` requires always applicable impls. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker { + fn f(); +} + +impl SpecMarker for &'static u8 { + //~^ ERROR cannot specialize + fn f() {} +} + +impl SpecMarker for (T, T) { + //~^ ERROR specializing impl + fn f() {} +} + +impl SpecMarker for [T] { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_trait.stderr new file mode 100644 index 00000000000..4357d2318fc --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_trait.stderr @@ -0,0 +1,29 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialization_trait.rs:11:1 + | +LL | / impl SpecMarker for &'static u8 { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: specializing impl repeats parameter `T` + --> $DIR/specialization_trait.rs:16:1 + | +LL | / impl SpecMarker for (T, T) { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: cannot specialize on trait `std::clone::Clone` + --> $DIR/specialization_trait.rs:21:1 + | +LL | / impl SpecMarker for [T] { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/specialization/min_specialization/specialize_on_marker.rs b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs new file mode 100644 index 00000000000..4219bd13b18 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_marker.rs @@ -0,0 +1,24 @@ +// Test that specializing on a `rustc_unsafe_specialization_marker` trait is +// allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_unsafe_specialization_marker] +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs new file mode 100644 index 00000000000..abbab5c23db --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_spec_trait.rs @@ -0,0 +1,27 @@ +// Test that specializing on a `rustc_specialization_trait` trait is allowed. + +// check-pass + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecTrait { + fn g(&self); +} + +trait X { + fn f(&self); +} + +impl X for T { + default fn f(&self) {} +} + +impl X for T { + fn f(&self) { + self.g(); + } +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.rs b/src/test/ui/specialization/min_specialization/specialize_on_static.rs new file mode 100644 index 00000000000..dd1b05401e6 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_static.rs @@ -0,0 +1,18 @@ +// Test that directly specializing on `'static` is not allowed. + +#![feature(min_specialization)] + +trait X { + fn f(); +} + +impl X for &'_ T { + default fn f() {} +} + +impl X for &'static u8 { + //~^ ERROR cannot specialize on `'static` lifetime + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_static.stderr b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr new file mode 100644 index 00000000000..d1809d6dfbb --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_static.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on `'static` lifetime + --> $DIR/specialize_on_static.rs:13:1 + | +LL | / impl X for &'static u8 { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.rs b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs new file mode 100644 index 00000000000..0588442c320 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.rs @@ -0,0 +1,20 @@ +// Test that specializing on a trait is not allowed in general. + +#![feature(min_specialization)] + +trait SpecMarker {} + +trait X { + fn f(); +} + +impl X for T { + default fn f() {} +} + +impl X for T { + //~^ ERROR cannot specialize on trait `SpecMarker` + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr new file mode 100644 index 00000000000..35445fd09b9 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialize_on_trait.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on trait `SpecMarker` + --> $DIR/specialize_on_trait.rs:15:1 + | +LL | / impl X for T { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + From 4377ac3e2f58f923062e6e945f06a9a93fcc70df Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 8 Feb 2020 20:54:33 +0000 Subject: [PATCH 1161/1250] Use min_specialization in libstd and libproc_macro --- src/libproc_macro/lib.rs | 3 ++- src/libstd/lib.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 59ce14c97c0..8f16e3c08ec 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -26,7 +26,8 @@ #![feature(in_band_lifetimes)] #![feature(optin_builtin_traits)] #![feature(rustc_attrs)] -#![feature(specialization)] +#![cfg_attr(bootstrap, feature(specialization))] +#![cfg_attr(not(bootstrap), feature(min_specialization))] #![recursion_limit = "256"] #[unstable(feature = "proc_macro_internals", issue = "27812")] diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 231908ddda0..703f60e5250 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -292,7 +292,8 @@ #![feature(shrink_to)] #![feature(slice_concat_ext)] #![feature(slice_internals)] -#![feature(specialization)] +#![cfg_attr(bootstrap, feature(specialization))] +#![cfg_attr(not(bootstrap), feature(min_specialization))] #![feature(staged_api)] #![feature(std_internals)] #![feature(stdsimd)] From 39ee66ab82fc38a13d046ac1caa1eb55edfa8901 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Mon, 9 Mar 2020 21:59:13 +0000 Subject: [PATCH 1162/1250] Consider well-formed predicates in min-specialization --- .../impl_wf_check/min_specialization.rs | 27 ++++++++++++++--- .../implcit-well-formed-bounds.rs | 30 +++++++++++++++++++ .../specialization_super_trait.rs | 18 +++++++++++ .../specialization_super_trait.stderr | 11 +++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs create mode 100644 src/test/ui/specialization/min_specialization/specialization_super_trait.rs create mode 100644 src/test/ui/specialization/min_specialization/specialization_super_trait.stderr diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index cd52dae5f9c..e96a8c454b8 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -21,8 +21,9 @@ //! in the *unconstrained* substs for `impl2`. A parameter is constrained if //! its value is completely determined by an associated type projection //! predicate. -//! 4. Check that all predicates on `impl1` also exist on `impl2` (after -//! matching substs). +//! 4. Check that all predicates on `impl1` either exist on `impl2` (after +//! matching substs), or are well-formed predicates for the trait's type +//! arguments. //! //! ## Example //! @@ -129,7 +130,7 @@ fn check_always_applicable( check_static_lifetimes(tcx, &parent_substs, span); check_duplicate_params(tcx, impl1_substs, &parent_substs, span); - check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); + check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span); } } @@ -282,14 +283,17 @@ fn check_static_lifetimes<'tcx>( /// * on the base `impl impl2` /// * Currently this check is done using syntactic equality, which is /// conservative but generally sufficient. +/// * a well-formed predicate of a type argument of the trait being implemented, +/// including the `Self`-type. fn check_predicates<'tcx>( - tcx: TyCtxt<'tcx>, + infcx: &InferCtxt<'_, 'tcx>, impl1_def_id: DefId, impl1_substs: SubstsRef<'tcx>, impl2_node: Node, impl2_substs: SubstsRef<'tcx>, span: Span, ) { + let tcx = infcx.tcx; let impl1_predicates = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any @@ -329,6 +333,21 @@ fn check_predicates<'tcx>( }) .copied() .collect(); + + // Include the well-formed predicates of the type parameters of the impl. + for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() { + if let Some(obligations) = wf::obligations( + infcx, + tcx.param_env(impl1_def_id), + tcx.hir().as_local_hir_id(impl1_def_id).unwrap(), + ty, + span, + ) { + impl2_predicates + .predicates + .extend(obligations.into_iter().map(|obligation| obligation.predicate)) + } + } impl2_predicates.predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits)); for predicate in impl1_predicates.predicates { diff --git a/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs new file mode 100644 index 00000000000..98d7f919435 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/implcit-well-formed-bounds.rs @@ -0,0 +1,30 @@ +// Test that specializing on the well-formed predicates of the trait and +// self-type of an impl is allowed. + +// check-pass + +#![feature(min_specialization)] + +struct OrdOnly(T); + +trait SpecTrait { + fn f(); +} + +impl SpecTrait for T { + default fn f() {} +} + +impl SpecTrait<()> for OrdOnly { + fn f() {} +} + +impl SpecTrait> for () { + fn f() {} +} + +impl SpecTrait<(OrdOnly, OrdOnly)> for &[OrdOnly] { + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.rs b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs new file mode 100644 index 00000000000..145f376edf9 --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.rs @@ -0,0 +1,18 @@ +// Test that supertraits can't be assumed in impls of +// `rustc_specialization_trait`, as such impls would +// allow specializing on the supertrait. + +#![feature(min_specialization)] +#![feature(rustc_attrs)] + +#[rustc_specialization_trait] +trait SpecMarker: Default { + fn f(); +} + +impl SpecMarker for T { + //~^ ERROR cannot specialize + fn f() {} +} + +fn main() {} diff --git a/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr new file mode 100644 index 00000000000..154c839c6da --- /dev/null +++ b/src/test/ui/specialization/min_specialization/specialization_super_trait.stderr @@ -0,0 +1,11 @@ +error: cannot specialize on trait `std::default::Default` + --> $DIR/specialization_super_trait.rs:13:1 + | +LL | / impl SpecMarker for T { +LL | | +LL | | fn f() {} +LL | | } + | |_^ + +error: aborting due to previous error + From 621c42c16351467fe089230d27889295203d2117 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 3 Mar 2020 23:41:32 +0000 Subject: [PATCH 1163/1250] Render full attributes in rustdoc --- src/librustdoc/html/render.rs | 24 ++---------------------- src/test/rustdoc/attributes.rs | 4 ++++ 2 files changed, 6 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index ceae42cc598..e791ae41927 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3126,25 +3126,6 @@ fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum) { render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All) } -fn render_attribute(attr: &ast::MetaItem) -> Option { - let path = pprust::path_to_string(&attr.path); - - if attr.is_word() { - Some(path) - } else if let Some(v) = attr.value_str() { - Some(format!("{} = {:?}", path, v)) - } else if let Some(values) = attr.meta_item_list() { - let display: Vec<_> = values - .iter() - .filter_map(|attr| attr.meta_item().and_then(|mi| render_attribute(mi))) - .collect(); - - if !display.is_empty() { Some(format!("{}({})", path, display.join(", "))) } else { None } - } else { - None - } -} - const ATTRIBUTE_WHITELIST: &[Symbol] = &[ sym::export_name, sym::lang, @@ -3170,9 +3151,8 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { if !ATTRIBUTE_WHITELIST.contains(&attr.name_or_empty()) { continue; } - if let Some(s) = render_attribute(&attr.meta().unwrap()) { - attrs.push_str(&format!("#[{}]\n", s)); - } + + attrs.push_str(&pprust::attribute_to_string(&attr)); } if !attrs.is_empty() { write!( diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index 6ecdad3ec00..d5772e183bc 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -15,3 +15,7 @@ pub extern "C" fn g() {} pub enum Foo { Bar, } + +// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align (8))]' +#[repr(C, align(8))] +pub struct Repr; From c599ec4460f17c43f5df1d4df269f3811ece4bd7 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 3 Mar 2020 23:47:13 +0000 Subject: [PATCH 1164/1250] Add FIXME note --- src/librustdoc/html/render.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e791ae41927..b3d70475bf3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -44,7 +44,6 @@ use std::sync::Arc; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability; -use rustc_ast::ast; use rustc_ast_pretty::pprust; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -3152,6 +3151,7 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { continue; } + // FIXME: this currently renders too many spaces as in: `#[repr(C, align (8))]`. attrs.push_str(&pprust::attribute_to_string(&attr)); } if !attrs.is_empty() { From 81099c27ddc856238d7b1b15c20d487130ef3057 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 10 Mar 2020 10:10:10 +0100 Subject: [PATCH 1165/1250] VariantSizeDifferences: bail on SizeOverflow --- src/librustc_lint/types.rs | 6 ++---- .../ui/lint/issue-69485-var-size-diffs-too-large.rs | 10 ++++++++++ .../lint/issue-69485-var-size-diffs-too-large.stderr | 8 ++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs create mode 100644 src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 86d93612e99..2896682ea82 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -998,10 +998,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences { let ty = cx.tcx.erase_regions(&t); let layout = match cx.layout_of(ty) { Ok(layout) => layout, - Err(ty::layout::LayoutError::Unknown(_)) => return, - Err(err @ ty::layout::LayoutError::SizeOverflow(_)) => { - bug!("failed to get layout for `{}`: {}", t, err); - } + Err(ty::layout::LayoutError::Unknown(_)) + | Err(ty::layout::LayoutError::SizeOverflow(_)) => return, }; let (variants, tag) = match layout.variants { layout::Variants::Multiple { diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs new file mode 100644 index 00000000000..49d489d9168 --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.rs @@ -0,0 +1,10 @@ +// build-fail +// only-x86_64 + +fn main() { + Bug::V([0; !0]); //~ ERROR is too big for the current +} + +enum Bug { + V([u8; !0]), +} diff --git a/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr new file mode 100644 index 00000000000..d31ce9cfe0c --- /dev/null +++ b/src/test/ui/lint/issue-69485-var-size-diffs-too-large.stderr @@ -0,0 +1,8 @@ +error: the type `[u8; 18446744073709551615]` is too big for the current architecture + --> $DIR/issue-69485-var-size-diffs-too-large.rs:5:12 + | +LL | Bug::V([0; !0]); + | ^^^^^^^ + +error: aborting due to previous error + From f53f9a88f16dc3d1b94ed2e7f0f201e1456d8cfc Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 15 Mar 2020 19:43:25 +0100 Subject: [PATCH 1166/1250] Bump the bootstrap compiler --- src/bootstrap/builder.rs | 10 ++---- src/bootstrap/channel.rs | 2 +- src/liballoc/boxed.rs | 24 ------------- src/libcore/cell.rs | 2 +- src/libcore/lib.rs | 2 +- src/libcore/ops/generator.rs | 31 ++--------------- src/librustc_data_structures/box_region.rs | 39 ---------------------- src/libstd/future.rs | 5 +-- src/stage0.txt | 2 +- 9 files changed, 9 insertions(+), 108 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index e4b57cddfb8..602e4511ea5 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -725,7 +725,7 @@ impl<'a> Builder<'a> { self.clear_if_dirty(&my_out, &rustdoc); } - cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd).arg("-Zconfig-profile"); + cargo.env("CARGO_TARGET_DIR", &out_dir).arg(cmd); let profile_var = |name: &str| { let profile = if self.config.rust_optimize { "RELEASE" } else { "DEV" }; @@ -847,13 +847,7 @@ impl<'a> Builder<'a> { rustflags.arg("-Zforce-unstable-if-unmarked"); } - // cfg(bootstrap): the flag was renamed from `-Zexternal-macro-backtrace` - // to `-Zmacro-backtrace`, keep only the latter after beta promotion. - if stage == 0 { - rustflags.arg("-Zexternal-macro-backtrace"); - } else { - rustflags.arg("-Zmacro-backtrace"); - } + rustflags.arg("-Zmacro-backtrace"); let want_rustdoc = self.doc_tests != DocTests::No; diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 504cba45570..be2b0f36d14 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.43.0"; +pub const CFG_RELEASE_NUM: &str = "1.44.0"; pub struct GitInfo { inner: Option, diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 9a7d0d9aeba..36641284a76 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -1105,29 +1105,6 @@ impl AsMut for Box { #[stable(feature = "pin", since = "1.33.0")] impl Unpin for Box {} -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Box { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume(Pin::new(&mut *self)) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Pin> { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume((*self).as_mut()) - } -} - -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R> Generator for Box { type Yield = G::Yield; @@ -1138,7 +1115,6 @@ impl + Unpin, R> Generator for Box { } } -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl, R> Generator for Pin> { type Yield = G::Yield; diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9ebb3176418..a84f0caf0a0 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -1538,7 +1538,7 @@ impl fmt::Display for RefMut<'_, T> { #[lang = "unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] -#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303. +#[repr(no_niche)] // rust-lang/rust#68303. pub struct UnsafeCell { value: T, } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index a1dde1d51ef..5a731766054 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -140,7 +140,7 @@ #![feature(associated_type_bounds)] #![feature(const_type_id)] #![feature(const_caller_location)] -#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303 +#![feature(no_niche)] // rust-lang/rust#68303 #[prelude_import] #[allow(unused)] diff --git a/src/libcore/ops/generator.rs b/src/libcore/ops/generator.rs index 4e43561996c..4f23620b92b 100644 --- a/src/libcore/ops/generator.rs +++ b/src/libcore/ops/generator.rs @@ -67,7 +67,7 @@ pub enum GeneratorState { #[lang = "generator"] #[unstable(feature = "generator_trait", issue = "43122")] #[fundamental] -pub trait Generator<#[cfg(not(bootstrap))] R = ()> { +pub trait Generator { /// The type of value this generator yields. /// /// This associated type corresponds to the `yield` expression and the @@ -110,35 +110,9 @@ pub trait Generator<#[cfg(not(bootstrap))] R = ()> { /// been returned previously. While generator literals in the language are /// guaranteed to panic on resuming after `Complete`, this is not guaranteed /// for all implementations of the `Generator` trait. - fn resume( - self: Pin<&mut Self>, - #[cfg(not(bootstrap))] arg: R, - ) -> GeneratorState; + fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState; } -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for Pin<&mut G> { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume((*self).as_mut()) - } -} - -#[cfg(bootstrap)] -#[unstable(feature = "generator_trait", issue = "43122")] -impl Generator for &mut G { - type Yield = G::Yield; - type Return = G::Return; - - fn resume(mut self: Pin<&mut Self>) -> GeneratorState { - G::resume(Pin::new(&mut *self)) - } -} - -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl, R> Generator for Pin<&mut G> { type Yield = G::Yield; @@ -149,7 +123,6 @@ impl, R> Generator for Pin<&mut G> { } } -#[cfg(not(bootstrap))] #[unstable(feature = "generator_trait", issue = "43122")] impl + Unpin, R> Generator for &mut G { type Yield = G::Yield; diff --git a/src/librustc_data_structures/box_region.rs b/src/librustc_data_structures/box_region.rs index dbc54291f40..edeb4f83c7d 100644 --- a/src/librustc_data_structures/box_region.rs +++ b/src/librustc_data_structures/box_region.rs @@ -25,22 +25,6 @@ pub struct PinnedGenerator { } impl PinnedGenerator { - #[cfg(bootstrap)] - pub fn new, Return = R> + 'static>( - generator: T, - ) -> (I, Self) { - let mut result = PinnedGenerator { generator: Box::pin(generator) }; - - // Run it to the first yield to set it up - let init = match Pin::new(&mut result.generator).resume() { - GeneratorState::Yielded(YieldType::Initial(y)) => y, - _ => panic!(), - }; - - (init, result) - } - - #[cfg(not(bootstrap))] pub fn new, Return = R> + 'static>( generator: T, ) -> (I, Self) { @@ -55,19 +39,6 @@ impl PinnedGenerator { (init, result) } - #[cfg(bootstrap)] - pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) { - BOX_REGION_ARG.with(|i| { - i.set(Action::Access(AccessAction(closure))); - }); - - // Call the generator, which in turn will call the closure in BOX_REGION_ARG - if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume() { - panic!() - } - } - - #[cfg(not(bootstrap))] pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) { BOX_REGION_ARG.with(|i| { i.set(Action::Access(AccessAction(closure))); @@ -79,16 +50,6 @@ impl PinnedGenerator { } } - #[cfg(bootstrap)] - pub fn complete(&mut self) -> R { - // Tell the generator we want it to complete, consuming it and yielding a result - BOX_REGION_ARG.with(|i| i.set(Action::Complete)); - - let result = Pin::new(&mut self.generator).resume(); - if let GeneratorState::Complete(r) = result { r } else { panic!() } - } - - #[cfg(not(bootstrap))] pub fn complete(&mut self) -> R { // Tell the generator we want it to complete, consuming it and yielding a result BOX_REGION_ARG.with(|i| i.set(Action::Complete)); diff --git a/src/libstd/future.rs b/src/libstd/future.rs index 7b1beb1ecda..c1ca6771326 100644 --- a/src/libstd/future.rs +++ b/src/libstd/future.rs @@ -41,10 +41,7 @@ impl> Future for GenFuture { // Safe because we're !Unpin + !Drop mapping to a ?Unpin value let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) }; let _guard = unsafe { set_task_context(cx) }; - match gen.resume( - #[cfg(not(bootstrap))] - (), - ) { + match gen.resume(()) { GeneratorState::Yielded(()) => Poll::Pending, GeneratorState::Complete(x) => Poll::Ready(x), } diff --git a/src/stage0.txt b/src/stage0.txt index 55416b6729a..4d9a91e38b3 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: 2020-02-29 +date: 2020-03-12 rustc: beta cargo: beta From 51ea260ee7ee896701ef7296d7f63e7ef455b383 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 9 Feb 2020 02:39:14 +0200 Subject: [PATCH 1167/1250] rustc: don't resolve Instances which would produce malformed shims. --- src/librustc/ty/instance.rs | 15 ++++++++ src/librustc_mir/shim.rs | 33 ++++++++++------- src/librustc_ty/instance.rs | 70 ++++++++++++++++++++++++++----------- 3 files changed, 86 insertions(+), 32 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 445df76cd32..07acb7abfdb 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -39,6 +39,11 @@ pub enum InstanceDef<'tcx> { /// `::call_*` /// `DefId` is `FnTrait::call_*`. + /// + /// NB: the (`fn` pointer) type must be monomorphic for MIR shims to work. + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `fn(_, _) -> _` instead of requiring a fully monomorphic + // `fn(Foo, Bar) -> Baz` etc. FnPtrShim(DefId, Ty<'tcx>), /// `::fn`, "direct calls" of which are implicitly @@ -57,9 +62,19 @@ pub enum InstanceDef<'tcx> { /// The `DefId` is for `core::ptr::drop_in_place`. /// The `Option>` is either `Some(T)`, or `None` for empty drop /// glue. + /// + /// NB: the type must be monomorphic for MIR shims to work. + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. DropGlue(DefId, Option>), ///`::clone` shim. + /// + /// NB: the type must be monomorphic for MIR shims to work. + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. CloneShim(DefId, Ty<'tcx>), } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 1f7db2861a2..c1d969a4b51 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -2,13 +2,13 @@ use rustc::mir::*; use rustc::ty::layout::VariantIdx; use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, Subst}; -use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_index::vec::{Idx, IndexVec}; -use rustc_span::{sym, Span}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use std::fmt; @@ -39,6 +39,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ), ty::InstanceDef::FnPtrShim(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + let trait_ = tcx.trait_of_item(def_id).unwrap(); let adjustment = match tcx.fn_trait_kind_from_lang_item(trait_) { Some(ty::ClosureKind::FnOnce) => Adjustment::Identity, @@ -81,17 +86,21 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx None, ) } - ty::InstanceDef::DropGlue(def_id, ty) => build_drop_shim(tcx, def_id, ty), + ty::InstanceDef::DropGlue(def_id, ty) => { + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_drop_shim(tcx, def_id, ty) + } ty::InstanceDef::CloneShim(def_id, ty) => { - let name = tcx.item_name(def_id); - if name == sym::clone { - build_clone_shim(tcx, def_id, ty) - } else if name == sym::clone_from { - debug!("make_shim({:?}: using default trait implementation", instance); - return tcx.optimized_mir(def_id); - } else { - bug!("builtin clone shim {:?} not supported", instance) - } + // FIXME(eddyb) support generating shims for a "shallow type", + // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic + // `Foo` or `[String]` etc. + assert!(!ty.needs_subst()); + + build_clone_shim(tcx, def_id, ty) } ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 10cc2c0e303..a5abe7b6413 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -1,6 +1,7 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt, TypeFoldable}; use rustc_hir::def_id::DefId; +use rustc_span::sym; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; @@ -31,21 +32,26 @@ pub fn resolve_instance<'tcx>( debug!(" => intrinsic"); ty::InstanceDef::Intrinsic(def_id) } - _ => { - if Some(def_id) == tcx.lang_items().drop_in_place_fn() { - let ty = substs.type_at(0); - if ty.needs_drop(tcx, param_env.with_reveal_all()) { - debug!(" => nontrivial drop glue"); - ty::InstanceDef::DropGlue(def_id, Some(ty)) - } else { - debug!(" => trivial drop glue"); - ty::InstanceDef::DropGlue(def_id, None) + ty::FnDef(def_id, substs) if Some(def_id) == tcx.lang_items().drop_in_place_fn() => { + let ty = substs.type_at(0); + + if ty.needs_drop(tcx, param_env) { + // `DropGlue` requires a monomorphic aka concrete type. + if ty.needs_subst() { + return None; } + + debug!(" => nontrivial drop glue"); + ty::InstanceDef::DropGlue(def_id, Some(ty)) } else { - debug!(" => free item"); - ty::InstanceDef::Item(def_id) + debug!(" => trivial drop glue"); + ty::InstanceDef::DropGlue(def_id, None) } } + _ => { + debug!(" => free item"); + ty::InstanceDef::Item(def_id) + } }; Some(Instance { def, substs }) }; @@ -113,20 +119,44 @@ fn resolve_associated_item<'tcx>( trait_closure_kind, )) } - traits::VtableFnPointer(ref data) => Some(Instance { - def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), - substs: rcvr_substs, - }), + traits::VtableFnPointer(ref data) => { + // `FnPtrShim` requires a monomorphic aka concrete type. + if data.fn_ty.needs_subst() { + return None; + } + + Some(Instance { + def: ty::InstanceDef::FnPtrShim(trait_item.def_id, data.fn_ty), + substs: rcvr_substs, + }) + } traits::VtableObject(ref data) => { let index = traits::get_vtable_index_of_object_method(tcx, data, def_id); Some(Instance { def: ty::InstanceDef::Virtual(def_id, index), substs: rcvr_substs }) } traits::VtableBuiltin(..) => { - if tcx.lang_items().clone_trait().is_some() { - Some(Instance { - def: ty::InstanceDef::CloneShim(def_id, trait_ref.self_ty()), - substs: rcvr_substs, - }) + if Some(trait_ref.def_id) == tcx.lang_items().clone_trait() { + // FIXME(eddyb) use lang items for methods instead of names. + let name = tcx.item_name(def_id); + if name == sym::clone { + let self_ty = trait_ref.self_ty(); + + // `CloneShim` requires a monomorphic aka concrete type. + if self_ty.needs_subst() { + return None; + } + + Some(Instance { + def: ty::InstanceDef::CloneShim(def_id, self_ty), + substs: rcvr_substs, + }) + } else { + assert_eq!(name, sym::clone_from); + + // Use the default `fn clone_from` from `trait Clone`. + let substs = tcx.erase_regions(&rcvr_substs); + Some(ty::Instance::new(def_id, substs)) + } } else { None } From bc8ff3fe8e8cebc9e4855aaf44c19c887f8f4be4 Mon Sep 17 00:00:00 2001 From: Ana-Maria Mihalache Date: Wed, 11 Mar 2020 15:20:31 +0000 Subject: [PATCH 1168/1250] rustc: tweak comments on InstanceDef. --- src/librustc/ty/instance.rs | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/src/librustc/ty/instance.rs b/src/librustc/ty/instance.rs index 07acb7abfdb..c9ad8707a74 100644 --- a/src/librustc/ty/instance.rs +++ b/src/librustc/ty/instance.rs @@ -40,10 +40,9 @@ pub enum InstanceDef<'tcx> { /// `::call_*` /// `DefId` is `FnTrait::call_*`. /// - /// NB: the (`fn` pointer) type must be monomorphic for MIR shims to work. - // FIXME(eddyb) support generating shims for a "shallow type", - // e.g. `fn(_, _) -> _` instead of requiring a fully monomorphic - // `fn(Foo, Bar) -> Baz` etc. + /// NB: the (`fn` pointer) type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. FnPtrShim(DefId, Ty<'tcx>), /// `::fn`, "direct calls" of which are implicitly @@ -63,18 +62,16 @@ pub enum InstanceDef<'tcx> { /// The `Option>` is either `Some(T)`, or `None` for empty drop /// glue. /// - /// NB: the type must be monomorphic for MIR shims to work. - // FIXME(eddyb) support generating shims for a "shallow type", - // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic - // `Foo` or `[String]` etc. + /// NB: the type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. DropGlue(DefId, Option>), ///`::clone` shim. /// - /// NB: the type must be monomorphic for MIR shims to work. - // FIXME(eddyb) support generating shims for a "shallow type", - // e.g. `Foo<_>` or `[_]` instead of requiring a fully monomorphic - // `Foo` or `[String]` etc. + /// NB: the type must currently be monomorphic to avoid double substitution + /// problems with the MIR shim bodies. `Instance::resolve` enforces this. + // FIXME(#69925) support polymorphic MIR shim bodies properly instead. CloneShim(DefId, Ty<'tcx>), } From 65bf4831d22d3c0eee639a6536bb0bcd191ec915 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 00:52:24 +0300 Subject: [PATCH 1169/1250] ast/hir: `MacroDef::legacy` -> `MacroDef::macro_rules` --- src/librustc_ast/ast.rs | 2 +- src/librustc_ast/mut_visit.rs | 2 +- src/librustc_ast_lowering/item.rs | 6 +++--- src/librustc_ast_passes/feature_gate.rs | 2 +- src/librustc_ast_pretty/pprust.rs | 2 +- src/librustc_expand/mbe/macro_rules.rs | 10 +++++----- src/librustc_parse/parser/item.rs | 4 ++-- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 6 +++--- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 08ce0cc2c56..68960ba9fe9 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -1450,7 +1450,7 @@ impl MacDelimiter { pub struct MacroDef { pub body: P, /// `true` if macro was defined with `macro_rules`. - pub legacy: bool, + pub macro_rules: bool, } #[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)] diff --git a/src/librustc_ast/mut_visit.rs b/src/librustc_ast/mut_visit.rs index a1a5b9debc5..aa2968b3cbe 100644 --- a/src/librustc_ast/mut_visit.rs +++ b/src/librustc_ast/mut_visit.rs @@ -591,7 +591,7 @@ pub fn noop_visit_mac(mac: &mut MacCall, vis: &mut T) { } pub fn noop_visit_macro_def(macro_def: &mut MacroDef, vis: &mut T) { - let MacroDef { body, legacy: _ } = macro_def; + let MacroDef { body, macro_rules: _ } = macro_def; visit_mac_args(body, vis); } diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 2c60fe9c077..458cb721d48 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -220,8 +220,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let mut vis = self.lower_visibility(&i.vis, None); let attrs = self.lower_attrs(&i.attrs); - if let ItemKind::MacroDef(MacroDef { ref body, legacy }) = i.kind { - if !legacy || attr::contains_name(&i.attrs, sym::macro_export) { + if let ItemKind::MacroDef(MacroDef { ref body, macro_rules }) = i.kind { + if !macro_rules || attr::contains_name(&i.attrs, sym::macro_export) { let hir_id = self.lower_node_id(i.id); let body = P(self.lower_mac_args(body)); self.exported_macros.push(hir::MacroDef { @@ -230,7 +230,7 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs, hir_id, span: i.span, - ast: MacroDef { body, legacy }, + ast: MacroDef { body, macro_rules }, }); } else { self.non_exported_macro_attrs.extend(attrs.iter().cloned()); diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs index 66be2b49ada..2a9847c900e 100644 --- a/src/librustc_ast_passes/feature_gate.rs +++ b/src/librustc_ast_passes/feature_gate.rs @@ -366,7 +366,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { gate_feature_post!(&self, trait_alias, i.span, "trait aliases are experimental"); } - ast::ItemKind::MacroDef(ast::MacroDef { legacy: false, .. }) => { + ast::ItemKind::MacroDef(ast::MacroDef { macro_rules: false, .. }) => { let msg = "`macro` is experimental"; gate_feature_post!(&self, decl_macro, i.span, msg); } diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index a81b28d7c39..b2e6ab7c5e7 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -1238,7 +1238,7 @@ impl<'a> State<'a> { } } ast::ItemKind::MacroDef(ref macro_def) => { - let (kw, has_bang) = if macro_def.legacy { + let (kw, has_bang) = if macro_def.macro_rules { ("macro_rules", true) } else { self.print_visibility(&item.vis); diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 3040a9aefbb..3cad3ff55d9 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -350,8 +350,8 @@ pub fn compile_declarative_macro( let tt_spec = ast::Ident::new(sym::tt, def.span); // Parse the macro_rules! invocation - let (is_legacy, body) = match &def.kind { - ast::ItemKind::MacroDef(macro_def) => (macro_def.legacy, macro_def.body.inner_tokens()), + let (macro_rules, body) = match &def.kind { + ast::ItemKind::MacroDef(def) => (def.macro_rules, def.body.inner_tokens()), _ => unreachable!(), }; @@ -370,7 +370,7 @@ pub fn compile_declarative_macro( mbe::TokenTree::MetaVarDecl(def.span, rhs_nm, tt_spec), ], separator: Some(Token::new( - if is_legacy { token::Semi } else { token::Comma }, + if macro_rules { token::Semi } else { token::Comma }, def.span, )), kleene: mbe::KleeneToken::new(mbe::KleeneOp::OneOrMore, def.span), @@ -382,7 +382,7 @@ pub fn compile_declarative_macro( DelimSpan::dummy(), Lrc::new(mbe::SequenceRepetition { tts: vec![mbe::TokenTree::token( - if is_legacy { token::Semi } else { token::Comma }, + if macro_rules { token::Semi } else { token::Comma }, def.span, )], separator: None, @@ -456,7 +456,7 @@ pub fn compile_declarative_macro( // that is not lint-checked and trigger the "failed to process buffered lint here" bug. valid &= macro_check::check_meta_variables(sess, ast::CRATE_NODE_ID, def.span, &lhses, &rhses); - let (transparency, transparency_error) = attr::find_transparency(&def.attrs, is_legacy); + let (transparency, transparency_error) = attr::find_transparency(&def.attrs, macro_rules); match transparency_error { Some(TransparencyError::UnknownTransparency(value, span)) => { diag.span_err(span, &format!("unknown macro transparency: `{}`", value)) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index fe5495fbf8a..cb4a98a6b4f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1260,7 +1260,7 @@ impl<'a> Parser<'a> { }; self.sess.gated_spans.gate(sym::decl_macro, lo.to(self.prev_token.span)); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: false }))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: false }))) } /// Is this unambiguously the start of a `macro_rules! foo` item defnition? @@ -1280,7 +1280,7 @@ impl<'a> Parser<'a> { self.eat_semi_for_macro_if_needed(&body); self.complain_if_pub_macro(vis, true); - Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, legacy: true }))) + Ok((ident, ItemKind::MacroDef(ast::MacroDef { body, macro_rules: true }))) } /// Item macro invocations or `macro_rules!` definitions need inherited visibility. diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index d61ba60da31..5c363168784 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -920,7 +920,7 @@ impl Visitor<'tcx> for EmbargoVisitor<'tcx> { } fn visit_macro_def(&mut self, md: &'tcx hir::MacroDef<'tcx>) { - if attr::find_transparency(&md.attrs, md.ast.legacy).0 != Transparency::Opaque { + if attr::find_transparency(&md.attrs, md.ast.macro_rules).0 != Transparency::Opaque { self.update(md.hir_id, Some(AccessLevel::Public)); return; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 0c6edd3e47d..e85741c114e 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -1098,10 +1098,10 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let (ext, ident, span, is_legacy) = match &item.kind { + let (ext, ident, span, macro_rules) = match &item.kind { ItemKind::MacroDef(def) => { let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition())); - (ext, item.ident, item.span, def.legacy) + (ext, item.ident, item.span, def.macro_rules) } ItemKind::Fn(..) => match Self::proc_macro_stub(item) { Some((macro_kind, ident, span)) => { @@ -1118,7 +1118,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.macro_map.insert(def_id, ext); self.r.local_macro_def_scopes.insert(item.id, parent_scope.module); - if is_legacy { + if macro_rules { let ident = ident.modern(); self.r.macro_names.insert(ident); let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export); From 3fbb2549ce66e83583bb3bad83bbd15436b10d35 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 01:06:36 +0300 Subject: [PATCH 1170/1250] resolve: `Legacy(Scope,Binding)` -> `MacroRules(Scope,Binding)` --- src/librustc_resolve/build_reduced_graph.rs | 34 ++++++++-------- src/librustc_resolve/diagnostics.rs | 12 +++--- src/librustc_resolve/lib.rs | 44 +++++++++++++-------- src/librustc_resolve/macros.rs | 30 +++++++------- 4 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index e85741c114e..324669963f6 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -7,7 +7,7 @@ use crate::def_collector::collect_definitions; use crate::imports::{Import, ImportKind}; -use crate::macros::{LegacyBinding, LegacyScope}; +use crate::macros::{MacroRulesBinding, MacroRulesScope}; use crate::Namespace::{self, MacroNS, TypeNS, ValueNS}; use crate::{CrateLint, Determinacy, PathResult, ResolutionError, VisResolutionError}; use crate::{ @@ -165,11 +165,11 @@ impl<'a> Resolver<'a> { &mut self, fragment: &AstFragment, parent_scope: ParentScope<'a>, - ) -> LegacyScope<'a> { + ) -> MacroRulesScope<'a> { collect_definitions(&mut self.definitions, fragment, parent_scope.expansion); let mut visitor = BuildReducedGraphVisitor { r: self, parent_scope }; fragment.visit_with(&mut visitor); - visitor.parent_scope.legacy + visitor.parent_scope.macro_rules } crate fn build_reduced_graph_external(&mut self, module: Module<'a>) { @@ -1060,7 +1060,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { false } - fn visit_invoc(&mut self, id: NodeId) -> LegacyScope<'a> { + fn visit_invoc(&mut self, id: NodeId) -> MacroRulesScope<'a> { let invoc_id = id.placeholder_to_expn_id(); self.parent_scope.module.unexpanded_invocations.borrow_mut().insert(invoc_id); @@ -1068,7 +1068,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { 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"); - LegacyScope::Invocation(invoc_id) + MacroRulesScope::Invocation(invoc_id) } fn proc_macro_stub(item: &ast::Item) -> Option<(MacroKind, Ident, Span)> { @@ -1095,7 +1095,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn define_macro(&mut self, item: &ast::Item) -> LegacyScope<'a> { + fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; let (ext, ident, span, macro_rules) = match &item.kind { @@ -1108,7 +1108,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.proc_macro_stubs.insert(item.id); (self.r.dummy_ext(macro_kind), ident, span, false) } - None => return parent_scope.legacy, + None => return parent_scope.macro_rules, }, _ => unreachable!(), }; @@ -1137,8 +1137,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, item.id, span); } - LegacyScope::Binding(self.r.arenas.alloc_legacy_binding(LegacyBinding { - parent_legacy_scope: parent_scope.legacy, + MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { + parent_macro_rules_scope: parent_scope.macro_rules, binding, ident, })) @@ -1149,7 +1149,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.insert_unused_macro(ident, item.id, span); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.parent_scope.legacy + self.parent_scope.macro_rules } } } @@ -1174,29 +1174,29 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_item(&mut self, item: &'b Item) { let macro_use = match item.kind { ItemKind::MacroDef(..) => { - self.parent_scope.legacy = self.define_macro(item); + self.parent_scope.macro_rules = self.define_macro(item); return; } ItemKind::MacCall(..) => { - self.parent_scope.legacy = self.visit_invoc(item.id); + self.parent_scope.macro_rules = self.visit_invoc(item.id); return; } ItemKind::Mod(..) => self.contains_macro_use(&item.attrs), _ => false, }; let orig_current_module = self.parent_scope.module; - let orig_current_legacy_scope = self.parent_scope.legacy; + let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_item(item); visit::walk_item(self, item); self.parent_scope.module = orig_current_module; if !macro_use { - self.parent_scope.legacy = orig_current_legacy_scope; + self.parent_scope.macro_rules = orig_current_macro_rules_scope; } } fn visit_stmt(&mut self, stmt: &'b ast::Stmt) { if let ast::StmtKind::MacCall(..) = stmt.kind { - self.parent_scope.legacy = self.visit_invoc(stmt.id); + self.parent_scope.macro_rules = self.visit_invoc(stmt.id); } else { visit::walk_stmt(self, stmt); } @@ -1214,11 +1214,11 @@ impl<'a, 'b> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b> { fn visit_block(&mut self, block: &'b Block) { let orig_current_module = self.parent_scope.module; - let orig_current_legacy_scope = self.parent_scope.legacy; + let orig_current_macro_rules_scope = self.parent_scope.macro_rules; self.build_reduced_graph_for_block(block); visit::walk_block(self, block); self.parent_scope.module = orig_current_module; - self.parent_scope.legacy = orig_current_legacy_scope; + self.parent_scope.macro_rules = orig_current_macro_rules_scope; } fn visit_assoc_item(&mut self, item: &'b AssocItem, ctxt: AssocCtxt) { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 47a05ec90d4..d50f88b59ed 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -21,7 +21,9 @@ use rustc_span::{BytePos, MultiSpan, Span}; use crate::imports::{Import, ImportKind, ImportResolver}; use crate::path_names_to_string; use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind}; -use crate::{BindingError, CrateLint, HasGenericParams, LegacyScope, Module, ModuleOrUniformRoot}; +use crate::{ + BindingError, CrateLint, HasGenericParams, MacroRulesScope, Module, ModuleOrUniformRoot, +}; use crate::{NameBinding, NameBindingKind, PrivacyError, VisResolutionError}; use crate::{ParentScope, PathResult, ResolutionError, Resolver, Scope, ScopeSet, Segment}; @@ -498,12 +500,12 @@ impl<'a> Resolver<'a> { } } } - Scope::MacroRules(legacy_scope) => { - if let LegacyScope::Binding(legacy_binding) = legacy_scope { - let res = legacy_binding.binding.res(); + Scope::MacroRules(macro_rules_scope) => { + if let MacroRulesScope::Binding(macro_rules_binding) = macro_rules_scope { + let res = macro_rules_binding.binding.res(); if filter_fn(res) { suggestions - .push(TypoSuggestion::from_res(legacy_binding.ident.name, res)) + .push(TypoSuggestion::from_res(macro_rules_binding.ident.name, res)) } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 37a800a0b7b..0d02b8ea074 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -58,7 +58,7 @@ use diagnostics::{extend_span_to_previous_binding, find_span_of_binding_until_ne use diagnostics::{ImportSuggestion, Suggestion}; use imports::{Import, ImportKind, ImportResolver, NameResolution}; use late::{HasGenericParams, PathSource, Rib, RibKind::*}; -use macros::{LegacyBinding, LegacyScope}; +use macros::{MacroRulesBinding, MacroRulesScope}; type Res = def::Res; @@ -94,7 +94,7 @@ impl Determinacy { enum Scope<'a> { DeriveHelpers(ExpnId), DeriveHelpersCompat, - MacroRules(LegacyScope<'a>), + MacroRules(MacroRulesScope<'a>), CrateRoot, Module(Module<'a>), RegisteredAttrs, @@ -127,7 +127,7 @@ enum ScopeSet { pub struct ParentScope<'a> { module: Module<'a>, expansion: ExpnId, - legacy: LegacyScope<'a>, + macro_rules: MacroRulesScope<'a>, derives: &'a [ast::Path], } @@ -135,7 +135,12 @@ 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: &[] } + ParentScope { + module, + expansion: ExpnId::root(), + macro_rules: MacroRulesScope::Empty, + derives: &[], + } } } @@ -930,9 +935,9 @@ pub struct Resolver<'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>, - /// Legacy scopes *produced* by expanding the macro invocations, + /// `macro_rules` scopes *produced* by expanding the macro invocations, /// include all the `macro_rules` items and other invocations generated by them. - output_legacy_scopes: FxHashMap>, + output_macro_rules_scopes: FxHashMap>, /// Helper attributes that are in scope for the given expansion. helper_attrs: FxHashMap>, @@ -965,7 +970,7 @@ pub struct ResolverArenas<'a> { name_bindings: arena::TypedArena>, imports: arena::TypedArena>, name_resolutions: arena::TypedArena>>, - legacy_bindings: arena::TypedArena>, + macro_rules_bindings: arena::TypedArena>, ast_paths: arena::TypedArena, } @@ -989,8 +994,11 @@ impl<'a> ResolverArenas<'a> { fn alloc_name_resolution(&'a self) -> &'a RefCell> { self.name_resolutions.alloc(Default::default()) } - fn alloc_legacy_binding(&'a self, binding: LegacyBinding<'a>) -> &'a LegacyBinding<'a> { - self.legacy_bindings.alloc(binding) + fn alloc_macro_rules_binding( + &'a self, + binding: MacroRulesBinding<'a>, + ) -> &'a MacroRulesBinding<'a> { + self.macro_rules_bindings.alloc(binding) } fn alloc_ast_paths(&'a self, paths: &[ast::Path]) -> &'a [ast::Path] { self.ast_paths.alloc_from_iter(paths.iter().cloned()) @@ -1210,7 +1218,7 @@ impl<'a> Resolver<'a> { dummy_ext_derive: Lrc::new(SyntaxExtension::dummy_derive(session.edition())), non_macro_attrs: [non_macro_attr(false), non_macro_attr(true)], invocation_parent_scopes, - output_legacy_scopes: Default::default(), + output_macro_rules_scopes: Default::default(), helper_attrs: Default::default(), macro_defs, local_macro_def_scopes: FxHashMap::default(), @@ -1530,16 +1538,18 @@ impl<'a> Resolver<'a> { } } Scope::DeriveHelpers(..) => Scope::DeriveHelpersCompat, - Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.legacy), - Scope::MacroRules(legacy_scope) => match legacy_scope { - LegacyScope::Binding(binding) => Scope::MacroRules(binding.parent_legacy_scope), - LegacyScope::Invocation(invoc_id) => Scope::MacroRules( - self.output_legacy_scopes + Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules), + Scope::MacroRules(macro_rules_scope) => match macro_rules_scope { + MacroRulesScope::Binding(binding) => { + Scope::MacroRules(binding.parent_macro_rules_scope) + } + MacroRulesScope::Invocation(invoc_id) => Scope::MacroRules( + self.output_macro_rules_scopes .get(&invoc_id) .cloned() - .unwrap_or(self.invocation_parent_scopes[&invoc_id].legacy), + .unwrap_or(self.invocation_parent_scopes[&invoc_id].macro_rules), ), - LegacyScope::Empty => Scope::Module(module), + MacroRulesScope::Empty => Scope::Module(module), }, Scope::CrateRoot => match ns { TypeNS => { diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e11aec90669..d8ef148bacf 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -33,26 +33,26 @@ use std::{mem, ptr}; type Res = def::Res; /// Binding produced by a `macro_rules` item. -/// Not modularized, can shadow previous legacy bindings, etc. +/// Not modularized, can shadow previous `macro_rules` bindings, etc. #[derive(Debug)] -pub struct LegacyBinding<'a> { +pub struct MacroRulesBinding<'a> { crate binding: &'a NameBinding<'a>, - /// Legacy scope into which the `macro_rules` item was planted. - crate parent_legacy_scope: LegacyScope<'a>, + /// `macro_rules` scope into which the `macro_rules` item was planted. + crate parent_macro_rules_scope: MacroRulesScope<'a>, crate ident: Ident, } /// The scope introduced by a `macro_rules!` macro. /// This starts at the macro's definition and ends at the end of the macro's parent /// module (named or unnamed), or even further if it escapes with `#[macro_use]`. -/// Some macro invocations need to introduce legacy scopes too because they +/// Some macro invocations need to introduce `macro_rules` scopes too because they /// can potentially expand into macro definitions. #[derive(Copy, Clone, Debug)] -pub enum LegacyScope<'a> { +pub enum MacroRulesScope<'a> { /// Empty "root" scope at the crate start containing no names. Empty, /// The scope introduced by a `macro_rules!` macro definition. - Binding(&'a LegacyBinding<'a>), + Binding(&'a MacroRulesBinding<'a>), /// The scope introduced by a macro invocation that can potentially /// create a `macro_rules!` macro definition. Invocation(ExpnId), @@ -159,8 +159,8 @@ impl<'a> base::Resolver for Resolver<'a> { // 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, parent_scope); - self.output_legacy_scopes.insert(expansion, output_legacy_scope); + let output_macro_rules_scope = self.build_reduced_graph(fragment, parent_scope); + self.output_macro_rules_scopes.insert(expansion, output_macro_rules_scope); parent_scope.module.unexpanded_invocations.borrow_mut().remove(&expansion); } @@ -608,12 +608,14 @@ impl<'a> Resolver<'a> { } result } - Scope::MacroRules(legacy_scope) => match legacy_scope { - LegacyScope::Binding(legacy_binding) if ident == legacy_binding.ident => { - Ok((legacy_binding.binding, Flags::MACRO_RULES)) + Scope::MacroRules(macro_rules_scope) => match macro_rules_scope { + MacroRulesScope::Binding(macro_rules_binding) + if ident == macro_rules_binding.ident => + { + Ok((macro_rules_binding.binding, Flags::MACRO_RULES)) } - LegacyScope::Invocation(invoc_id) - if !this.output_legacy_scopes.contains_key(&invoc_id) => + MacroRulesScope::Invocation(invoc_id) + if !this.output_macro_rules_scopes.contains_key(&invoc_id) => { Err(Determinacy::Undetermined) } From 8c9a38f679a0dd70c65e094f3063318616eb8387 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 01:23:24 +0300 Subject: [PATCH 1171/1250] Other `legacy` -> `macro_rules` --- src/librustc_attr/builtin.rs | 4 +-- src/librustc_expand/mbe/macro_check.rs | 12 ++++----- src/librustc_parse/parser/item.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 10 ++++---- src/librustc_resolve/lib.rs | 28 +++++++++++---------- src/librustc_resolve/macros.rs | 10 +++++--- 6 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index 08eae24da9b..99083cca6cb 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -1024,7 +1024,7 @@ pub enum TransparencyError { pub fn find_transparency( attrs: &[Attribute], - is_legacy: bool, + macro_rules: bool, ) -> (Transparency, Option) { let mut transparency = None; let mut error = None; @@ -1049,7 +1049,7 @@ pub fn find_transparency( } } } - let fallback = if is_legacy { Transparency::SemiTransparent } else { Transparency::Opaque }; + let fallback = if macro_rules { Transparency::SemiTransparent } else { Transparency::Opaque }; (transparency.map_or(fallback, |t| t.0), error) } diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs index 6eb834beac6..8c6bfbec902 100644 --- a/src/librustc_expand/mbe/macro_check.rs +++ b/src/librustc_expand/mbe/macro_check.rs @@ -419,10 +419,10 @@ fn check_nested_occurrences( | (NestedMacroState::MacroName, &TokenTree::Delimited(_, ref del)) if del.delim == DelimToken::Brace => { - let legacy = state == NestedMacroState::MacroRulesNotName; + let macro_rules = state == NestedMacroState::MacroRulesNotName; state = NestedMacroState::Empty; let rest = - check_nested_macro(sess, node_id, legacy, &del.tts, &nested_macros, valid); + check_nested_macro(sess, node_id, macro_rules, &del.tts, &nested_macros, valid); // If we did not check the whole macro definition, then check the rest as if outside // the macro definition. check_nested_occurrences( @@ -493,21 +493,21 @@ fn check_nested_occurrences( /// Arguments: /// - `sess` is used to emit diagnostics and lints /// - `node_id` is used to emit lints -/// - `legacy` specifies whether the macro is legacy +/// - `macro_rules` specifies whether the macro is `macro_rules` /// - `tts` is checked as a list of (LHS) => {RHS} /// - `macros` is the stack of outer macros /// - `valid` is set in case of errors fn check_nested_macro( sess: &ParseSess, node_id: NodeId, - legacy: bool, + macro_rules: bool, tts: &[TokenTree], macros: &Stack<'_, MacroState<'_>>, valid: &mut bool, ) -> usize { let n = tts.len(); let mut i = 0; - let separator = if legacy { TokenKind::Semi } else { TokenKind::Comma }; + let separator = if macro_rules { TokenKind::Semi } else { TokenKind::Comma }; loop { // We expect 3 token trees: `(LHS) => {RHS}`. The separator is checked after. if i + 2 >= n @@ -522,7 +522,7 @@ fn check_nested_macro( let mut binders = Binders::default(); check_binders(sess, node_id, lhs, macros, &mut binders, &Stack::Empty, valid); check_occurrences(sess, node_id, rhs, macros, &binders, &Stack::Empty, valid); - // Since the last semicolon is optional for legacy macros and decl_macro are not terminated, + // Since the last semicolon is optional for `macro_rules` macros and decl_macro are not terminated, // we increment our checked position by how many token trees we already checked (the 3 // above) before checking for the separator. i += 3; diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index cb4a98a6b4f..e927bcd07e2 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -1270,7 +1270,7 @@ impl<'a> Parser<'a> { && self.look_ahead(2, |t| t.is_ident()) } - /// Parses a legacy `macro_rules! foo { ... }` declarative macro. + /// Parses a `macro_rules! foo { ... }` declarative macro. fn parse_item_macro_rules(&mut self, vis: &Visibility) -> PResult<'a, ItemInfo> { self.expect_keyword(kw::MacroRules)?; // `macro_rules` self.expect(&token::Not)?; // `!` diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index 324669963f6..f7bbba28c07 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -624,7 +624,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.get_module(DefId { krate: crate_id, index: CRATE_DEF_INDEX }) }; - let used = self.process_legacy_macro_imports(item, module); + let used = self.process_macro_use_imports(item, module); let binding = (module, ty::Visibility::Public, sp, expansion).to_name_binding(self.r.arenas); let import = self.r.arenas.alloc_import(Import { @@ -913,7 +913,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } - fn legacy_import_macro( + fn add_macro_use_binding( &mut self, name: ast::Name, binding: &'a NameBinding<'a>, @@ -929,7 +929,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } /// Returns `true` if we should consider the underlying `extern crate` to be used. - fn process_legacy_macro_imports(&mut self, item: &Item, module: Module<'a>) -> bool { + fn process_macro_use_imports(&mut self, item: &Item, module: Module<'a>) -> bool { let mut import_all = None; let mut single_imports = Vec::new(); for attr in &item.attrs { @@ -1004,7 +1004,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { module.for_each_child(self, |this, ident, ns, binding| { if ns == MacroNS { let imported_binding = this.r.import(binding, import); - this.legacy_import_macro(ident.name, imported_binding, span, allow_shadowing); + this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing); } }); } else { @@ -1021,7 +1021,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let import = macro_use_import(self, ident.span); self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); - self.legacy_import_macro( + self.add_macro_use_binding( ident.name, imported_binding, ident.span, diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 0d02b8ea074..c4338710478 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -618,7 +618,7 @@ enum AmbiguityKind { Import, BuiltinAttr, DeriveHelper, - LegacyVsModern, + MacroRulesVsModularized, GlobVsOuter, GlobVsGlob, GlobVsExpanded, @@ -631,7 +631,9 @@ impl AmbiguityKind { AmbiguityKind::Import => "name vs any other name during import resolution", AmbiguityKind::BuiltinAttr => "built-in attribute vs any other name", AmbiguityKind::DeriveHelper => "derive helper attribute vs any other name", - AmbiguityKind::LegacyVsModern => "`macro_rules` vs non-`macro_rules` from other module", + AmbiguityKind::MacroRulesVsModularized => { + "`macro_rules` vs non-`macro_rules` from other module" + } AmbiguityKind::GlobVsOuter => { "glob import vs any other name from outer scope during import/macro resolution" } @@ -1473,7 +1475,7 @@ impl<'a> Resolver<'a> { // derives (you need to resolve the derive first to add helpers into scope), but they // should be available before the derive is expanded for compatibility. // It's mess in general, so we are being conservative for now. - // 1-3. `macro_rules` (open, not controlled), loop through legacy scopes. Have higher + // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher // priority than prelude macros, but create ambiguities with macros in modules. // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents // (open, not controlled). Have higher priority than prelude macros, but create @@ -1639,7 +1641,7 @@ impl<'a> Resolver<'a> { for i in (0..ribs.len()).rev() { 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). + // (modern hygiene) or local variables (`macro_rules` hygiene). let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident }; if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. @@ -1898,7 +1900,7 @@ impl<'a> Resolver<'a> { break; } } - // Then find the last legacy mark from the end if it exists. + // Then find the last semi-transparent mark from the end if it exists. for (mark, transparency) in iter { if transparency == Transparency::SemiTransparent { result = Some(mark); @@ -2423,21 +2425,21 @@ impl<'a> Resolver<'a> { } } - fn disambiguate_legacy_vs_modern( + fn disambiguate_macro_rules_vs_modularized( &self, - legacy: &'a NameBinding<'a>, - modern: &'a NameBinding<'a>, + macro_rules: &'a NameBinding<'a>, + modularized: &'a NameBinding<'a>, ) -> bool { // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( - self.binding_parent_modules.get(&PtrKey(legacy)), - self.binding_parent_modules.get(&PtrKey(modern)), + self.binding_parent_modules.get(&PtrKey(macro_rules)), + self.binding_parent_modules.get(&PtrKey(modularized)), ) { - (Some(legacy), Some(modern)) => { - legacy.normal_ancestor_id == modern.normal_ancestor_id - && modern.is_ancestor_of(legacy) + (Some(macro_rules), Some(modularized)) => { + macro_rules.normal_ancestor_id == modularized.normal_ancestor_id + && modularized.is_ancestor_of(macro_rules) } _ => false, } diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index d8ef148bacf..f4dfa037dae 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -761,16 +761,18 @@ impl<'a> Resolver<'a> { Some(AmbiguityKind::DeriveHelper) } else if innermost_flags.contains(Flags::MACRO_RULES) && flags.contains(Flags::MODULE) - && !this - .disambiguate_legacy_vs_modern(innermost_binding, binding) + && !this.disambiguate_macro_rules_vs_modularized( + innermost_binding, + binding, + ) || flags.contains(Flags::MACRO_RULES) && innermost_flags.contains(Flags::MODULE) - && !this.disambiguate_legacy_vs_modern( + && !this.disambiguate_macro_rules_vs_modularized( binding, innermost_binding, ) { - Some(AmbiguityKind::LegacyVsModern) + Some(AmbiguityKind::MacroRulesVsModularized) } else if innermost_binding.is_glob_import() { Some(AmbiguityKind::GlobVsOuter) } else if innermost_binding From db638bd123b7b73be691f7b4daebb61469587a27 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 14 Mar 2020 01:36:46 +0300 Subject: [PATCH 1172/1250] hygiene: `modern` -> `normalize_to_macros_2_0` `modern_and_legacy` -> `normalize_to_macro_rules` --- src/librustc/ty/mod.rs | 18 ++++---- src/librustc_ast_lowering/item.rs | 2 +- src/librustc_ast_lowering/lib.rs | 13 ++++-- src/librustc_hir/hir.rs | 10 ++-- src/librustc_mir/monomorphize/collector.rs | 4 +- src/librustc_resolve/build_reduced_graph.rs | 15 +++--- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/imports.rs | 3 +- src/librustc_resolve/late.rs | 10 ++-- src/librustc_resolve/late/lifetimes.rs | 27 ++++++----- src/librustc_resolve/lib.rs | 46 +++++++++---------- src/librustc_resolve/macros.rs | 8 +++- src/librustc_span/hygiene.rs | 32 ++++++------- src/librustc_span/lib.rs | 12 ++--- src/librustc_span/symbol.rs | 12 ++--- src/librustc_typeck/astconv.rs | 13 ++++-- src/librustc_typeck/check/expr.rs | 6 ++- src/librustc_typeck/check/pat.rs | 4 +- .../coherence/inherent_impls_overlap.rs | 8 ++-- src/librustc_typeck/collect.rs | 4 +- src/librustc_typeck/impl_wf_check.rs | 2 +- 21 files changed, 141 insertions(+), 110 deletions(-) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index c2697570dda..e1df0e6cde3 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3083,7 +3083,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn hygienic_eq(self, use_name: Ident, def_name: Ident, def_parent_def_id: DefId) -> bool { // We could use `Ident::eq` here, but we deliberately don't. The name // comparison fails frequently, and we want to avoid the expensive - // `modern()` calls required for the span comparison whenever possible. + // `normalize_to_macros_2_0()` calls required for the span comparison whenever possible. use_name.name == def_name.name && use_name .span @@ -3099,7 +3099,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn adjust_ident(self, mut ident: Ident, scope: DefId) -> Ident { - ident.span.modernize_and_adjust(self.expansion_that_defined(scope)); + ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope)); ident } @@ -3109,12 +3109,14 @@ impl<'tcx> TyCtxt<'tcx> { scope: DefId, block: hir::HirId, ) -> (Ident, DefId) { - let scope = match ident.span.modernize_and_adjust(self.expansion_that_defined(scope)) { - Some(actual_expansion) => { - self.hir().definitions().parent_module_of_macro_def(actual_expansion) - } - None => self.parent_module(block), - }; + let scope = + match ident.span.normalize_to_macros_2_0_and_adjust(self.expansion_that_defined(scope)) + { + Some(actual_expansion) => { + self.hir().definitions().parent_module_of_macro_def(actual_expansion) + } + None => self.parent_module(block), + }; (ident, scope) } diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 458cb721d48..38089167f5c 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -115,7 +115,7 @@ impl<'hir> LoweringContext<'_, 'hir> { _ => &[], }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { - hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()), + hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()), _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 24e547af237..97711d8c8ff 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -153,7 +153,7 @@ struct LoweringContext<'a, 'hir: 'a> { /// against this list to see if it is already in-scope, or if a definition /// needs to be created for it. /// - /// We always store a `modern()` version of the param-name in this + /// We always store a `normalize_to_macros_2_0()` version of the param-name in this /// vector. in_scope_lifetimes: Vec, @@ -805,14 +805,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { return; } - if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) { + if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.normalize_to_macros_2_0())) { return; } let hir_name = ParamName::Plain(ident); - if self.lifetimes_to_define.iter().any(|(_, lt_name)| lt_name.modern() == hir_name.modern()) - { + if self.lifetimes_to_define.iter().any(|(_, lt_name)| { + lt_name.normalize_to_macros_2_0() == hir_name.normalize_to_macros_2_0() + }) { return; } @@ -840,7 +841,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) -> T { let old_len = self.in_scope_lifetimes.len(); let lt_def_names = params.iter().filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())), + GenericParamKind::Lifetime { .. } => { + Some(ParamName::Plain(param.ident.normalize_to_macros_2_0())) + } _ => None, }); self.in_scope_lifetimes.extend(lt_def_names); diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index fc6a9e39645..797387cdced 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -79,9 +79,9 @@ impl ParamName { } } - pub fn modern(&self) -> ParamName { + pub fn normalize_to_macros_2_0(&self) -> ParamName { match *self { - ParamName::Plain(ident) => ParamName::Plain(ident.modern()), + ParamName::Plain(ident) => ParamName::Plain(ident.normalize_to_macros_2_0()), param_name => param_name, } } @@ -151,9 +151,11 @@ impl LifetimeName { self == &LifetimeName::Static } - pub fn modern(&self) -> LifetimeName { + pub fn normalize_to_macros_2_0(&self) -> LifetimeName { match *self { - LifetimeName::Param(param_name) => LifetimeName::Param(param_name.modern()), + LifetimeName::Param(param_name) => { + LifetimeName::Param(param_name.normalize_to_macros_2_0()) + } lifetime_name => lifetime_name, } } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 862a7ef1e73..28fafb126f4 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -1088,9 +1088,9 @@ fn create_mono_items_for_default_impls<'tcx>( let param_env = ty::ParamEnv::reveal_all(); let trait_ref = tcx.normalize_erasing_regions(param_env, trait_ref); let overridden_methods: FxHashSet<_> = - items.iter().map(|iiref| iiref.ident.modern()).collect(); + items.iter().map(|iiref| iiref.ident.normalize_to_macros_2_0()).collect(); for method in tcx.provided_trait_methods(trait_ref.def_id) { - if overridden_methods.contains(&method.ident.modern()) { + if overridden_methods.contains(&method.ident.normalize_to_macros_2_0()) { continue; } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f7bbba28c07..ce3b1233a74 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -645,7 +645,8 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.potentially_unused_imports.push(import); let imported_binding = self.r.import(binding, import); if ptr::eq(parent, self.r.graph_root) { - if let Some(entry) = self.r.extern_prelude.get(&ident.modern()) { + if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) + { if expansion != ExpnId::root() && orig_name.is_some() && entry.extern_crate_item.is_none() @@ -656,10 +657,12 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { } } let entry = - self.r.extern_prelude.entry(ident.modern()).or_insert(ExternPreludeEntry { - extern_crate_item: None, - introduced_by_item: true, - }); + self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert( + ExternPreludeEntry { + extern_crate_item: None, + introduced_by_item: true, + }, + ); entry.extern_crate_item = Some(imported_binding); if orig_name.is_some() { entry.introduced_by_item = true; @@ -1119,7 +1122,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { self.r.local_macro_def_scopes.insert(item.id, parent_scope.module); if macro_rules { - let ident = ident.modern(); + let ident = ident.normalize_to_macros_2_0(); self.r.macro_names.insert(ident); let is_macro_export = attr::contains_name(&item.attrs, sym::macro_export); let vis = if is_macro_export { diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index d50f88b59ed..63fbc800ff7 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -758,7 +758,7 @@ impl<'a> Resolver<'a> { let msg = format!("unsafe traits like `{}` should be implemented explicitly", ident); err.span_note(ident.span, &msg); } - if self.macro_names.contains(&ident.modern()) { + if self.macro_names.contains(&ident.normalize_to_macros_2_0()) { err.help("have you added the `#[macro_use]` on the module/import?"); } } diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 485b86636a0..681c0392118 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -416,7 +416,8 @@ impl<'a> Resolver<'a> { None => return Err((Undetermined, Weak::Yes)), }; let tmp_parent_scope; - let (mut adjusted_parent_scope, mut ident) = (parent_scope, ident.modern()); + let (mut adjusted_parent_scope, mut ident) = + (parent_scope, ident.normalize_to_macros_2_0()); match ident.span.glob_adjust(module.expansion, glob_import.span) { Some(Some(def)) => { tmp_parent_scope = diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 7efd9e90ceb..867aa8c6321 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -935,7 +935,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { _ => unreachable!(), }; - let ident = param.ident.modern(); + let ident = param.ident.normalize_to_macros_2_0(); debug!("with_generic_param_rib: {}", param.id); if seen_bindings.contains_key(&ident) { @@ -1464,7 +1464,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // Add the binding to the local ribs, if it doesn't already exist in the bindings map. // (We must not add it if it's in the bindings map because that breaks the assumptions // later passes make about or-patterns.) - let ident = ident.modern_and_legacy(); + let ident = ident.normalize_to_macro_rules(); let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident)); // Already bound in a product pattern? e.g. `(a, a)` which is not allowed. @@ -1873,7 +1873,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { self.diagnostic_metadata.unused_labels.insert(id, label.ident.span); } self.with_label_rib(NormalRibKind, |this| { - let ident = label.ident.modern_and_legacy(); + let ident = label.ident.normalize_to_macro_rules(); this.label_ribs.last_mut().unwrap().bindings.insert(ident, id); f(this); }); @@ -1949,7 +1949,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => { let node_id = self.search_label(label.ident, |rib, ident| { - rib.bindings.get(&ident.modern_and_legacy()).cloned() + rib.bindings.get(&ident.normalize_to_macro_rules()).cloned() }); match node_id { None => { @@ -2115,7 +2115,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { } } - ident.span = ident.span.modern(); + ident.span = ident.span.normalize_to_macros_2_0(); let mut search_module = self.parent_scope.module; loop { self.get_traits_in_module_containing_item(ident, ns, search_module, &mut found_traits); diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5c0748797f0..7c5b35381f0 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -62,7 +62,7 @@ impl RegionExt for Region { let def_id = hir_map.local_def_id(param.hir_id); let origin = LifetimeDefOrigin::from_param(param); debug!("Region::early: index={} def_id={:?}", i, def_id); - (param.name.modern(), Region::EarlyBound(i, def_id, origin)) + (param.name.normalize_to_macros_2_0(), Region::EarlyBound(i, def_id, origin)) } fn late(hir_map: &Map<'_>, param: &GenericParam<'_>) -> (ParamName, Region) { @@ -73,7 +73,7 @@ impl RegionExt for Region { "Region::late: param={:?} depth={:?} def_id={:?} origin={:?}", param, depth, def_id, origin, ); - (param.name.modern(), Region::LateBound(depth, def_id, origin)) + (param.name.normalize_to_macros_2_0(), Region::LateBound(depth, def_id, origin)) } fn late_anon(index: &Cell) -> Region { @@ -1174,7 +1174,9 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { Scope::Binder { ref lifetimes, s, .. } => { // FIXME (#24278): non-hygienic comparison - if let Some(def) = lifetimes.get(&hir::ParamName::Plain(label.modern())) { + if let Some(def) = + lifetimes.get(&hir::ParamName::Plain(label.normalize_to_macros_2_0())) + { let hir_id = tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( @@ -1253,7 +1255,7 @@ fn object_lifetime_defaults_for_item( fn add_bounds(set: &mut Set1, bounds: &[hir::GenericBound<'_>]) { for bound in bounds { if let hir::GenericBound::Outlives(ref lifetime) = *bound { - set.insert(lifetime.name.modern()); + set.insert(lifetime.name.normalize_to_macros_2_0()); } } } @@ -1791,7 +1793,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { Scope::Binder { ref lifetimes, s, .. } => { match lifetime_ref.name { LifetimeName::Param(param_name) => { - if let Some(&def) = lifetimes.get(¶m_name.modern()) { + if let Some(&def) = lifetimes.get(¶m_name.normalize_to_macros_2_0()) + { break Some(def.shifted(late_depth)); } } @@ -2544,7 +2547,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { let lifetimes: Vec<_> = params .iter() .filter_map(|param| match param.kind { - GenericParamKind::Lifetime { .. } => Some((param, param.name.modern())), + GenericParamKind::Lifetime { .. } => { + Some((param, param.name.normalize_to_macros_2_0())) + } _ => None, }) .collect(); @@ -2661,7 +2666,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } Scope::Binder { ref lifetimes, s, .. } => { - if let Some(&def) = lifetimes.get(¶m.name.modern()) { + if let Some(&def) = lifetimes.get(¶m.name.normalize_to_macros_2_0()) { let hir_id = self.tcx.hir().as_local_hir_id(def.id().unwrap()).unwrap(); signal_shadowing_problem( @@ -2799,7 +2804,7 @@ fn insert_late_bound_lifetimes( // `'a: 'b` means both `'a` and `'b` are referenced appears_in_where_clause .regions - .insert(hir::LifetimeName::Param(param.name.modern())); + .insert(hir::LifetimeName::Param(param.name.normalize_to_macros_2_0())); } } } @@ -2821,7 +2826,7 @@ fn insert_late_bound_lifetimes( hir::GenericParamKind::Type { .. } | hir::GenericParamKind::Const { .. } => continue, } - let lt_name = hir::LifetimeName::Param(param.name.modern()); + let lt_name = hir::LifetimeName::Param(param.name.normalize_to_macros_2_0()); // appears in the where clauses? early-bound. if appears_in_where_clause.regions.contains(<_name) { continue; @@ -2885,7 +2890,7 @@ fn insert_late_bound_lifetimes( } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - self.regions.insert(lifetime_ref.name.modern()); + self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0()); } } @@ -2902,7 +2907,7 @@ fn insert_late_bound_lifetimes( } fn visit_lifetime(&mut self, lifetime_ref: &'v hir::Lifetime) { - self.regions.insert(lifetime_ref.name.modern()); + self.regions.insert(lifetime_ref.name.normalize_to_macros_2_0()); } } } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index c4338710478..05d0f206450 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -424,7 +424,7 @@ impl ModuleKind { /// program) if all but one of them come from glob imports. #[derive(Copy, Clone, PartialEq, Eq, Hash)] struct BindingKey { - /// The identifier for the binding, aways the `modern` version of the + /// The identifier for the binding, aways the `normalize_to_macros_2_0` version of the /// identifier. ident: Ident, ns: Namespace, @@ -1362,7 +1362,7 @@ impl<'a> Resolver<'a> { } fn new_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey { - let ident = ident.modern(); + let ident = ident.normalize_to_macros_2_0(); let disambiguator = if ident.name == kw::Underscore { self.underscore_disambiguator += 1; self.underscore_disambiguator @@ -1413,7 +1413,7 @@ impl<'a> Resolver<'a> { // Avoid marking `extern crate` items that refer to a name from extern prelude, // but not introduce it, as used if they are accessed from lexical scope. if is_lexical_scope { - if let Some(entry) = self.extern_prelude.get(&ident.modern()) { + if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { if let Some(crate_item) = entry.extern_crate_item { if ptr::eq(used_binding, crate_item) && !entry.introduced_by_item { return; @@ -1500,7 +1500,7 @@ impl<'a> Resolver<'a> { TypeNS | ValueNS => Scope::Module(module), MacroNS => Scope::DeriveHelpers(parent_scope.expansion), }; - let mut ident = ident.modern(); + let mut ident = ident.normalize_to_macros_2_0(); let mut use_prelude = !module.no_implicit_prelude; loop { @@ -1622,18 +1622,18 @@ impl<'a> Resolver<'a> { if ident.name == kw::Invalid { return Some(LexicalScopeBinding::Res(Res::Err)); } - let (general_span, modern_span) = if ident.name == kw::SelfUpper { + let (general_span, normalized_span) = if ident.name == kw::SelfUpper { // FIXME(jseyfried) improve `Self` hygiene let empty_span = ident.span.with_ctxt(SyntaxContext::root()); (empty_span, empty_span) } else if ns == TypeNS { - let modern_span = ident.span.modern(); - (modern_span, modern_span) + let normalized_span = ident.span.normalize_to_macros_2_0(); + (normalized_span, normalized_span) } else { - (ident.span.modern_and_legacy(), ident.span.modern()) + (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0()) }; ident.span = general_span; - let modern_ident = Ident { span: modern_span, ..ident }; + let normalized_ident = Ident { span: normalized_span, ..ident }; // Walk backwards up the ribs in scope. let record_used = record_used_id.is_some(); @@ -1641,8 +1641,8 @@ impl<'a> Resolver<'a> { for i in (0..ribs.len()).rev() { debug!("walk rib\n{:?}", ribs[i].bindings); // Use the rib kind to determine whether we are resolving parameters - // (modern hygiene) or local variables (`macro_rules` hygiene). - let rib_ident = if ribs[i].kind.contains_params() { modern_ident } else { ident }; + // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). + let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; if let Some(res) = ribs[i].bindings.get(&rib_ident).cloned() { // The ident resolves to a type parameter or local variable. return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( @@ -1685,7 +1685,7 @@ impl<'a> Resolver<'a> { } } - ident = modern_ident; + ident = normalized_ident; let mut poisoned = None; loop { let opt_module = if let Some(node_id) = record_used_id { @@ -1854,14 +1854,14 @@ impl<'a> Resolver<'a> { let mut adjusted_parent_scope = parent_scope; match module { ModuleOrUniformRoot::Module(m) => { - if let Some(def) = ident.span.modernize_and_adjust(m.expansion) { + if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) { tmp_parent_scope = ParentScope { module: self.macro_def_scope(def), ..*parent_scope }; adjusted_parent_scope = &tmp_parent_scope; } } ModuleOrUniformRoot::ExternPrelude => { - ident.span.modernize_and_adjust(ExpnId::root()); + ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root()); } ModuleOrUniformRoot::CrateRootAndExternPrelude | ModuleOrUniformRoot::CurrentScope => { // No adjustments @@ -1884,14 +1884,14 @@ impl<'a> Resolver<'a> { let mark = if ident.name == kw::DollarCrate { // When resolving `$crate` from a `macro_rules!` invoked in a `macro`, // we don't want to pretend that the `macro_rules!` definition is in the `macro` - // as described in `SyntaxContext::apply_mark`, so we ignore prepended modern marks. + // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks. // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!` // definitions actually produced by `macro` and `macro` definitions produced by // `macro_rules!`, but at least such configurations are not stable yet. - ctxt = ctxt.modern_and_legacy(); + ctxt = ctxt.normalize_to_macro_rules(); let mut iter = ctxt.marks().into_iter().rev().peekable(); let mut result = None; - // Find the last modern mark from the end if it exists. + // Find the last opaque mark from the end if it exists. while let Some(&(mark, transparency)) = iter.peek() { if transparency == Transparency::Opaque { result = Some(mark); @@ -1910,7 +1910,7 @@ impl<'a> Resolver<'a> { } result } else { - ctxt = ctxt.modern(); + ctxt = ctxt.normalize_to_macros_2_0(); ctxt.adjust(ExpnId::root()) }; let module = match mark { @@ -1922,7 +1922,7 @@ impl<'a> Resolver<'a> { fn resolve_self(&mut self, ctxt: &mut SyntaxContext, module: Module<'a>) -> Module<'a> { let mut module = self.get_module(module.normal_ancestor_id); - while module.span.ctxt().modern() != *ctxt { + while module.span.ctxt().normalize_to_macros_2_0() != *ctxt { let parent = module.parent.unwrap_or_else(|| self.macro_def_scope(ctxt.remove_mark())); module = self.get_module(parent.normal_ancestor_id); } @@ -1990,7 +1990,7 @@ impl<'a> Resolver<'a> { if ns == TypeNS { if allow_super && name == kw::Super { - let mut ctxt = ident.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); let self_module = match i { 0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)), _ => match module { @@ -2016,7 +2016,7 @@ impl<'a> Resolver<'a> { } if i == 0 { if name == kw::SelfLower { - let mut ctxt = ident.span.ctxt().modern(); + let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0(); module = Some(ModuleOrUniformRoot::Module( self.resolve_self(&mut ctxt, parent_scope.module), )); @@ -2430,7 +2430,7 @@ impl<'a> Resolver<'a> { macro_rules: &'a NameBinding<'a>, modularized: &'a NameBinding<'a>, ) -> bool { - // Some non-controversial subset of ambiguities "modern macro name" vs "macro_rules" + // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules" // is disambiguated to mitigate regressions from macro modularization. // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general. match ( @@ -2769,7 +2769,7 @@ impl<'a> Resolver<'a> { // Make sure `self`, `super` etc produce an error when passed to here. return None; } - self.extern_prelude.get(&ident.modern()).cloned().and_then(|entry| { + self.extern_prelude.get(&ident.normalize_to_macros_2_0()).cloned().and_then(|entry| { if let Some(binding) = entry.extern_crate_item { if !speculative && entry.introduced_by_item { self.record_use(ident, TypeNS, binding, false); diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index f4dfa037dae..058ead95f50 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -258,7 +258,13 @@ impl<'a> base::Resolver for Resolver<'a> { force, ) { Ok((Some(ext), _)) => { - let span = path.segments.last().unwrap().ident.span.modern(); + let span = path + .segments + .last() + .unwrap() + .ident + .span + .normalize_to_macros_2_0(); helper_attrs.extend( ext.helper_attrs.iter().map(|name| Ident::new(*name, span)), ); diff --git a/src/librustc_span/hygiene.rs b/src/librustc_span/hygiene.rs index a368a881674..e073d735a12 100644 --- a/src/librustc_span/hygiene.rs +++ b/src/librustc_span/hygiene.rs @@ -201,11 +201,11 @@ impl HygieneData { true } - fn modern(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque } - fn modern_and_legacy(&self, ctxt: SyntaxContext) -> SyntaxContext { + fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext { self.syntax_context_data[ctxt.0 as usize].opaque_and_semitransparent } @@ -266,9 +266,9 @@ impl HygieneData { 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) + self.normalize_to_macros_2_0(call_site_ctxt) } else { - self.modern_and_legacy(call_site_ctxt) + self.normalize_to_macro_rules(call_site_ctxt) }; if call_site_ctxt == SyntaxContext::root() { @@ -491,10 +491,10 @@ impl SyntaxContext { HygieneData::with(|data| data.adjust(self, expn_id)) } - /// Like `SyntaxContext::adjust`, but also modernizes `self`. - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option { + /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0. + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { HygieneData::with(|data| { - *self = data.modern(*self); + *self = data.normalize_to_macros_2_0(*self); data.adjust(self, expn_id) }) } @@ -527,7 +527,7 @@ impl SyntaxContext { pub fn glob_adjust(&mut self, expn_id: ExpnId, glob_span: Span) -> Option> { HygieneData::with(|data| { let mut scope = None; - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { scope = Some(data.remove_mark(&mut glob_ctxt).0); if data.remove_mark(self).0 != scope.unwrap() { @@ -558,7 +558,7 @@ impl SyntaxContext { return None; } - let mut glob_ctxt = data.modern(glob_span.ctxt()); + let mut glob_ctxt = data.normalize_to_macros_2_0(glob_span.ctxt()); let mut marks = Vec::new(); while !data.is_descendant_of(expn_id, data.outer_expn(glob_ctxt)) { marks.push(data.remove_mark(&mut glob_ctxt)); @@ -574,20 +574,20 @@ impl SyntaxContext { pub fn hygienic_eq(self, other: SyntaxContext, expn_id: ExpnId) -> bool { HygieneData::with(|data| { - let mut self_modern = data.modern(self); - data.adjust(&mut self_modern, expn_id); - self_modern == data.modern(other) + let mut self_normalized = data.normalize_to_macros_2_0(self); + data.adjust(&mut self_normalized, expn_id); + self_normalized == data.normalize_to_macros_2_0(other) }) } #[inline] - pub fn modern(self) -> SyntaxContext { - HygieneData::with(|data| data.modern(self)) + pub fn normalize_to_macros_2_0(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macros_2_0(self)) } #[inline] - pub fn modern_and_legacy(self) -> SyntaxContext { - HygieneData::with(|data| data.modern_and_legacy(self)) + pub fn normalize_to_macro_rules(self) -> SyntaxContext { + HygieneData::with(|data| data.normalize_to_macro_rules(self)) } #[inline] diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index b5224e57cd2..caa50e9a41c 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -548,9 +548,9 @@ impl Span { } #[inline] - pub fn modernize_and_adjust(&mut self, expn_id: ExpnId) -> Option { + pub fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option { let mut span = self.data(); - let mark = span.ctxt.modernize_and_adjust(expn_id); + let mark = span.ctxt.normalize_to_macros_2_0_and_adjust(expn_id); *self = Span::new(span.lo, span.hi, span.ctxt); mark } @@ -576,15 +576,15 @@ impl Span { } #[inline] - pub fn modern(self) -> Span { + pub fn normalize_to_macros_2_0(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern()) + span.with_ctxt(span.ctxt.normalize_to_macros_2_0()) } #[inline] - pub fn modern_and_legacy(self) -> Span { + pub fn normalize_to_macro_rules(self) -> Span { let span = self.data(); - span.with_ctxt(span.ctxt.modern_and_legacy()) + span.with_ctxt(span.ctxt.normalize_to_macro_rules()) } } diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index bca4bfee85a..5760e1d004e 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -853,12 +853,12 @@ impl Ident { } /// "Normalize" ident for use in comparisons using "item hygiene". - /// Identifiers with same string value become same if they came from the same "modern" macro + /// Identifiers with same string value become same if they came from the same macro 2.0 macro /// (e.g., `macro` item, but not `macro_rules` item) and stay different if they came from - /// different "modern" macros. + /// different macro 2.0 macros. /// Technically, this operation strips all non-opaque marks from ident's syntactic context. - pub fn modern(self) -> Ident { - Ident::new(self.name, self.span.modern()) + pub fn normalize_to_macros_2_0(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macros_2_0()) } /// "Normalize" ident for use in comparisons using "local variable hygiene". @@ -866,8 +866,8 @@ impl Ident { /// macro (e.g., `macro` or `macro_rules!` items) and stay different if they came from different /// non-transparent macros. /// Technically, this operation strips all transparent marks from ident's syntactic context. - pub fn modern_and_legacy(self) -> Ident { - Ident::new(self.name, self.span.modern_and_legacy()) + pub fn normalize_to_macro_rules(self) -> Ident { + Ident::new(self.name, self.span.normalize_to_macro_rules()) } /// Convert the name to a `SymbolStr`. This is a slowish operation because diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index be8090cf21b..b273efa7827 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1441,12 +1441,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(binding.item_name, candidate.def_id(), hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.modern()` instead + // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. let assoc_ty = tcx .associated_items(candidate.def_id()) .filter_by_name_unhygienic(assoc_ident.name) - .find(|i| i.kind == ty::AssocKind::Type && i.ident.modern() == assoc_ident) + .find(|i| { + i.kind == ty::AssocKind::Type && i.ident.normalize_to_macros_2_0() == assoc_ident + }) .expect("missing associated type"); if !assoc_ty.vis.is_accessible_from(def_scope, tcx) { @@ -2298,12 +2300,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let (assoc_ident, def_scope) = tcx.adjust_ident_and_get_scope(assoc_ident, trait_did, hir_ref_id); - // We have already adjusted the item name above, so compare with `ident.modern()` instead + // We have already adjusted the item name above, so compare with `ident.normalize_to_macros_2_0()` instead // of calling `filter_by_name_and_kind`. let item = tcx .associated_items(trait_did) .in_definition_order() - .find(|i| i.kind.namespace() == Namespace::TypeNS && i.ident.modern() == assoc_ident) + .find(|i| { + i.kind.namespace() == Namespace::TypeNS + && i.ident.normalize_to_macros_2_0() == assoc_ident + }) .expect("missing associated type"); let ty = self.projected_ty_from_poly_trait_ref(span, item.def_id, assoc_segment, bound); diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 93f9050b26e..4531d93c01d 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1203,7 +1203,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .fields .iter() .enumerate() - .map(|(i, field)| (field.ident.modern(), (i, field))) + .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field))) .collect::>(); let mut seen_fields = FxHashMap::default(); @@ -1469,7 +1469,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope(field, base_def.did, self.body_id); let fields = &base_def.non_enum_variant().fields; - if let Some(index) = fields.iter().position(|f| f.ident.modern() == ident) { + if let Some(index) = + fields.iter().position(|f| f.ident.normalize_to_macros_2_0() == ident) + { let field = &fields[index]; let field_ty = self.field_ty(expr.span, field, substs); // Save the index of all fields regardless of their visibility in case diff --git a/src/librustc_typeck/check/pat.rs b/src/librustc_typeck/check/pat.rs index fabf3dd1153..0f3884de84e 100644 --- a/src/librustc_typeck/check/pat.rs +++ b/src/librustc_typeck/check/pat.rs @@ -1023,7 +1023,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .fields .iter() .enumerate() - .map(|(i, field)| (field.ident.modern(), (i, field))) + .map(|(i, field)| (field.ident.normalize_to_macros_2_0(), (i, field))) .collect::>(); // Keep track of which fields have already appeared in the pattern. @@ -1064,7 +1064,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut unmentioned_fields = variant .fields .iter() - .map(|field| field.ident.modern()) + .map(|field| field.ident.normalize_to_macros_2_0()) .filter(|ident| !used_fields.contains_key(&ident)) .collect::>(); diff --git a/src/librustc_typeck/coherence/inherent_impls_overlap.rs b/src/librustc_typeck/coherence/inherent_impls_overlap.rs index 1eae9d3b7fa..7513759c76b 100644 --- a/src/librustc_typeck/coherence/inherent_impls_overlap.rs +++ b/src/librustc_typeck/coherence/inherent_impls_overlap.rs @@ -26,7 +26,8 @@ impl InherentOverlapChecker<'tcx> { let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).any(|item2| { // Symbols and namespace match, compare hygienically. item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() + && item1.ident.normalize_to_macros_2_0() + == item2.ident.normalize_to_macros_2_0() }); if collision { @@ -50,11 +51,12 @@ impl InherentOverlapChecker<'tcx> { let collision = impl_items2.filter_by_name_unhygienic(item1.ident.name).find(|item2| { // Symbols and namespace match, compare hygienically. item1.kind.namespace() == item2.kind.namespace() - && item1.ident.modern() == item2.ident.modern() + && item1.ident.normalize_to_macros_2_0() + == item2.ident.normalize_to_macros_2_0() }); if let Some(item2) = collision { - let name = item1.ident.modern(); + let name = item1.ident.normalize_to_macros_2_0(); let mut err = struct_span_err!( self.tcx.sess, self.tcx.span_of_impl(item1.def_id).unwrap(), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index cd63dacdcda..1ffcd7f271e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -828,7 +828,7 @@ fn convert_variant( .iter() .map(|f| { let fid = tcx.hir().local_def_id(f.hir_id); - let dup_span = seen_fields.get(&f.ident.modern()).cloned(); + let dup_span = seen_fields.get(&f.ident.normalize_to_macros_2_0()).cloned(); if let Some(prev_span) = dup_span { struct_span_err!( tcx.sess, @@ -841,7 +841,7 @@ fn convert_variant( .span_label(prev_span, format!("`{}` first declared here", f.ident)) .emit(); } else { - seen_fields.insert(f.ident.modern(), f.span); + seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span); } ty::FieldDef { diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs index 0a765a1f9c9..5fb510d6e33 100644 --- a/src/librustc_typeck/impl_wf_check.rs +++ b/src/librustc_typeck/impl_wf_check.rs @@ -227,7 +227,7 @@ fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_item_refs: &[hir::ImplI hir::ImplItemKind::TyAlias(_) => &mut seen_type_items, _ => &mut seen_value_items, }; - match seen_items.entry(impl_item.ident.modern()) { + match seen_items.entry(impl_item.ident.normalize_to_macros_2_0()) { Occupied(entry) => { let mut err = struct_span_err!( tcx.sess, From 7bd8ce2e506ed4c9a1a2214e7a6e9ead36e92631 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 5 Mar 2020 09:57:34 -0600 Subject: [PATCH 1173/1250] More Method->Fn renaming --- src/librustc/hir/map/blocks.rs | 8 +++--- src/librustc/hir/map/mod.rs | 25 +++++++++++-------- src/librustc_ast_lowering/item.rs | 6 ++--- .../back/symbol_export.rs | 2 +- src/librustc_hir/hir.rs | 10 ++++---- src/librustc_hir/intravisit.rs | 6 ++--- src/librustc_hir/print.rs | 6 ++--- src/librustc_hir/target.rs | 4 +-- .../persist/dirty_clean.rs | 2 +- .../infer/error_reporting/mod.rs | 2 +- .../nice_region_error/find_anon_type.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/nonstandard_style.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 10 ++++---- src/librustc_metadata/rmeta/encoder.rs | 12 ++++----- src/librustc_metadata/rmeta/mod.rs | 2 +- .../diagnostics/mutability_errors.rs | 4 +-- .../borrow_check/diagnostics/region_name.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 2 +- src/librustc_mir_build/build/mod.rs | 4 +-- src/librustc_passes/check_attr.rs | 2 +- src/librustc_passes/dead.rs | 8 +++--- src/librustc_passes/reachable.rs | 14 +++++------ src/librustc_privacy/lib.rs | 5 ++-- src/librustc_resolve/late/lifetimes.rs | 14 +++++------ .../traits/error_reporting/mod.rs | 2 +- .../error_reporting/on_unimplemented.rs | 4 +-- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_traits/lowering/environment.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 6 ++--- src/librustc_typeck/check/method/suggest.rs | 4 +-- src/librustc_typeck/check/mod.rs | 20 +++++++-------- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/collect.rs | 8 +++--- src/librustc_typeck/collect/type_of.rs | 2 +- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustc_typeck/variance/mod.rs | 2 +- src/librustc_typeck/variance/terms.rs | 2 +- src/librustdoc/clean/mod.rs | 6 ++--- 39 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index d9ffe4582e7..7024e86f95d 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -51,7 +51,7 @@ impl MaybeFnLike for hir::Item<'_> { impl MaybeFnLike for hir::ImplItem<'_> { fn is_fn_like(&self) -> bool { match self.kind { - hir::ImplItemKind::Method(..) => true, + hir::ImplItemKind::Fn(..) => true, _ => false, } } @@ -60,7 +60,7 @@ impl MaybeFnLike for hir::ImplItem<'_> { impl MaybeFnLike for hir::TraitItem<'_> { fn is_fn_like(&self) -> bool { match self.kind { - hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, _ => false, } } @@ -239,13 +239,13 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, Node::TraitItem(ti) => match ti.kind { - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { method(ti.hir_id, ti.ident, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), }, Node::ImplItem(ii) => match ii.kind { - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { method(ii.hir_id, ii.ident, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } _ => bug!("impl method FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index bcbb6f3ec31..af08eb7b04c 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -56,7 +56,7 @@ fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> { }, Node::ImplItem(ref item) => match item.kind { - ImplItemKind::Method(ref sig, _) => Some(&sig.decl), + ImplItemKind::Fn(ref sig, _) => Some(&sig.decl), _ => None, }, @@ -82,7 +82,7 @@ fn fn_sig<'hir>(node: Node<'hir>) -> Option<&'hir FnSig<'hir>> { }, Node::ImplItem(item) => match &item.kind { - ImplItemKind::Method(sig, _) => Some(sig), + ImplItemKind::Fn(sig, _) => Some(sig), _ => None, }, @@ -100,13 +100,14 @@ fn associated_body<'hir>(node: Node<'hir>) -> Option { }, Node::TraitItem(item) => match item.kind { - TraitItemKind::Const(_, Some(body)) - | TraitItemKind::Fn(_, TraitMethod::Provided(body)) => Some(body), + TraitItemKind::Const(_, Some(body)) | TraitItemKind::Fn(_, TraitFn::Provided(body)) => { + Some(body) + } _ => None, }, Node::ImplItem(item) => match item.kind { - ImplItemKind::Const(_, body) | ImplItemKind::Method(_, body) => Some(body), + ImplItemKind::Const(_, body) | ImplItemKind::Fn(_, body) => Some(body), _ => None, }, @@ -299,7 +300,7 @@ impl<'hir> Map<'hir> { }, Node::ImplItem(item) => match item.kind { ImplItemKind::Const(..) => DefKind::AssocConst, - ImplItemKind::Method(..) => DefKind::AssocFn, + ImplItemKind::Fn(..) => DefKind::AssocFn, ImplItemKind::TyAlias(..) => DefKind::AssocTy, ImplItemKind::OpaqueTy(..) => DefKind::AssocOpaqueTy, }, @@ -443,7 +444,7 @@ impl<'hir> Map<'hir> { Node::Ctor(..) | Node::Item(&Item { kind: ItemKind::Fn(..), .. }) | Node::TraitItem(&TraitItem { kind: TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&ImplItem { kind: ImplItemKind::Method(..), .. }) => BodyOwnerKind::Fn, + | Node::ImplItem(&ImplItem { kind: ImplItemKind::Fn(..), .. }) => BodyOwnerKind::Fn, Node::Item(&Item { kind: ItemKind::Static(_, m, _), .. }) => BodyOwnerKind::Static(m), Node::Expr(&Expr { kind: ExprKind::Closure(..), .. }) => BodyOwnerKind::Closure, node => bug!("{:#?} is not a body node", node), @@ -541,7 +542,11 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { let node = self.get_entry(hir_id).node; - if let Node::Crate(..) = node { None } else { Some(node) } + if let Node::Crate(..) = node { + None + } else { + Some(node) + } } /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there @@ -749,7 +754,7 @@ impl<'hir> Map<'hir> { _ => false, }, Node::ImplItem(ii) => match ii.kind { - ImplItemKind::Method(..) => true, + ImplItemKind::Fn(..) => true, _ => false, }, Node::Block(_) => true, @@ -1110,7 +1115,7 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId, include_id: bool) -> String { ImplItemKind::Const(..) => { format!("assoc const {} in {}{}", ii.ident, path_str(), id_str) } - ImplItemKind::Method(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), + ImplItemKind::Fn(..) => format!("method {} in {}{}", ii.ident, path_str(), id_str), ImplItemKind::TyAlias(_) => { format!("assoc type {} in {}{}", ii.ident, path_str(), id_str) } diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index 2c60fe9c077..22d876ae14e 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -761,13 +761,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let names = self.lower_fn_params_to_names(&sig.decl); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Required(names))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names))) } AssocItemKind::Fn(_, ref sig, ref generics, Some(ref body)) => { let body_id = self.lower_fn_body_block(i.span, &sig.decl, Some(body)); let (generics, sig) = self.lower_method_sig(generics, sig, trait_item_def_id, false, None); - (generics, hir::TraitItemKind::Fn(sig, hir::TraitMethod::Provided(body_id))) + (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id))) } AssocItemKind::TyAlias(_, ref generics, ref bounds, ref default) => { let ty = default.as_ref().map(|x| self.lower_ty(x, ImplTraitContext::disallowed())); @@ -838,7 +838,7 @@ impl<'hir> LoweringContext<'_, 'hir> { asyncness.opt_return_id(), ); - (generics, hir::ImplItemKind::Method(sig, body_id)) + (generics, hir::ImplItemKind::Fn(sig, body_id)) } AssocItemKind::TyAlias(_, generics, _, ty) => { let generics = self.lower_generics(generics, ImplTraitContext::disallowed()); diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 3fe256ce25b..178a74c791b 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -88,7 +88,7 @@ fn reachable_non_generics_provider( // Only consider nodes that actually have exported symbols. Node::Item(&hir::Item { kind: hir::ItemKind::Static(..), .. }) | Node::Item(&hir::Item { kind: hir::ItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(..), .. }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { let def_id = tcx.hir().local_def_id(hir_id); let generics = tcx.generics_of(def_id); if !generics.requires_monomorphization(tcx) && diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index 48b423de268..b189ae1f13d 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1854,7 +1854,7 @@ pub struct TraitItem<'hir> { /// Represents a trait method's body (or just argument names). #[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)] -pub enum TraitMethod<'hir> { +pub enum TraitFn<'hir> { /// No default body in the trait, just a signature. Required(&'hir [Ident]), @@ -1868,7 +1868,7 @@ pub enum TraitItemKind<'hir> { /// An associated constant with an optional value (otherwise `impl`s must contain a value). Const(&'hir Ty<'hir>, Option), /// An associated function with an optional body. - Fn(FnSig<'hir>, TraitMethod<'hir>), + Fn(FnSig<'hir>, TraitFn<'hir>), /// An associated type with (possibly empty) bounds and optional concrete /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), @@ -1902,7 +1902,7 @@ pub enum ImplItemKind<'hir> { /// of the expression. Const(&'hir Ty<'hir>, BodyId), /// A method implementation with the given signature and body. - Method(FnSig<'hir>, BodyId), + Fn(FnSig<'hir>, BodyId), /// An associated type. TyAlias(&'hir Ty<'hir>), /// An associated `type = impl Trait`. @@ -1913,7 +1913,7 @@ impl ImplItemKind<'_> { pub fn namespace(&self) -> Namespace { match self { ImplItemKind::OpaqueTy(..) | ImplItemKind::TyAlias(..) => Namespace::TypeNS, - ImplItemKind::Const(..) | ImplItemKind::Method(..) => Namespace::ValueNS, + ImplItemKind::Const(..) | ImplItemKind::Fn(..) => Namespace::ValueNS, } } } @@ -2704,7 +2704,7 @@ impl Node<'_> { pub fn fn_decl(&self) -> Option<&FnDecl<'_>> { match self { Node::TraitItem(TraitItem { kind: TraitItemKind::Fn(fn_sig, _), .. }) - | Node::ImplItem(ImplItem { kind: ImplItemKind::Method(fn_sig, _), .. }) + | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(fn_sig, _), .. }) | Node::Item(Item { kind: ItemKind::Fn(fn_sig, _, _), .. }) => Some(fn_sig.decl), Node::ForeignItem(ForeignItem { kind: ForeignItemKind::Fn(fn_decl, _, _), .. }) => { Some(fn_decl) diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 79c7f34dd53..b13f1a91b03 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -911,14 +911,14 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_ty(ty); walk_list!(visitor, visit_nested_body, default); } - TraitItemKind::Fn(ref sig, TraitMethod::Required(param_names)) => { + TraitItemKind::Fn(ref sig, TraitFn::Required(param_names)) => { visitor.visit_id(trait_item.hir_id); visitor.visit_fn_decl(&sig.decl); for ¶m_name in param_names { visitor.visit_ident(param_name); } } - TraitItemKind::Fn(ref sig, TraitMethod::Provided(body_id)) => { + TraitItemKind::Fn(ref sig, TraitFn::Provided(body_id)) => { visitor.visit_fn( FnKind::Method(trait_item.ident, sig, None, &trait_item.attrs), &sig.decl, @@ -968,7 +968,7 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_ty(ty); visitor.visit_nested_body(body); } - ImplItemKind::Method(ref sig, body_id) => { + ImplItemKind::Fn(ref sig, body_id) => { visitor.visit_fn( FnKind::Method(impl_item.ident, sig, Some(&impl_item.vis), &impl_item.attrs), &sig.decl, diff --git a/src/librustc_hir/print.rs b/src/librustc_hir/print.rs index 1a2c3a38565..4e9618b7676 100644 --- a/src/librustc_hir/print.rs +++ b/src/librustc_hir/print.rs @@ -886,13 +886,13 @@ impl<'a> State<'a> { Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_associated_const(ti.ident, &ty, default, &vis); } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref arg_names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref arg_names)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.print_method_sig(ti.ident, sig, &ti.generics, &vis, arg_names, None); self.s.word(";"); } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { let vis = Spanned { span: rustc_span::DUMMY_SP, node: hir::VisibilityKind::Inherited }; self.head(""); @@ -925,7 +925,7 @@ impl<'a> State<'a> { hir::ImplItemKind::Const(ref ty, expr) => { self.print_associated_const(ii.ident, &ty, Some(expr), &ii.vis); } - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { self.head(""); self.print_method_sig(ii.ident, sig, &ii.generics, &ii.vis, &[], Some(body)); self.nbsp(); diff --git a/src/librustc_hir/target.rs b/src/librustc_hir/target.rs index b7bc555d7b4..3a4485a1b17 100644 --- a/src/librustc_hir/target.rs +++ b/src/librustc_hir/target.rs @@ -105,10 +105,10 @@ impl Target { pub fn from_trait_item(trait_item: &TraitItem<'_>) -> Target { match trait_item.kind { TraitItemKind::Const(..) => Target::AssocConst, - TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { + TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { Target::Method(MethodKind::Trait { body: false }) } - TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { + TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { Target::Method(MethodKind::Trait { body: true }) } TraitItemKind::Type(..) => Target::AssocTy, diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index cfc0a5e1498..df5fd110db9 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -333,7 +333,7 @@ impl DirtyCleanVisitor<'tcx> { TraitItemKind::Type(..) => ("NodeTraitType", LABELS_CONST_IN_TRAIT), }, HirNode::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), + ImplItemKind::Fn(..) => ("Node::ImplItem", LABELS_FN_IN_IMPL), ImplItemKind::Const(..) => ("NodeImplConst", LABELS_CONST_IN_IMPL), ImplItemKind::TyAlias(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), ImplItemKind::OpaqueTy(..) => ("NodeImplType", LABELS_CONST_IN_IMPL), diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index 4a39403f211..a544381f33d 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -275,7 +275,7 @@ fn trait_item_scope_tag(item: &hir::TraitItem<'_>) -> &'static str { fn impl_item_scope_tag(item: &hir::ImplItem<'_>) -> &'static str { match item.kind { - hir::ImplItemKind::Method(..) => "method body", + hir::ImplItemKind::Fn(..) => "method body", hir::ImplItemKind::Const(..) | hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(..) => "associated item", diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs index 47d6f5ccbb1..15acf632b2c 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/find_anon_type.rs @@ -37,7 +37,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { .. }) | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(ref m, ..), + kind: hir::ImplItemKind::Fn(ref m, ..), .. }) => &m.decl, _ => return None, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ab8a6070721..54b8fad3930 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -486,7 +486,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let desc = match impl_item.kind { hir::ImplItemKind::Const(..) => "an associated constant", - hir::ImplItemKind::Method(..) => "a method", + hir::ImplItemKind::Fn(..) => "a method", hir::ImplItemKind::TyAlias(_) => "an associated type", hir::ImplItemKind::OpaqueTy(_) => "an associated `impl Trait` type", }; diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs index 37fefe680d7..afab55358d9 100644 --- a/src/librustc_lint/nonstandard_style.rs +++ b/src/librustc_lint/nonstandard_style.rs @@ -343,7 +343,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase { } fn check_trait_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(pnames)) = item.kind { + if let hir::TraitItemKind::Fn(_, hir::TraitFn::Required(pnames)) = item.kind { self.check_snake_case(cx, "trait method", &item.ident); for param_name in pnames { self.check_snake_case(cx, "variable", param_name); diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 7126f86c326..b37e339bab3 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -505,7 +505,7 @@ impl EntryKind { EntryKind::Struct(_, _) => DefKind::Struct, EntryKind::Union(_, _) => DefKind::Union, EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn, - EntryKind::Method(_) => DefKind::AssocFn, + EntryKind::AssocFn(_) => DefKind::AssocFn, EntryKind::Type => DefKind::TyAlias, EntryKind::TypeParam => DefKind::TyParam, EntryKind::ConstParam => DefKind::ConstParam, @@ -1067,7 +1067,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let (kind, container, has_self) = match self.kind(id) { EntryKind::AssocConst(container, _, _) => (ty::AssocKind::Const, container, false), - EntryKind::Method(data) => { + EntryKind::AssocFn(data) => { let data = data.decode(self); (ty::AssocKind::Method, data.container, data.has_self) } @@ -1249,7 +1249,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn get_fn_param_names(&self, id: DefIndex) -> Vec { let param_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).param_names, - EntryKind::Method(data) => data.decode(self).fn_data.param_names, + EntryKind::AssocFn(data) => data.decode(self).fn_data.param_names, _ => Lazy::empty(), }; param_names.decode(self).collect() @@ -1286,7 +1286,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // don't serialize constness for tuple variant and tuple struct constructors. fn is_const_fn_raw(&self, id: DefIndex) -> bool { let constness = match self.kind(id) { - EntryKind::Method(data) => data.decode(self).fn_data.constness, + EntryKind::AssocFn(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, // Some intrinsics can be const fn. While we could recompute this (at least until we // stop having hardcoded whitelists and move to stability attributes), it seems cleaner @@ -1301,7 +1301,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn asyncness(&self, id: DefIndex) -> hir::IsAsync { match self.kind(id) { EntryKind::Fn(data) => data.decode(self).asyncness, - EntryKind::Method(data) => data.decode(self).fn_data.asyncness, + EntryKind::AssocFn(data) => data.decode(self).fn_data.asyncness, EntryKind::ForeignFn(data) => data.decode(self).asyncness, _ => bug!("asyncness: expected function kind"), } diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 8b589f70651..441a4afe197 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -807,10 +807,10 @@ impl EncodeContext<'tcx> { ty::AssocKind::Method => { let fn_data = if let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind { let param_names = match *m { - hir::TraitMethod::Required(ref names) => { + hir::TraitFn::Required(ref names) => { self.encode_fn_param_names(names) } - hir::TraitMethod::Provided(body) => { + hir::TraitFn::Provided(body) => { self.encode_fn_param_names_for_body(body) } }; @@ -822,7 +822,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::Method(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(MethodData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -894,7 +894,7 @@ impl EncodeContext<'tcx> { } } ty::AssocKind::Method => { - let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.kind { + let fn_data = if let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind { FnData { asyncness: sig.header.asyncness, constness: sig.header.constness, @@ -903,7 +903,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::Method(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(MethodData { fn_data, container, has_self: impl_item.method_has_self_argument, @@ -928,7 +928,7 @@ impl EncodeContext<'tcx> { self.encode_inferred_outlives(def_id); let mir = match ast_item.kind { hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(ref sig, _) => { + hir::ImplItemKind::Fn(ref sig, _) => { let generics = self.tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(self.tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 152bb257fa2..55723ec08fa 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -305,7 +305,7 @@ enum EntryKind { Generator(hir::GeneratorKind), Trait(Lazy), Impl(Lazy), - Method(Lazy), + AssocFn(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, mir::ConstQualifs, Lazy), diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs index 5d22ef46c41..c462f934148 100644 --- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs @@ -485,7 +485,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { })) | Some(hir::Node::ImplItem(hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(sig, _), + kind: hir::ImplItemKind::Fn(sig, _), .. })) => Some( arg_pos @@ -527,7 +527,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(sig, _), + kind: hir::ImplItemKind::Fn(sig, _), .. }) => { err.span_label(ident.span, ""); diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs index 01ace742876..7103fc596c9 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs @@ -651,7 +651,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { if gen_move.is_some() { " of generator" } else { " of closure" }, ), hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(method_sig, _), + kind: hir::ImplItemKind::Fn(method_sig, _), .. }) => (method_sig.decl.output.span(), ""), _ => (self.body.span, ""), diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 862a7ef1e73..8892794ffa9 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -983,7 +983,7 @@ impl ItemLikeVisitor<'v> for RootCollector<'_, 'v> { fn visit_impl_item(&mut self, ii: &'v hir::ImplItem<'v>) { match ii.kind { - hir::ImplItemKind::Method(hir::FnSig { .. }, _) => { + hir::ImplItemKind::Fn(hir::FnSig { .. }, _) => { let def_id = self.tcx.hir().local_def_id(ii.hir_id); self.push_if_root(def_id); } diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs index c6bc8694295..821c4d68c7e 100644 --- a/src/librustc_mir_build/build/mod.rs +++ b/src/librustc_mir_build/build/mod.rs @@ -39,12 +39,12 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> { .. }) | Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(hir::FnSig { decl, .. }, body_id), + kind: hir::ImplItemKind::Fn(hir::FnSig { decl, .. }, body_id), .. }) | Node::TraitItem(hir::TraitItem { kind: - hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitMethod::Provided(body_id)), + hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)), .. }) => (*body_id, decl.output.span()), Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. }) diff --git a/src/librustc_passes/check_attr.rs b/src/librustc_passes/check_attr.rs index 702872400c4..373b7c56d38 100644 --- a/src/librustc_passes/check_attr.rs +++ b/src/librustc_passes/check_attr.rs @@ -25,7 +25,7 @@ use rustc_span::Span; fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target { match impl_item.kind { hir::ImplItemKind::Const(..) => Target::AssocConst, - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { let parent_hir_id = tcx.hir().get_parent_item(impl_item.hir_id); let containing_item = tcx.hir().expect_item(parent_hir_id); let containing_impl_is_for_trait = match &containing_item.kind { diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 7460b8e2fe9..587b57eb322 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -391,7 +391,7 @@ impl<'v, 'k, 'tcx> ItemLikeVisitor<'v> for LifeSeeder<'k, 'tcx> { let trait_item = self.krate.trait_item(trait_item_ref.id); match trait_item.kind { hir::TraitItemKind::Const(_, Some(_)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => { if has_allow_dead_code_or_lang_attr( self.tcx, trait_item.hir_id, @@ -661,7 +661,7 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { } self.visit_nested_body(body_id) } - hir::ImplItemKind::Method(_, body_id) => { + hir::ImplItemKind::Fn(_, body_id) => { if !self.symbol_is_live(impl_item.hir_id) { let span = self.tcx.sess.source_map().def_span(impl_item.span); self.warn_dead_code( @@ -682,11 +682,11 @@ impl Visitor<'tcx> for DeadVisitor<'tcx> { fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) { match trait_item.kind { hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id) } hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) + | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => {} } } diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index ad415ed8f62..4643add5ac3 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -53,7 +53,7 @@ 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.kind { + if let hir::ImplItemKind::Fn(method_sig, _) = &impl_item.kind { if method_sig.header.is_const() { return true; } @@ -162,14 +162,14 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { }, Some(Node::TraitItem(trait_method)) => match trait_method.kind { hir::TraitItemKind::Const(_, ref default) => default.is_some(), - hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(_)) => true, - hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) + hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)) => true, + hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) | hir::TraitItemKind::Type(..) => false, }, Some(Node::ImplItem(impl_item)) => { match impl_item.kind { hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { let attrs = self.tcx.codegen_fn_attrs(def_id); let generics = self.tcx.generics_of(def_id); if generics.requires_monomorphization(self.tcx) || attrs.requests_inline() { @@ -278,11 +278,11 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { Node::TraitItem(trait_method) => { match trait_method.kind { hir::TraitItemKind::Const(_, None) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Required(_)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Required(_)) => { // Keep going, nothing to get exported } hir::TraitItemKind::Const(_, Some(body_id)) - | hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)) => { + | hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)) => { self.visit_nested_body(body_id); } hir::TraitItemKind::Type(..) => {} @@ -292,7 +292,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Const(_, body) => { self.visit_nested_body(body); } - hir::ImplItemKind::Method(_, body) => { + hir::ImplItemKind::Fn(_, body) => { let did = self.tcx.hir().get_parent_did(search_item); if method_might_be_inlined(self.tcx, impl_item, did) { self.visit_nested_body(body) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 28a2987301f..bf407b82cbe 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1556,7 +1556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { || items.iter().any(|impl_item_ref| { let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) => { self.access_levels.is_reachable(impl_item_ref.id.hir_id) } hir::ImplItemKind::OpaqueTy(..) | hir::ImplItemKind::TyAlias(_) => { @@ -1578,8 +1578,7 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { // types in private items. let impl_item = self.tcx.hir().impl_item(impl_item_ref.id); match impl_item.kind { - hir::ImplItemKind::Const(..) - | hir::ImplItemKind::Method(..) + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Fn(..) if self .item_is_public(&impl_item.hir_id, &impl_item.vis) => { diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index ddee73e72a4..767ca5f887b 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -771,7 +771,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { use self::hir::ImplItemKind::*; self.missing_named_lifetime_spots.push((&impl_item.generics).into()); match impl_item.kind { - Method(ref sig, _) => { + Fn(ref sig, _) => { let tcx = self.tcx; self.visit_early_late( Some(tcx.hir().get_parent_item(impl_item.hir_id)), @@ -1466,7 +1466,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } } Node::ImplItem(impl_item) => { - if let hir::ImplItemKind::Method(sig, _) = &impl_item.kind { + if let hir::ImplItemKind::Fn(sig, _) = &impl_item.kind { find_arg_use_span(sig.decl.inputs); } } @@ -1818,9 +1818,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { | Node::TraitItem(&hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. }) - | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(..), .. - }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(..), .. }) => { let scope = self.tcx.hir().local_def_id(fn_id); def = Region::Free(scope, def.id().unwrap()); } @@ -2100,12 +2098,12 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { trait_items.iter().find(|ti| ti.id.hir_id == parent).map(|ti| ti.kind); } match *m { - hir::TraitMethod::Required(_) => None, - hir::TraitMethod::Provided(body) => Some(body), + hir::TraitFn::Required(_) => None, + hir::TraitFn::Provided(body) => Some(body), } } - Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Method(_, body), .. }) => { + Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body), .. }) => { if let hir::ItemKind::Impl { ref self_ty, ref items, .. } = self.tcx.hir().expect_item(self.tcx.hir().get_parent_item(parent)).kind { diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index abd9638bfa7..46654a4e8b4 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -715,7 +715,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Node::Item(&hir::Item { span, kind: hir::ItemKind::Fn(ref sig, ..), .. }) | Node::ImplItem(&hir::ImplItem { span, - kind: hir::ImplItemKind::Method(ref sig, _), + kind: hir::ImplItemKind::Fn(ref sig, _), .. }) | Node::TraitItem(&hir::TraitItem { diff --git a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs index 6e3074cd3ca..3d0dd73f03c 100644 --- a/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs +++ b/src/librustc_trait_selection/traits/error_reporting/on_unimplemented.rs @@ -90,11 +90,11 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }) } hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(_, hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(body_id)), .. }) => self.describe_generator(*body_id).or_else(|| Some("a trait method")), hir::Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(sig, body_id), + kind: hir::ImplItemKind::Fn(sig, body_id), .. }) => self.describe_generator(*body_id).or_else(|| { Some(if let hir::FnHeader { asyncness: hir::IsAsync::Async, .. } = sig.header { diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 656c3c7e613..6fe6d7aab28 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -203,7 +203,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { }) | hir::Node::ImplItem(hir::ImplItem { generics, - kind: hir::ImplItemKind::Method(..), + kind: hir::ImplItemKind::Fn(..), .. }) | hir::Node::Item(hir::Item { diff --git a/src/librustc_traits/lowering/environment.rs b/src/librustc_traits/lowering/environment.rs index db392ede432..69d0bd09296 100644 --- a/src/librustc_traits/lowering/environment.rs +++ b/src/librustc_traits/lowering/environment.rs @@ -190,7 +190,7 @@ crate fn environment(tcx: TyCtxt<'_>, def_id: DefId) -> Environment<'_> { }, Node::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => NodeKind::Fn, + ImplItemKind::Fn(..) => NodeKind::Fn, _ => NodeKind::Other, }, diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 1dde57124ee..779b87f6623 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -403,7 +403,7 @@ fn extract_spans_for_error_reporting<'a, 'tcx>( let tcx = infcx.tcx; let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap(); let (impl_m_output, impl_m_iter) = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Method(ref impl_m_sig, _) => { + ImplItemKind::Fn(ref impl_m_sig, _) => { (&impl_m_sig.decl.output, impl_m_sig.decl.inputs.iter()) } _ => bug!("{:?} is not a method", impl_m), @@ -732,7 +732,7 @@ fn compare_number_of_method_arguments<'tcx>( }; let impl_m_hir_id = tcx.hir().as_local_hir_id(impl_m.def_id).unwrap(); let impl_span = match tcx.hir().expect_impl_item(impl_m_hir_id).kind { - ImplItemKind::Method(ref impl_m_sig, _) => { + ImplItemKind::Fn(ref impl_m_sig, _) => { let pos = if impl_number_args > 0 { impl_number_args - 1 } else { 0 }; if let Some(arg) = impl_m_sig.decl.inputs.get(pos) { if pos == 0 { @@ -873,7 +873,7 @@ fn compare_synthetic_generics<'tcx>( let impl_m = tcx.hir().as_local_hir_id(impl_m.def_id)?; let impl_m = tcx.hir().impl_item(hir::ImplItemId { hir_id: impl_m }); let input_tys = match impl_m.kind { - hir::ImplItemKind::Method(ref sig, _) => sig.decl.inputs, + hir::ImplItemKind::Fn(ref sig, _) => sig.decl.inputs, _ => unreachable!(), }; struct Visitor(Option, hir::def_id::DefId); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index ef779cfa834..3eb3624a296 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -939,10 +939,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { })) = id.map(|id| self.tcx.hir().get(id)) { let self_first_arg = match method { - hir::TraitMethod::Required([ident, ..]) => { + hir::TraitFn::Required([ident, ..]) => { ident.name == kw::SelfLower } - hir::TraitMethod::Provided(body_id) => { + hir::TraitFn::Provided(body_id) => { match &self.tcx.hir().body(*body_id).params[..] { [hir::Param { pat: diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d0d421746ae..55e395afad9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -816,14 +816,14 @@ fn primary_body_of( }, Node::TraitItem(item) => match item.kind { hir::TraitItemKind::Const(ref ty, Some(body)) => Some((body, Some(ty), None, None)), - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { Some((body, None, Some(&sig.header), Some(&sig.decl))) } _ => None, }, Node::ImplItem(item) => match item.kind { hir::ImplItemKind::Const(ref ty, body) => Some((body, Some(ty), None, None)), - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { Some((body, None, Some(&sig.header), Some(&sig.decl))) } _ => None, @@ -1896,7 +1896,7 @@ fn check_specialization_validity<'tcx>( ) { let kind = match impl_item.kind { hir::ImplItemKind::Const(..) => ty::AssocKind::Const, - hir::ImplItemKind::Method(..) => ty::AssocKind::Method, + hir::ImplItemKind::Fn(..) => ty::AssocKind::Method, hir::ImplItemKind::OpaqueTy(..) => ty::AssocKind::OpaqueTy, hir::ImplItemKind::TyAlias(_) => ty::AssocKind::Type, }; @@ -2019,7 +2019,7 @@ fn check_impl_items_against_trait<'tcx>( err.emit() } } - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { let opt_trait_span = tcx.hir().span_if_local(ty_trait_item.def_id); if ty_trait_item.kind == ty::AssocKind::Method { compare_impl_method( @@ -4738,9 +4738,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let node = self.tcx.hir().get(self.tcx.hir().get_parent_item(id)); match node { Node::Item(&hir::Item { kind: hir::ItemKind::Fn(_, _, body_id), .. }) - | Node::ImplItem(&hir::ImplItem { - kind: hir::ImplItemKind::Method(_, body_id), .. - }) => { + | Node::ImplItem(&hir::ImplItem { kind: hir::ImplItemKind::Fn(_, body_id), .. }) => { let body = self.tcx.hir().body(body_id); if let ExprKind::Block(block, _) = &body.value.kind { return Some(block.span); @@ -4779,7 +4777,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }) => Some((&sig.decl, ident, true)), Node::ImplItem(&hir::ImplItem { ident, - kind: hir::ImplItemKind::Method(ref sig, ..), + kind: hir::ImplItemKind::Fn(ref sig, ..), .. }) => Some((&sig.decl, ident, false)), _ => None, @@ -4864,11 +4862,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match hir.get_if_local(def_id) { Some(Node::Item(hir::Item { kind: ItemKind::Fn(.., body_id), .. })) | Some(Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Method(_, body_id), + kind: hir::ImplItemKind::Fn(_, body_id), .. })) | Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Provided(body_id)), + kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Provided(body_id)), .. })) => { let body = hir.body(*body_id); @@ -4939,7 +4937,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .join(", ") } Some(Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(.., hir::TraitMethod::Required(idents)), + kind: hir::TraitItemKind::Fn(.., hir::TraitFn::Required(idents)), .. })) => { sugg_call = idents diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 026e68e10e0..23826c84509 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -248,7 +248,7 @@ pub fn check_impl_item(tcx: TyCtxt<'_>, def_id: DefId) { let impl_item = tcx.hir().expect_impl_item(hir_id); let method_sig = match impl_item.kind { - hir::ImplItemKind::Method(ref sig, _) => Some(sig), + hir::ImplItemKind::Fn(ref sig, _) => Some(sig), _ => None, }; diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 779b30c55e1..7594ad5c43a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -745,7 +745,7 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { tcx.predicates_of(def_id); let impl_item = tcx.hir().expect_impl_item(impl_item_id); match impl_item.kind { - hir::ImplItemKind::Method(..) => { + hir::ImplItemKind::Fn(..) => { tcx.fn_sig(def_id); } hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => { @@ -1127,7 +1127,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option None, }, Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Method(ref sig, _) => { + hir::ImplItemKind::Fn(ref sig, _) => { has_late_bound_regions(tcx, &item.generics, &sig.decl) } _ => None, @@ -1437,12 +1437,12 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: DefId) -> ty::PolyFnSig<'_> { match tcx.hir().get(hir_id) { TraitItem(hir::TraitItem { - kind: TraitItemKind::Fn(sig, TraitMethod::Provided(_)), + kind: TraitItemKind::Fn(sig, TraitFn::Provided(_)), ident, generics, .. }) - | ImplItem(hir::ImplItem { kind: ImplItemKind::Method(sig, _), ident, generics, .. }) + | ImplItem(hir::ImplItem { kind: ImplItemKind::Fn(sig, _), ident, generics, .. }) | Item(hir::Item { kind: ItemKind::Fn(sig, generics, _), ident, .. }) => { match get_infer_ret_ty(&sig.decl.output) { Some(ty) => { diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index c4a8edd86f8..c5d3d276721 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -47,7 +47,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { }, Node::ImplItem(item) => match item.kind { - ImplItemKind::Method(..) => { + ImplItemKind::Fn(..) => { let substs = InternalSubsts::identity_for_item(tcx, def_id); tcx.mk_fn_def(def_id, substs) } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index fc3b7201a1e..54f84272ae8 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ConstraintContext<'a, 'tcx> { } fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { - if let hir::ImplItemKind::Method(..) = impl_item.kind { + if let hir::ImplItemKind::Fn(..) = impl_item.kind { self.visit_node_helper(impl_item.hir_id); } } diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs index b1fcc3d3fe8..3cbb42bb5f3 100644 --- a/src/librustc_typeck/variance/mod.rs +++ b/src/librustc_typeck/variance/mod.rs @@ -60,7 +60,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] { }, Node::ImplItem(item) => match item.kind { - hir::ImplItemKind::Method(..) => {} + hir::ImplItemKind::Fn(..) => {} _ => unsupported(), }, diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs index bd44a3eda98..7e6ec96b379 100644 --- a/src/librustc_typeck/variance/terms.rs +++ b/src/librustc_typeck/variance/terms.rs @@ -170,7 +170,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for TermsContext<'a, 'tcx> { } fn visit_impl_item(&mut self, impl_item: &hir::ImplItem<'_>) { - if let hir::ImplItemKind::Method(..) = impl_item.kind { + if let hir::ImplItemKind::Fn(..) = impl_item.kind { self.add_inferreds_for_item(impl_item.hir_id); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e2fca8f39a3..c4ad4554a00 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1084,10 +1084,10 @@ impl Clean for hir::TraitItem<'_> { hir::TraitItemKind::Const(ref ty, default) => { AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e))) } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Provided(body)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => { MethodItem((sig, &self.generics, body, None).clean(cx)) } - hir::TraitItemKind::Fn(ref sig, hir::TraitMethod::Required(ref names)) => { + hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => { let (generics, decl) = enter_impl_trait(cx, || { (self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx)) }); @@ -1118,7 +1118,7 @@ impl Clean for hir::ImplItem<'_> { hir::ImplItemKind::Const(ref ty, expr) => { AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr))) } - hir::ImplItemKind::Method(ref sig, body) => { + hir::ImplItemKind::Fn(ref sig, body) => { MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx)) } hir::ImplItemKind::TyAlias(ref ty) => { From e3c15ae6bc508b754af222a4d47f756e2827cdfe Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 6 Mar 2020 18:00:46 -0600 Subject: [PATCH 1174/1250] update comment --- src/librustc/hir/map/mod.rs | 6 +----- src/librustc_hir/hir.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index af08eb7b04c..55ed07a97d1 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -542,11 +542,7 @@ impl<'hir> Map<'hir> { /// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found. pub fn find(&self, hir_id: HirId) -> Option> { let node = self.get_entry(hir_id).node; - if let Node::Crate(..) = node { - None - } else { - Some(node) - } + if let Node::Crate(..) = node { None } else { Some(node) } } /// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs index b189ae1f13d..5fee6920ddf 100644 --- a/src/librustc_hir/hir.rs +++ b/src/librustc_hir/hir.rs @@ -1901,7 +1901,7 @@ pub enum ImplItemKind<'hir> { /// An associated constant of the given type, set to the constant result /// of the expression. Const(&'hir Ty<'hir>, BodyId), - /// A method implementation with the given signature and body. + /// An associated function implementation with the given signature and body. Fn(FnSig<'hir>, BodyId), /// An associated type. TyAlias(&'hir Ty<'hir>), From 1b92e86a1c70533d76b5ea3937bdaabba9653f2c Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Sun, 15 Mar 2020 11:19:17 -0500 Subject: [PATCH 1175/1250] MethodData -> AssocFnData --- src/librustc_metadata/rmeta/encoder.rs | 4 ++-- src/librustc_metadata/rmeta/mod.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 441a4afe197..005bebbe1e2 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -822,7 +822,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::AssocFn(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(AssocFnData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -903,7 +903,7 @@ impl EncodeContext<'tcx> { } else { bug!() }; - EntryKind::AssocFn(self.lazy(MethodData { + EntryKind::AssocFn(self.lazy(AssocFnData { fn_data, container, has_self: impl_item.method_has_self_argument, diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 55723ec08fa..43a1515da32 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -305,7 +305,7 @@ enum EntryKind { Generator(hir::GeneratorKind), Trait(Lazy), Impl(Lazy), - AssocFn(Lazy), + AssocFn(Lazy), AssocType(AssocContainer), AssocOpaqueTy(AssocContainer), AssocConst(AssocContainer, mir::ConstQualifs, Lazy), @@ -392,7 +392,7 @@ impl AssocContainer { } #[derive(RustcEncodable, RustcDecodable)] -struct MethodData { +struct AssocFnData { fn_data: FnData, container: AssocContainer, has_self: bool, From 73a625b5fb820964fff4ff85ac0a09b398dbe994 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 11 Mar 2020 12:05:32 +0100 Subject: [PATCH 1176/1250] remove unnecessary hir::map imports --- src/librustc_ast_lowering/lib.rs | 3 +-- src/librustc_hir/intravisit.rs | 19 +++++++++++++++++++ src/librustc_lint/builtin.rs | 3 +-- src/librustc_mir/transform/check_unsafety.rs | 3 +-- src/librustc_mir/transform/mod.rs | 3 +-- .../hair/pattern/check_match.rs | 5 ++--- src/librustc_passes/dead.rs | 2 +- src/librustc_passes/intrinsicck.rs | 5 ++--- src/librustc_passes/liveness.rs | 2 +- src/librustc_passes/reachable.rs | 6 ++---- src/librustc_passes/region.rs | 3 +-- src/librustc_passes/upvars.rs | 5 ++--- src/librustc_passes/weak_lang_items.rs | 5 ++--- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 10 +++++----- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 3 +-- .../check/generator_interior.rs | 3 +-- src/librustc_typeck/check/method/suggest.rs | 3 +-- src/librustc_typeck/check/mod.rs | 3 +-- src/librustc_typeck/check/regionck.rs | 3 +-- src/librustc_typeck/check/upvar.rs | 3 +-- src/librustc_typeck/check/writeback.rs | 3 +-- src/librustc_typeck/collect.rs | 4 ++-- 24 files changed, 52 insertions(+), 51 deletions(-) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 3ef02d7c61e..6685a89d2c7 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -37,7 +37,6 @@ use rustc::arena::Arena; use rustc::dep_graph::DepGraph; use rustc::hir::map::definitions::{DefKey, DefPathData, Definitions}; -use rustc::hir::map::Map; use rustc::{bug, span_bug}; use rustc_ast::ast; use rustc_ast::ast::*; @@ -1460,7 +1459,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } impl<'r, 'a, 'v, 'hir> intravisit::Visitor<'v> for ImplTraitLifetimeCollector<'r, 'a, 'hir> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs index 79c7f34dd53..5ccec90cee1 100644 --- a/src/librustc_hir/intravisit.rs +++ b/src/librustc_hir/intravisit.rs @@ -127,6 +127,25 @@ pub trait Map<'hir> { fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir>; } +/// An erased version of `Map<'hir>`, using dynamic dispatch. +/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`. +pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>); + +impl<'hir> Map<'hir> for ErasedMap<'hir> { + fn body(&self, id: BodyId) -> &'hir Body<'hir> { + self.0.body(id) + } + fn item(&self, id: HirId) -> &'hir Item<'hir> { + self.0.item(id) + } + fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> { + self.0.trait_item(id) + } + fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> { + self.0.impl_item(id) + } +} + /// Specifies what nested things a visitor wants to visit. The most /// common choice is `OnlyBodies`, which will cause the visitor to /// visit fn bodies for fns that it encounters, but skip over nested diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index ab8a6070721..e9dda81ed43 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -22,7 +22,6 @@ //! `late_lint_methods!` invocation in `lib.rs`. use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; -use rustc::hir::map::Map; use rustc::lint::LintDiagnosticBuilder; use rustc::ty::{self, layout::VariantIdx, Ty, TyCtxt}; use rustc_ast::ast::{self, Expr}; @@ -1071,7 +1070,7 @@ impl TypeAliasBounds { err: &'a mut DiagnosticBuilder<'db>, } impl<'a, 'db, 'v> Visitor<'v> for WalkAssocTypes<'a, 'db> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 21788593259..78440c8437d 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::Map; use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; @@ -451,7 +450,7 @@ struct UnusedUnsafeVisitor<'a> { } impl<'a, 'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'a> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index d4a5966af4a..3eb9d23a32a 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,5 +1,4 @@ use crate::{shim, util}; -use rustc::hir::map::Map; use rustc::mir::{BodyAndCache, ConstQualifs, MirPhase, Promoted}; use rustc::ty::query::Providers; use rustc::ty::steal::Steal; @@ -86,7 +85,7 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> &DefIdSet { } intravisit::walk_struct_def(self, v) } - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 36913051813..f71ec5e9ac0 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -4,7 +4,6 @@ use super::_match::{expand_pattern, is_useful, MatchCheckCtxt, Matrix, PatStack} use super::{PatCtxt, PatKind, PatternError}; -use rustc::hir::map::Map; use rustc::ty::{self, Ty, TyCtxt}; use rustc_ast::ast::Mutability; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder}; @@ -43,7 +42,7 @@ struct MatchVisitor<'a, 'tcx> { } impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -753,7 +752,7 @@ fn check_legality_of_bindings_in_at_patterns(cx: &MatchVisitor<'_, '_>, pat: &Pa } impl<'v> Visitor<'v> for AtBindingPatternVisitor<'_, '_, '_> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/dead.rs b/src/librustc_passes/dead.rs index 7460b8e2fe9..0c90933bd19 100644 --- a/src/librustc_passes/dead.rs +++ b/src/librustc_passes/dead.rs @@ -210,7 +210,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/intrinsicck.rs b/src/librustc_passes/intrinsicck.rs index 5cf9666797e..1b46aaeefcb 100644 --- a/src/librustc_passes/intrinsicck.rs +++ b/src/librustc_passes/intrinsicck.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::Map; use rustc::ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; use rustc::ty::query::Providers; use rustc::ty::{self, Ty, TyCtxt}; @@ -122,7 +121,7 @@ impl ExprVisitor<'tcx> { } impl Visitor<'tcx> for ItemVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -139,7 +138,7 @@ impl Visitor<'tcx> for ItemVisitor<'tcx> { } impl Visitor<'tcx> for ExprVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 030d0893b02..161aad253f2 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1359,7 +1359,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // Checking for error conditions impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index ad415ed8f62..34af0d5b03e 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -5,7 +5,6 @@ // makes all other generics or inline functions that it references // reachable as well. -use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::middle::privacy; use rustc::session::config; @@ -17,8 +16,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::def_id::{CrateNum, DefId}; -use rustc_hir::intravisit; -use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdSet, Node}; use rustc_target::spec::abi::Abi; @@ -83,7 +81,7 @@ struct ReachableContext<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index 640a3a35aa0..e771696a5b6 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -6,7 +6,6 @@ //! //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html -use rustc::hir::map::Map; use rustc::middle::region::*; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; @@ -696,7 +695,7 @@ impl<'tcx> RegionResolutionVisitor<'tcx> { } impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/upvars.rs b/src/librustc_passes/upvars.rs index d20237a22d9..43f39e6c610 100644 --- a/src/librustc_passes/upvars.rs +++ b/src/librustc_passes/upvars.rs @@ -1,6 +1,5 @@ //! Upvar (closure capture) collection from cross-body HIR uses of `Res::Local`s. -use rustc::hir::map::Map; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; @@ -44,7 +43,7 @@ struct LocalCollector { } impl Visitor<'tcx> for LocalCollector { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -73,7 +72,7 @@ impl CaptureCollector<'_, '_> { } impl Visitor<'tcx> for CaptureCollector<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index d85c7d8c6de..2aef080a677 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -4,7 +4,6 @@ use rustc::middle::lang_items; use rustc::middle::lang_items::whitelisted; use rustc::session::config; -use rustc::hir::map::Map; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; @@ -85,9 +84,9 @@ impl<'a, 'tcx> Context<'a, 'tcx> { } impl<'a, 'tcx, 'v> Visitor<'v> for Context<'a, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; - fn nested_visit_map(&mut self) -> NestedVisitorMap> { + fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 28a2987301f..8dd4fadc026 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -1447,7 +1447,7 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> { } impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index ddee73e72a4..e28b4884b88 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -1123,7 +1123,7 @@ fn extract_labels(ctxt: &mut LifetimeContext<'_, '_>, body: &hir::Body<'_>) { gather.visit_body(body); impl<'v, 'a, 'tcx> Visitor<'v> for GatherLabels<'a, 'tcx> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -2172,7 +2172,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } impl<'a> Visitor<'a> for SelfVisitor<'a> { - type Map = Map<'a>; + type Map = intravisit::ErasedMap<'a>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -2263,7 +2263,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { } impl<'v, 'a> Visitor<'v> for GatherLifetimes<'a> { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -2852,7 +2852,7 @@ fn insert_late_bound_lifetimes( } impl<'v> Visitor<'v> for ConstrainedCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -2895,7 +2895,7 @@ fn insert_late_bound_lifetimes( } impl<'v> Visitor<'v> for AllCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 656c3c7e613..f9d8bf37761 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1567,7 +1567,7 @@ struct ReturnsVisitor<'v> { } impl<'v> Visitor<'v> for ReturnsVisitor<'v> { - type Map = rustc::hir::map::Map<'v>; + type Map = hir::intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap { hir::intravisit::NestedVisitorMap::None diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 1dde57124ee..09dece7d7e4 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -1,4 +1,3 @@ -use rustc::hir::map::Map; use rustc::ty::error::{ExpectedFound, TypeError}; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::ExplicitSelf; @@ -890,7 +889,7 @@ fn compare_synthetic_generics<'tcx>( } } } - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map( &mut self, ) -> intravisit::NestedVisitorMap diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 5208e2f56a5..cdf68256a7a 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -4,7 +4,6 @@ //! types computed here. use super::FnCtxt; -use rustc::hir::map::Map; use rustc::middle::region::{self, YieldData}; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -209,7 +208,7 @@ pub fn resolve_interior<'a, 'tcx>( // librustc/middle/region.rs since `expr_count` is compared against the results // there. impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index ef779cfa834..7ad2120fa54 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -4,7 +4,6 @@ use crate::check::FnCtxt; use crate::middle::lang_items::FnOnceTraitLangItem; use rustc::hir::map as hir_map; -use rustc::hir::map::Map; use rustc::ty::print::with_crate_prefix; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc_ast::ast; @@ -1347,7 +1346,7 @@ impl intravisit::Visitor<'tcx> for UsePlacementFinder<'tcx> { } } - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap { intravisit::NestedVisitorMap::None diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d0d421746ae..bbc9171918f 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,7 +90,6 @@ pub mod writeback; use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg}; use crate::middle::lang_items; use rustc::hir::map::blocks::FnLikeNode; -use rustc::hir::map::Map; use rustc::middle::region; use rustc::mir::interpret::ConstValue; use rustc::session::parse::feature_err; @@ -1177,7 +1176,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 975c6e101a6..72e4169332e 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -76,7 +76,6 @@ use crate::check::dropck; use crate::check::FnCtxt; use crate::mem_categorization as mc; use crate::middle::region; -use rustc::hir::map::Map; use rustc::ty::adjustment; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::ty::{self, Ty}; @@ -417,7 +416,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionCtxt<'a, 'tcx> { // hierarchy, and in particular the relationships between free // regions, until regionck, as described in #3238. - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 7bc121733a4..44b960ad22b 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -35,7 +35,6 @@ use super::FnCtxt; use crate::expr_use_visitor as euv; use crate::mem_categorization as mc; use crate::mem_categorization::PlaceBase; -use rustc::hir::map::Map; use rustc::ty::{self, Ty, TyCtxt, UpvarSubsts}; use rustc_ast::ast; use rustc_data_structures::fx::FxIndexMap; @@ -60,7 +59,7 @@ struct InferBorrowKindVisitor<'a, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b8f8030e3cd..58b45638e43 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -4,7 +4,6 @@ use crate::check::FnCtxt; -use rustc::hir::map::Map; use rustc::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; @@ -244,7 +243,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { // traffic in node-ids or update tables in the type context etc. impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 779b30c55e1..9bb1f7e3131 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -105,7 +105,7 @@ pub struct ItemCtxt<'tcx> { crate struct PlaceholderHirTyCollector(crate Vec); impl<'v> Visitor<'v> for PlaceholderHirTyCollector { - type Map = Map<'v>; + type Map = intravisit::ErasedMap<'v>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None @@ -1045,7 +1045,7 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option for LateBoundRegionsDetector<'tcx> { - type Map = Map<'tcx>; + type Map = intravisit::ErasedMap<'tcx>; fn nested_visit_map(&mut self) -> NestedVisitorMap { NestedVisitorMap::None From 4392a8b73c3f51315c593344f4e7386ebc6e78e5 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Wed, 11 Mar 2020 12:49:08 +0100 Subject: [PATCH 1177/1250] use direct imports for `rustc::{lint, session}`. --- Cargo.lock | 10 ++++++ src/librustc/ich/hcx.rs | 5 ++- src/librustc/lib.rs | 1 - src/librustc/lint.rs | 2 +- src/librustc/middle/cstore.rs | 18 +++++----- src/librustc/middle/dependency_format.rs | 2 +- src/librustc/middle/limits.rs | 6 ++-- src/librustc/middle/stability.rs | 2 +- src/librustc/mir/mono.rs | 2 +- src/librustc/ty/layout.rs | 34 ++++++++----------- src/librustc/ty/mod.rs | 3 +- src/librustc/ty/query/mod.rs | 4 +-- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/librustc_ast_lowering/path.rs | 2 +- src/librustc_codegen_llvm/attributes.rs | 4 +-- src/librustc_codegen_llvm/back/archive.rs | 2 +- src/librustc_codegen_llvm/back/lto.rs | 2 +- src/librustc_codegen_llvm/back/write.rs | 4 +-- src/librustc_codegen_llvm/base.rs | 2 +- src/librustc_codegen_llvm/builder.rs | 2 +- src/librustc_codegen_llvm/context.rs | 17 +++++----- src/librustc_codegen_llvm/debuginfo/gdb.rs | 2 +- .../debuginfo/metadata.rs | 2 +- src/librustc_codegen_llvm/debuginfo/mod.rs | 2 +- src/librustc_codegen_llvm/lib.rs | 23 ++++++------- src/librustc_codegen_llvm/llvm/ffi.rs | 4 +-- src/librustc_codegen_llvm/llvm_util.rs | 4 +-- src/librustc_codegen_ssa/back/archive.rs | 2 +- src/librustc_codegen_ssa/back/link.rs | 12 +++---- src/librustc_codegen_ssa/back/linker.rs | 6 ++-- .../back/symbol_export.rs | 2 +- src/librustc_codegen_ssa/back/write.rs | 8 ++--- src/librustc_codegen_ssa/base.rs | 4 +-- src/librustc_codegen_ssa/common.rs | 2 +- src/librustc_codegen_ssa/lib.rs | 2 +- src/librustc_codegen_ssa/mir/debuginfo.rs | 2 +- src/librustc_codegen_ssa/traits/backend.rs | 2 +- src/librustc_codegen_ssa/traits/misc.rs | 2 +- src/librustc_codegen_utils/Cargo.toml | 1 + src/librustc_codegen_utils/codegen_backend.rs | 4 +-- src/librustc_codegen_utils/link.rs | 4 +-- src/librustc_codegen_utils/symbol_names.rs | 2 +- src/librustc_driver/Cargo.toml | 1 + src/librustc_driver/lib.rs | 12 +++---- src/librustc_driver/pretty.rs | 4 +-- src/librustc_errors/emitter.rs | 2 +- .../persist/file_format.rs | 2 +- src/librustc_incremental/persist/fs.rs | 2 +- src/librustc_incremental/persist/load.rs | 2 +- src/librustc_incremental/persist/save.rs | 2 +- .../persist/work_product.rs | 2 +- src/librustc_infer/Cargo.toml | 1 + src/librustc_infer/infer/mod.rs | 6 ++-- src/librustc_interface/interface.rs | 8 ++--- src/librustc_interface/passes.rs | 10 +++--- src/librustc_interface/queries.rs | 4 +-- src/librustc_interface/tests.rs | 14 ++++---- src/librustc_interface/util.rs | 3 +- src/librustc_metadata/Cargo.toml | 1 + src/librustc_metadata/creader.rs | 9 +++-- src/librustc_metadata/dependency_format.rs | 2 +- src/librustc_metadata/lib.rs | 2 +- src/librustc_metadata/locator.rs | 6 ++-- src/librustc_metadata/native_libs.rs | 4 +-- src/librustc_metadata/rmeta/decoder.rs | 23 ++++++------- .../rmeta/decoder/cstore_impl.rs | 2 +- src/librustc_metadata/rmeta/encoder.rs | 24 ++++++------- src/librustc_metadata/rmeta/mod.rs | 4 +-- src/librustc_mir/Cargo.toml | 1 + src/librustc_mir/borrow_check/mod.rs | 9 ++--- src/librustc_mir/dataflow/mod.rs | 14 ++++---- src/librustc_mir/monomorphize/collector.rs | 2 +- .../transform/check_consts/ops.rs | 4 +-- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/dump_mir.rs | 2 +- src/librustc_mir/transform/inline.rs | 15 ++++---- src/librustc_mir_build/hair/pattern/_match.rs | 12 +++---- .../hair/pattern/const_to_pat.rs | 10 +++--- src/librustc_mir_build/lints.rs | 2 +- src/librustc_passes/check_const.rs | 4 +-- src/librustc_passes/entry.rs | 4 +-- src/librustc_passes/liveness.rs | 2 +- src/librustc_passes/reachable.rs | 2 +- src/librustc_passes/stability.rs | 6 ++-- src/librustc_passes/weak_lang_items.rs | 3 +- src/librustc_plugin_impl/Cargo.toml | 1 + src/librustc_plugin_impl/load.rs | 2 +- src/librustc_privacy/Cargo.toml | 1 + src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/check_unused.rs | 10 +++--- src/librustc_resolve/diagnostics.rs | 2 +- src/librustc_resolve/imports.rs | 2 +- src/librustc_resolve/late.rs | 3 +- src/librustc_resolve/late/diagnostics.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 2 +- src/librustc_resolve/lib.rs | 2 +- src/librustc_resolve/macros.rs | 14 +++----- src/librustc_save_analysis/Cargo.toml | 1 + src/librustc_save_analysis/dump_visitor.rs | 2 +- src/librustc_save_analysis/lib.rs | 2 +- src/librustc_save_analysis/span_utils.rs | 2 +- src/librustc_trait_selection/opaque_types.rs | 2 +- .../traits/error_reporting/mod.rs | 2 +- src/librustc_ty/Cargo.toml | 1 + src/librustc_ty/ty.rs | 2 +- src/librustc_typeck/Cargo.toml | 1 + src/librustc_typeck/astconv.rs | 10 +++--- src/librustc_typeck/check/autoderef.rs | 7 ++-- src/librustc_typeck/check/cast.rs | 4 +-- src/librustc_typeck/check/coercion.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 4 +-- src/librustc_typeck/check/mod.rs | 10 +++--- src/librustc_typeck/check/wfcheck.rs | 7 ++-- src/librustc_typeck/check_unused.rs | 2 +- src/librustc_typeck/collect.rs | 4 +-- src/librustc_typeck/collect/type_of.rs | 2 +- src/librustc_typeck/lib.rs | 4 +-- src/librustc_typeck/structured_errors.rs | 2 +- src/librustdoc/config.rs | 17 +++++----- src/librustdoc/core.rs | 21 ++++++------ src/librustdoc/lib.rs | 4 +-- .../passes/collect_intra_doc_links.rs | 2 +- src/librustdoc/passes/mod.rs | 2 +- src/librustdoc/test.rs | 6 ++-- .../hotplug_codegen_backend/the_backend.rs | 9 ++--- src/test/run-make-fulldeps/issue-19371/foo.rs | 7 ++-- 127 files changed, 317 insertions(+), 334 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42049da8e6a..afd072bf50c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3625,6 +3625,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_metadata", + "rustc_session", "rustc_span", "rustc_target", ] @@ -3678,6 +3679,7 @@ dependencies = [ "rustc_parse", "rustc_plugin_impl", "rustc_save_analysis", + "rustc_session", "rustc_span", "rustc_target", "serialize", @@ -3792,6 +3794,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_macros", + "rustc_session", "rustc_span", "rustc_target", "smallvec 1.0.0", @@ -3904,6 +3907,7 @@ dependencies = [ "rustc_expand", "rustc_hir", "rustc_index", + "rustc_session", "rustc_span", "rustc_target", "serialize", @@ -3934,6 +3938,7 @@ dependencies = [ "rustc_infer", "rustc_lexer", "rustc_macros", + "rustc_session", "rustc_span", "rustc_target", "rustc_trait_selection", @@ -4014,6 +4019,7 @@ dependencies = [ "rustc_hir", "rustc_lint", "rustc_metadata", + "rustc_session", "rustc_span", ] @@ -4028,6 +4034,7 @@ dependencies = [ "rustc_data_structures", "rustc_errors", "rustc_hir", + "rustc_session", "rustc_span", "rustc_typeck", ] @@ -4069,6 +4076,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_parse", + "rustc_session", "rustc_span", "serde_json", ] @@ -4175,6 +4183,7 @@ dependencies = [ "rustc_data_structures", "rustc_hir", "rustc_infer", + "rustc_session", "rustc_span", "rustc_target", "rustc_trait_selection", @@ -4194,6 +4203,7 @@ dependencies = [ "rustc_hir", "rustc_index", "rustc_infer", + "rustc_session", "rustc_span", "rustc_target", "rustc_trait_selection", diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index c15d54745a1..8fd86b3232d 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -1,8 +1,6 @@ -use crate::hir::map::definitions::Definitions; -use crate::hir::map::DefPathHash; +use crate::hir::map::definitions::{DefPathHash, Definitions}; use crate::ich::{self, CachingSourceMapView}; use crate::middle::cstore::CrateStore; -use crate::session::Session; use crate::ty::{fast_reject, TyCtxt}; use rustc_ast::ast; @@ -11,6 +9,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIndex}; +use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; use rustc_span::{BytePos, SourceFile}; diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24237235e0c..00e66425e00 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -80,7 +80,6 @@ pub mod infer; pub mod lint; pub mod middle; pub mod mir; -pub use rustc_session as session; pub mod traits; pub mod ty; diff --git a/src/librustc/lint.rs b/src/librustc/lint.rs index dcc8dcbf219..d4d01a716db 100644 --- a/src/librustc/lint.rs +++ b/src/librustc/lint.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_errors::{pluralize, Applicability, DiagnosticBuilder, DiagnosticId}; use rustc_hir::HirId; -pub use rustc_session::lint::{builtin, Level, Lint, LintId, LintPass}; +use rustc_session::lint::{builtin, Level, Lint, LintId}; use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::{DesugaringKind, ExpnKind, MultiSpan}; diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 42d56c65462..9f5a56903aa 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -2,10 +2,9 @@ //! are *mostly* used as a part of that interface, but these should //! probably get a better home if someone can find one. -use crate::hir::map as hir_map; -use crate::hir::map::definitions::{DefKey, DefPathTable}; -use crate::session::search_paths::PathKind; -use crate::session::CrateDisambiguator; +pub use self::NativeLibraryKind::*; + +use crate::hir::map::definitions::{DefKey, DefPath, DefPathHash, DefPathTable}; use crate::ty::TyCtxt; use rustc_ast::ast; @@ -14,15 +13,16 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, MetadataRef}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_macros::HashStable; +use rustc_session::search_paths::PathKind; +pub use rustc_session::utils::NativeLibraryKind; +use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::Target; + use std::any::Any; use std::path::{Path, PathBuf}; -pub use self::NativeLibraryKind::*; -pub use rustc_session::utils::NativeLibraryKind; - // lonely orphan structs and enums looking for a better home /// Where a crate came from on the local filesystem. One of these three options @@ -197,8 +197,8 @@ pub trait CrateStore { // resolve fn def_key(&self, def: DefId) -> DefKey; - fn def_path(&self, def: DefId) -> hir_map::DefPath; - fn def_path_hash(&self, def: DefId) -> hir_map::DefPathHash; + fn def_path(&self, def: DefId) -> DefPath; + fn def_path_hash(&self, def: DefId) -> DefPathHash; fn def_path_table(&self, cnum: CrateNum) -> &DefPathTable; // "queries" used in resolve that aren't tracked for incremental compilation diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 6ece51fe866..ee5f822d313 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -4,7 +4,7 @@ //! For all the gory details, see the provider of the `dependency_formats` //! query. -use crate::session::config; +use rustc_session::config; /// A list of dependencies for a certain crate type. /// diff --git a/src/librustc/middle/limits.rs b/src/librustc/middle/limits.rs index 22e4f5ea222..6de53c703e1 100644 --- a/src/librustc/middle/limits.rs +++ b/src/librustc/middle/limits.rs @@ -5,13 +5,13 @@ //! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass //! just peeks and looks for that attribute. -use crate::session::Session; -use core::num::IntErrorKind; use rustc::bug; use rustc_ast::ast; +use rustc_data_structures::sync::Once; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; -use rustc_data_structures::sync::Once; +use std::num::IntErrorKind; pub fn update_limits(sess: &Session, krate: &ast::Crate) { update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128); diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 048e24ce3aa..46525bdedad 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -3,7 +3,6 @@ pub use self::StabilityLevel::*; -use crate::session::{DiagnosticMessageId, Session}; use crate::ty::{self, TyCtxt}; use rustc_ast::ast::CRATE_NODE_ID; use rustc_attr::{self as attr, ConstStability, Deprecation, RustcDeprecation, Stability}; @@ -17,6 +16,7 @@ use rustc_hir::{self, HirId}; use rustc_session::lint::builtin::{DEPRECATED, DEPRECATED_IN_FUTURE, SOFT_UNSTABLE}; use rustc_session::lint::{BuiltinLintDiagnostics, Lint, LintBuffer}; use rustc_session::parse::feature_err_issue; +use rustc_session::{DiagnosticMessageId, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{MultiSpan, Span}; diff --git a/src/librustc/mir/mono.rs b/src/librustc/mir/mono.rs index 4f8efc1607e..27d82d25803 100644 --- a/src/librustc/mir/mono.rs +++ b/src/librustc/mir/mono.rs @@ -1,6 +1,5 @@ use crate::dep_graph::{DepConstructor, DepNode, WorkProduct, WorkProductId}; use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; -use crate::session::config::OptLevel; use crate::ty::print::obsolete::DefPathBasedNames; use crate::ty::{subst::InternalSubsts, Instance, InstanceDef, SymbolName, TyCtxt}; use rustc_attr::InlineAttr; @@ -9,6 +8,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_hir::HirId; +use rustc_session::config::OptLevel; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; use std::fmt; diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index dedb3035ced..6a576ef3ce9 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -1,30 +1,28 @@ -use crate::session::{self, DataTypeKind}; +use crate::ich::StableHashingContext; +use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; +use crate::ty::subst::Subst; use crate::ty::{self, subst::SubstsRef, ReprOptions, Ty, TyCtxt, TypeFoldable}; use rustc_ast::ast::{self, Ident, IntTy, UintTy}; use rustc_attr as attr; -use rustc_span::DUMMY_SP; - -use std::cmp; -use std::fmt; -use std::iter; -use std::mem; -use std::ops::Bound; - -use crate::ich::StableHashingContext; -use crate::mir::{GeneratorLayout, GeneratorSavedLocal}; -use crate::ty::subst::Subst; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; - +use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; +use rustc_span::DUMMY_SP; use rustc_target::abi::call::{ ArgAbi, ArgAttribute, ArgAttributes, Conv, FnAbi, PassMode, Reg, RegKind, }; pub use rustc_target::abi::*; use rustc_target::spec::{abi::Abi as SpecAbi, HasTargetSpec}; +use std::cmp; +use std::fmt; +use std::iter; +use std::mem; +use std::ops::Bound; + pub trait IntegerExt { fn to_ty<'tcx>(&self, tcx: TyCtxt<'tcx>, signed: bool) -> Ty<'tcx>; fn from_attr(cx: &C, ity: attr::IntType) -> Integer; @@ -1648,7 +1646,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { if min_size < field_end { min_size = field_end; } - session::FieldInfo { + FieldInfo { name: name.to_string(), offset: offset.bytes(), size: field_layout.size.bytes(), @@ -1658,13 +1656,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { }) .collect(); - session::VariantInfo { + VariantInfo { name: n.map(|n| n.to_string()), - kind: if layout.is_unsized() { - session::SizeKind::Min - } else { - session::SizeKind::Exact - }, + kind: if layout.is_unsized() { SizeKind::Min } else { SizeKind::Exact }, align: layout.align.abi.bytes(), size: if min_size.bytes() == 0 { layout.size.bytes() } else { min_size.bytes() }, fields: field_info, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index d3c4ddf1ed3..d62827f7146 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -9,7 +9,6 @@ pub use self::Variance::*; use crate::arena::Arena; use crate::hir::exports::ExportMap; use crate::hir::map as hir_map; - use crate::ich::Fingerprint; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; @@ -19,7 +18,6 @@ use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::interpret::ErrorHandled; use crate::mir::GeneratorLayout; use crate::mir::ReadOnlyBodyAndCache; -use crate::session::DataTypeKind; use crate::traits::{self, Reveal}; use crate::ty; use crate::ty::layout::VariantIdx; @@ -42,6 +40,7 @@ use rustc_hir::{Constness, GlobMap, Node, TraitMap}; use rustc_index::vec::{Idx, IndexVec}; use rustc_macros::HashStable; use rustc_serialize::{self, Encodable, Encoder}; +use rustc_session::DataTypeKind; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index 3d17883fec3..e3859ed12a2 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -19,8 +19,6 @@ use crate::mir::interpret::GlobalId; use crate::mir::interpret::{ConstEvalRawResult, ConstEvalResult, ConstValue}; use crate::mir::interpret::{LitToConstError, LitToConstInput}; use crate::mir::mono::CodegenUnit; -use crate::session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; -use crate::session::CrateDisambiguator; use crate::traits::query::{ CanonicalPredicateGoal, CanonicalProjectionGoal, CanonicalTyGoal, CanonicalTypeOpAscribeUserTypeGoal, CanonicalTypeOpEqGoal, CanonicalTypeOpNormalizeGoal, @@ -49,6 +47,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex}; use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate}; use rustc_index::vec::IndexVec; +use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; +use rustc_session::CrateDisambiguator; use rustc_target::spec::PanicStrategy; use rustc_ast::ast; diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 9c1db7c5f2b..62c2bd801ee 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -3,7 +3,6 @@ use crate::hir::map::definitions::DefPathHash; use crate::ich::{CachingSourceMapView, Fingerprint}; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::{self, interpret}; -use crate::session::{CrateDisambiguator, Session}; use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder}; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; @@ -19,6 +18,7 @@ use rustc_serialize::{ opaque, Decodable, Decoder, Encodable, Encoder, SpecializedDecoder, SpecializedEncoder, UseSpecializedDecodable, UseSpecializedEncodable, }; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::hygiene::{ExpnId, SyntaxContext}; use rustc_span::source_map::{SourceMap, StableSourceFileId}; use rustc_span::{BytePos, SourceFile, Span, DUMMY_SP}; diff --git a/src/librustc_ast_lowering/path.rs b/src/librustc_ast_lowering/path.rs index db8517bfbf0..b5b0a3089ce 100644 --- a/src/librustc_ast_lowering/path.rs +++ b/src/librustc_ast_lowering/path.rs @@ -1,7 +1,6 @@ use super::{AnonymousLifetimeMode, ImplTraitContext, LoweringContext, ParamMode}; use super::{GenericArgsCtor, ParenthesizedGenericArgs}; -use rustc::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; use rustc::span_bug; use rustc_ast::ast::{self, *}; use rustc_errors::{struct_span_err, Applicability}; @@ -9,6 +8,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, PartialRes, Res}; use rustc_hir::def_id::DefId; use rustc_hir::GenericArg; +use rustc_session::lint::builtin::ELIDED_LIFETIMES_IN_PATHS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::Span; diff --git a/src/librustc_codegen_llvm/attributes.rs b/src/librustc_codegen_llvm/attributes.rs index a9e4fdba030..072607fff85 100644 --- a/src/librustc_codegen_llvm/attributes.rs +++ b/src/librustc_codegen_llvm/attributes.rs @@ -3,8 +3,6 @@ use std::ffi::CString; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; -use rustc::session::config::{OptLevel, Sanitizer}; -use rustc::session::Session; use rustc::ty::layout::HasTyCtxt; use rustc::ty::query::Providers; use rustc::ty::{self, Ty, TyCtxt}; @@ -13,6 +11,8 @@ use rustc_data_structures::const_cstr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_session::config::{OptLevel, Sanitizer}; +use rustc_session::Session; use rustc_target::abi::call::Conv; use rustc_target::spec::PanicStrategy; diff --git a/src/librustc_codegen_llvm/back/archive.rs b/src/librustc_codegen_llvm/back/archive.rs index 455b7086212..239ca57ba41 100644 --- a/src/librustc_codegen_llvm/back/archive.rs +++ b/src/librustc_codegen_llvm/back/archive.rs @@ -9,9 +9,9 @@ use std::str; use crate::llvm::archive_ro::{ArchiveRO, Child}; use crate::llvm::{self, ArchiveKind}; -use rustc::session::Session; use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder}; use rustc_codegen_ssa::{looks_like_rust_object_file, METADATA_FILENAME, RLIB_BYTECODE_EXTENSION}; +use rustc_session::Session; use rustc_span::symbol::Symbol; struct ArchiveConfig<'a> { diff --git a/src/librustc_codegen_llvm/back/lto.rs b/src/librustc_codegen_llvm/back/lto.rs index 310cae978bf..1b64750f51f 100644 --- a/src/librustc_codegen_llvm/back/lto.rs +++ b/src/librustc_codegen_llvm/back/lto.rs @@ -9,7 +9,6 @@ use log::{debug, info}; use rustc::bug; use rustc::dep_graph::WorkProduct; use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::session::config::{self, Lto}; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared}; use rustc_codegen_ssa::back::symbol_export; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; @@ -19,6 +18,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{FatalError, Handler}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_session::cgu_reuse_tracker::CguReuse; +use rustc_session::config::{self, Lto}; use std::ffi::{CStr, CString}; use std::fs::File; diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index 0c243128104..2327b96e26c 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -15,8 +15,6 @@ use crate::LlvmCodegenBackend; use crate::ModuleLlvm; use log::debug; use rustc::bug; -use rustc::session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_codegen_ssa::back::write::{run_assembler, CodegenContext, ModuleConfig}; use rustc_codegen_ssa::traits::*; @@ -25,6 +23,8 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_errors::{FatalError, Handler}; use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_hir::def_id::LOCAL_CRATE; +use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath}; +use rustc_session::Session; use libc::{c_char, c_int, c_uint, c_void, size_t}; use std::ffi::CString; diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 04c084e459e..0d063d82c69 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -28,13 +28,13 @@ use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::exported_symbols; use rustc::mir::mono::{Linkage, Visibility}; -use rustc::session::config::DebugInfo; use rustc::ty::TyCtxt; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{ModuleCodegen, ModuleKind}; use rustc_data_structures::small_c_str::SmallCStr; +use rustc_session::config::DebugInfo; use rustc_span::symbol::Symbol; use std::ffi::CString; diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 1c5987f26f1..b37d63fce65 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -7,7 +7,6 @@ use crate::type_of::LayoutLlvmExt; use crate::value::Value; use libc::{c_char, c_uint}; use log::debug; -use rustc::session::config::{self, Sanitizer}; use rustc::ty::layout::{self, Align, Size, TyLayout}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_codegen_ssa::base::to_immediate; @@ -19,6 +18,7 @@ use rustc_codegen_ssa::MemFlags; use rustc_data_structures::const_cstr; use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; +use rustc_session::config::{self, Sanitizer}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; use std::ffi::CStr; diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index d9c88951440..7b1526e9da1 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -1,31 +1,30 @@ use crate::attributes; +use crate::callee::get_fn; use crate::debuginfo; use crate::llvm; use crate::llvm_util; -use crate::value::Value; -use rustc::dep_graph::DepGraphSafe; - use crate::type_::Type; -use rustc_codegen_ssa::traits::*; +use crate::value::Value; -use crate::callee::get_fn; use rustc::bug; +use rustc::dep_graph::DepGraphSafe; use rustc::mir::mono::CodegenUnit; -use rustc::session::config::{self, CFGuard, DebugInfo}; -use rustc::session::Session; use rustc::ty::layout::{ HasParamEnv, LayoutError, LayoutOf, PointeeInfo, Size, TyLayout, VariantIdx, }; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc_codegen_ssa::base::wants_msvc_seh; +use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::const_cstr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_target::spec::{HasTargetSpec, Target}; - +use rustc_session::config::{self, CFGuard, DebugInfo}; +use rustc_session::Session; use rustc_span::source_map::{Span, DUMMY_SP}; use rustc_span::symbol::Symbol; +use rustc_target::spec::{HasTargetSpec, Target}; + use std::cell::{Cell, RefCell}; use std::ffi::CStr; use std::str; diff --git a/src/librustc_codegen_llvm/debuginfo/gdb.rs b/src/librustc_codegen_llvm/debuginfo/gdb.rs index 753a4e18faf..e4cbffb6db3 100644 --- a/src/librustc_codegen_llvm/debuginfo/gdb.rs +++ b/src/librustc_codegen_llvm/debuginfo/gdb.rs @@ -6,8 +6,8 @@ use crate::builder::Builder; use crate::common::CodegenCx; use crate::value::Value; use rustc::bug; -use rustc::session::config::DebugInfo; use rustc_codegen_ssa::traits::*; +use rustc_session::config::DebugInfo; use rustc_ast::attr; use rustc_span::symbol::sym; diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 55eee13d028..6a7ed4e1dc3 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -24,7 +24,6 @@ use rustc::ich::NodeIdHashingMode; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::interpret::truncate; use rustc::mir::{self, Field, GeneratorLayout}; -use rustc::session::config::{self, DebugInfo}; use rustc::ty::layout::{ self, Align, Integer, IntegerExt, LayoutOf, PrimitiveExt, Size, TyLayout, VariantIdx, }; @@ -42,6 +41,7 @@ use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::{Interner, Symbol}; use rustc_span::{self, FileName, Span}; use rustc_target::abi::HasDataLayout; diff --git a/src/librustc_codegen_llvm/debuginfo/mod.rs b/src/librustc_codegen_llvm/debuginfo/mod.rs index bbde541c58f..85decff35b9 100644 --- a/src/librustc_codegen_llvm/debuginfo/mod.rs +++ b/src/librustc_codegen_llvm/debuginfo/mod.rs @@ -20,12 +20,12 @@ use crate::builder::Builder; use crate::common::CodegenCx; use crate::value::Value; use rustc::mir; -use rustc::session::config::{self, DebugInfo}; use rustc::ty::{self, Instance, ParamEnv, Ty}; use rustc_codegen_ssa::debuginfo::type_names; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::vec::IndexVec; +use rustc_session::config::{self, DebugInfo}; use libc::c_uint; use log::debug; diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs index f3265754574..fa730d289b1 100644 --- a/src/librustc_codegen_llvm/lib.rs +++ b/src/librustc_codegen_llvm/lib.rs @@ -15,31 +15,30 @@ #![recursion_limit = "256"] use back::write::{create_informational_target_machine, create_target_machine}; -use rustc_span::symbol::Symbol; pub use llvm_util::target_features; -use rustc::dep_graph::WorkProduct; +use rustc::dep_graph::{DepGraph, WorkProduct}; +use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; +use rustc::ty::{self, TyCtxt}; +use rustc::util::common::ErrorReported; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig}; use rustc_codegen_ssa::traits::*; +use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::{CodegenResults, CompiledModule}; +use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_errors::{FatalError, Handler}; +use rustc_serialize::json; +use rustc_session::config::{self, OptLevel, OutputFilenames, PrintRequest}; +use rustc_session::Session; +use rustc_span::symbol::Symbol; + use std::any::Any; use std::ffi::CStr; use std::fs; use std::sync::Arc; -use rustc::dep_graph::DepGraph; -use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest}; -use rustc::session::Session; -use rustc::ty::{self, TyCtxt}; -use rustc::util::common::ErrorReported; -use rustc_codegen_ssa::ModuleCodegen; -use rustc_codegen_utils::codegen_backend::CodegenBackend; -use rustc_serialize::json; - mod back { pub mod archive; pub mod bytecode; diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 388b6c74839..c17c06718f5 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -694,8 +694,8 @@ pub mod debuginfo { } impl DebugEmissionKind { - pub fn from_generic(kind: rustc::session::config::DebugInfo) -> Self { - use rustc::session::config::DebugInfo; + pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self { + use rustc_session::config::DebugInfo; match kind { DebugInfo::None => DebugEmissionKind::NoDebug, DebugInfo::Limited => DebugEmissionKind::LineTablesOnly, diff --git a/src/librustc_codegen_llvm/llvm_util.rs b/src/librustc_codegen_llvm/llvm_util.rs index 0081a75a4da..5e924c9af84 100644 --- a/src/librustc_codegen_llvm/llvm_util.rs +++ b/src/librustc_codegen_llvm/llvm_util.rs @@ -2,10 +2,10 @@ use crate::back::write::create_informational_target_machine; use crate::llvm; use libc::c_int; use rustc::bug; -use rustc::session::config::PrintRequest; -use rustc::session::Session; use rustc_data_structures::fx::FxHashSet; use rustc_feature::UnstableFeatures; +use rustc_session::config::PrintRequest; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::symbol::Symbol; use rustc_target::spec::{MergeFunctions, PanicStrategy}; diff --git a/src/librustc_codegen_ssa/back/archive.rs b/src/librustc_codegen_ssa/back/archive.rs index a357c350287..f83b4b2b0c0 100644 --- a/src/librustc_codegen_ssa/back/archive.rs +++ b/src/librustc_codegen_ssa/back/archive.rs @@ -1,4 +1,4 @@ -use rustc::session::Session; +use rustc_session::Session; use rustc_span::symbol::Symbol; use std::io; diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index a4eef2374c2..6c26dd0c52f 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1,15 +1,15 @@ use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; -use rustc::session::config::{ +use rustc_data_structures::fx::FxHashSet; +use rustc_fs_util::fix_windows_verbatim_for_gcc; +use rustc_hir::def_id::CrateNum; +use rustc_session::config::{ self, CFGuard, DebugInfo, OutputFilenames, OutputType, PrintRequest, Sanitizer, }; -use rustc::session::search_paths::PathKind; +use rustc_session::search_paths::PathKind; /// For all the linkers we support, and information they might /// need out of the shared crate context before we get rid of it. -use rustc::session::{filesearch, Session}; -use rustc_data_structures::fx::FxHashSet; -use rustc_fs_util::fix_windows_verbatim_for_gcc; -use rustc_hir::def_id::CrateNum; +use rustc_session::{filesearch, Session}; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel}; diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs index 5aafb8a12d7..6b30ae8559d 100644 --- a/src/librustc_codegen_ssa/back/linker.rs +++ b/src/librustc_codegen_ssa/back/linker.rs @@ -2,7 +2,6 @@ use super::archive; use super::command::Command; use super::symbol_export; -use rustc_data_structures::fx::FxHashMap; use std::ffi::{OsStr, OsString}; use std::fs::{self, File}; use std::io::prelude::*; @@ -10,11 +9,12 @@ use std::io::{self, BufWriter}; use std::path::{Path, PathBuf}; use rustc::middle::dependency_format::Linkage; -use rustc::session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel}; -use rustc::session::Session; use rustc::ty::TyCtxt; +use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_serialize::{json, Encoder}; +use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel}; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_target::spec::{LinkerFlavor, LldFlavor}; diff --git a/src/librustc_codegen_ssa/back/symbol_export.rs b/src/librustc_codegen_ssa/back/symbol_export.rs index 3fe256ce25b..b86f55b6591 100644 --- a/src/librustc_codegen_ssa/back/symbol_export.rs +++ b/src/librustc_codegen_ssa/back/symbol_export.rs @@ -3,7 +3,6 @@ use std::sync::Arc; use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::middle::exported_symbols::{metadata_symbol_name, ExportedSymbol, SymbolExportLevel}; -use rustc::session::config::{self, Sanitizer}; use rustc::ty::query::Providers; use rustc::ty::subst::{GenericArgKind, SubstsRef}; use rustc::ty::Instance; @@ -16,6 +15,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::Node; use rustc_index::vec::IndexVec; +use rustc_session::config::{self, Sanitizer}; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { crates_export_threshold(&tcx.sess.crate_types.borrow()) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index dbc2ef6f2b0..303ee385658 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -14,10 +14,6 @@ use jobserver::{Acquired, Client}; use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; use rustc::middle::cstore::EncodedMetadata; use rustc::middle::exported_symbols::SymbolExportLevel; -use rustc::session::config::{ - self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath, -}; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_ast::attr; use rustc_data_structures::fx::FxHashMap; @@ -34,6 +30,10 @@ use rustc_incremental::{ copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; use rustc_session::cgu_reuse_tracker::CguReuseTracker; +use rustc_session::config::{ + self, Lto, OutputFilenames, OutputType, Passes, Sanitizer, SwitchWithOptPath, +}; +use rustc_session::Session; use rustc_span::hygiene::ExpnId; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{sym, Symbol}; diff --git a/src/librustc_codegen_ssa/base.rs b/src/librustc_codegen_ssa/base.rs index d6e1ab8909c..e57cae30b77 100644 --- a/src/librustc_codegen_ssa/base.rs +++ b/src/librustc_codegen_ssa/base.rs @@ -31,8 +31,6 @@ use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::lang_items; use rustc::middle::lang_items::StartFnLangItem; use rustc::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem}; -use rustc::session::config::{self, EntryFnType, Lto}; -use rustc::session::Session; use rustc::ty::layout::{self, Align, HasTyCtxt, LayoutOf, TyLayout, VariantIdx}; use rustc::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA}; use rustc::ty::query::Providers; @@ -46,6 +44,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::Idx; use rustc_session::cgu_reuse_tracker::CguReuse; +use rustc_session::config::{self, EntryFnType, Lto}; +use rustc_session::Session; use rustc_span::Span; use std::cmp; diff --git a/src/librustc_codegen_ssa/common.rs b/src/librustc_codegen_ssa/common.rs index 28b61e0b36d..147b2399502 100644 --- a/src/librustc_codegen_ssa/common.rs +++ b/src/librustc_codegen_ssa/common.rs @@ -1,8 +1,8 @@ #![allow(non_camel_case_types, non_snake_case)] -use rustc::session::Session; use rustc::ty::{Ty, TyCtxt}; use rustc_errors::struct_span_err; +use rustc_session::Session; use rustc_span::Span; use crate::base; diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs index a2bb39b9e40..d2afbdc23e1 100644 --- a/src/librustc_codegen_ssa/lib.rs +++ b/src/librustc_codegen_ssa/lib.rs @@ -21,12 +21,12 @@ use rustc::dep_graph::WorkProduct; use rustc::middle::cstore::{CrateSource, LibSource, NativeLibrary}; use rustc::middle::dependency_format::Dependencies; use rustc::middle::lang_items::LangItem; -use rustc::session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc::ty::query::Providers; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_hir::def_id::CrateNum; +use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT}; use rustc_span::symbol::Symbol; use std::path::{Path, PathBuf}; diff --git a/src/librustc_codegen_ssa/mir/debuginfo.rs b/src/librustc_codegen_ssa/mir/debuginfo.rs index 2dc1405f4e4..cbe5f511152 100644 --- a/src/librustc_codegen_ssa/mir/debuginfo.rs +++ b/src/librustc_codegen_ssa/mir/debuginfo.rs @@ -1,10 +1,10 @@ use crate::traits::*; use rustc::mir; -use rustc::session::config::DebugInfo; use rustc::ty; use rustc::ty::layout::{LayoutOf, Size}; use rustc_hir::def_id::CrateNum; use rustc_index::vec::IndexVec; +use rustc_session::config::DebugInfo; use rustc_span::symbol::{kw, Symbol}; use rustc_span::{BytePos, Span}; diff --git a/src/librustc_codegen_ssa/traits/backend.rs b/src/librustc_codegen_ssa/traits/backend.rs index 5535841156a..7acae300a2f 100644 --- a/src/librustc_codegen_ssa/traits/backend.rs +++ b/src/librustc_codegen_ssa/traits/backend.rs @@ -3,12 +3,12 @@ use super::CodegenObject; use crate::ModuleCodegen; use rustc::middle::cstore::EncodedMetadata; -use rustc::session::{config, Session}; use rustc::ty::layout::{HasTyCtxt, LayoutOf, TyLayout}; use rustc::ty::Ty; use rustc::ty::TyCtxt; use rustc_ast::expand::allocator::AllocatorKind; use rustc_codegen_utils::codegen_backend::CodegenBackend; +use rustc_session::{config, Session}; use rustc_span::symbol::Symbol; use std::sync::Arc; diff --git a/src/librustc_codegen_ssa/traits/misc.rs b/src/librustc_codegen_ssa/traits/misc.rs index d7587163ba0..6863b474cb6 100644 --- a/src/librustc_codegen_ssa/traits/misc.rs +++ b/src/librustc_codegen_ssa/traits/misc.rs @@ -1,8 +1,8 @@ use super::BackendTypes; use rustc::mir::mono::CodegenUnit; -use rustc::session::Session; use rustc::ty::{self, Instance, Ty}; use rustc_data_structures::fx::FxHashMap; +use rustc_session::Session; use std::cell::RefCell; use std::sync::Arc; diff --git a/src/librustc_codegen_utils/Cargo.toml b/src/librustc_codegen_utils/Cargo.toml index b5533a8307c..7ab59029bc8 100644 --- a/src/librustc_codegen_utils/Cargo.toml +++ b/src/librustc_codegen_utils/Cargo.toml @@ -21,3 +21,4 @@ rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_metadata = { path = "../librustc_metadata" } +rustc_session = { path = "../librustc_session" } diff --git a/src/librustc_codegen_utils/codegen_backend.rs b/src/librustc_codegen_utils/codegen_backend.rs index 96166e04c2e..561692e7066 100644 --- a/src/librustc_codegen_utils/codegen_backend.rs +++ b/src/librustc_codegen_utils/codegen_backend.rs @@ -10,11 +10,11 @@ use std::any::Any; use rustc::dep_graph::DepGraph; use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; -use rustc::session::config::{OutputFilenames, PrintRequest}; -use rustc::session::Session; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; +use rustc_session::config::{OutputFilenames, PrintRequest}; +use rustc_session::Session; use rustc_span::symbol::Symbol; pub use rustc_data_structures::sync::MetadataRef; diff --git a/src/librustc_codegen_utils/link.rs b/src/librustc_codegen_utils/link.rs index 524fb0a59c2..ad6ba7e6837 100644 --- a/src/librustc_codegen_utils/link.rs +++ b/src/librustc_codegen_utils/link.rs @@ -1,6 +1,6 @@ -use rustc::session::config::{self, Input, OutputFilenames, OutputType}; -use rustc::session::Session; use rustc_ast::{ast, attr}; +use rustc_session::config::{self, Input, OutputFilenames, OutputType}; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; use std::path::{Path, PathBuf}; diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index cfde09fad62..eb3fe49a5e9 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -89,12 +89,12 @@ use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::mono::{InstantiationMode, MonoItem}; -use rustc::session::config::SymbolManglingVersion; use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Instance, TyCtxt}; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_hir::Node; +use rustc_session::config::SymbolManglingVersion; use rustc_span::symbol::Symbol; diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 26f1741153c..3e644958231 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -33,6 +33,7 @@ rustc_interface = { path = "../librustc_interface" } rustc_serialize = { path = "../libserialize", package = "serialize" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } +rustc_session = { path = "../librustc_session" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["consoleapi", "debugapi", "processenv"] } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 8acb2260cbe..34f0c182499 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -18,12 +18,7 @@ extern crate lazy_static; pub extern crate rustc_plugin_impl as plugin; -use rustc::lint::{Lint, LintId}; use rustc::middle::cstore::MetadataLoader; -use rustc::session::config::nightly_options; -use rustc::session::config::{ErrorOutputType, Input, OutputType, PrintRequest}; -use rustc::session::{config, DiagnosticOutput, Session}; -use rustc::session::{early_error, early_warn}; use rustc::ty::TyCtxt; use rustc::util::common::ErrorReported; use rustc_codegen_ssa::CodegenResults; @@ -43,6 +38,11 @@ use rustc_metadata::locator; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; use rustc_serialize::json::{self, ToJson}; +use rustc_session::config::nightly_options; +use rustc_session::config::{ErrorOutputType, Input, OutputType, PrintRequest}; +use rustc_session::lint::{Lint, LintId}; +use rustc_session::{config, DiagnosticOutput, Session}; +use rustc_session::{early_error, early_warn}; use std::borrow::Cow; use std::cmp::max; @@ -652,7 +652,7 @@ impl RustcDefaultCalls { odir: &Option, ofile: &Option, ) -> Compilation { - use rustc::session::config::PrintRequest::*; + use rustc_session::config::PrintRequest::*; // PrintRequest::NativeStaticLibs is special - printed during linking // (empty iterator returns true) if sess.opts.prints.iter().all(|&p| p == PrintRequest::NativeStaticLibs) { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 2361046c036..1e5cc55a828 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -1,8 +1,6 @@ //! The various pretty-printing routines. use rustc::hir::map as hir_map; -use rustc::session::config::{Input, PpMode, PpSourceMode}; -use rustc::session::Session; use rustc::ty::{self, TyCtxt}; use rustc::util::common::ErrorReported; use rustc_ast::ast; @@ -11,6 +9,8 @@ use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::print as pprust_hir; use rustc_mir::util::{write_mir_graphviz, write_mir_pretty}; +use rustc_session::config::{Input, PpMode, PpSourceMode}; +use rustc_session::Session; use rustc_span::FileName; use std::cell::Cell; diff --git a/src/librustc_errors/emitter.rs b/src/librustc_errors/emitter.rs index 03f83e61636..26f1fa267f9 100644 --- a/src/librustc_errors/emitter.rs +++ b/src/librustc_errors/emitter.rs @@ -5,7 +5,7 @@ //! There are various `Emitter` implementations that generate different output formats such as //! JSON and human readable output. //! -//! The output types are defined in `librustc::session::config::ErrorOutputType`. +//! The output types are defined in `rustc_session::config::ErrorOutputType`. use Destination::*; diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 5c72b049d97..048a81b81ba 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -14,8 +14,8 @@ use std::fs; use std::io::{self, Read}; use std::path::Path; -use rustc::session::config::nightly_options; use rustc_serialize::opaque::Encoder; +use rustc_session::config::nightly_options; /// The first few bytes of files generated by incremental compilation. const FILE_MAGIC: &[u8] = b"RSIC"; diff --git a/src/librustc_incremental/persist/fs.rs b/src/librustc_incremental/persist/fs.rs index 8548ad392d2..4926f726f35 100644 --- a/src/librustc_incremental/persist/fs.rs +++ b/src/librustc_incremental/persist/fs.rs @@ -103,11 +103,11 @@ //! unsupported file system and emit a warning in that case. This is not yet //! implemented. -use rustc::session::{CrateDisambiguator, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; use rustc_fs_util::{link_or_copy, LinkOrCopy}; +use rustc_session::{CrateDisambiguator, Session}; use std::fs as std_fs; use std::io; diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 6c57f79e1a7..8a11586250d 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -1,12 +1,12 @@ //! Code to save/load the dep-graph from files. use rustc::dep_graph::{PreviousDepGraph, SerializedDepGraph, WorkProduct, WorkProductId}; -use rustc::session::Session; use rustc::ty::query::OnDiskCache; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_serialize::opaque::Decoder; use rustc_serialize::Decodable as RustcDecodable; +use rustc_session::Session; use std::path::Path; use super::data::*; diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 87f39dedd02..b465a11c99c 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -1,10 +1,10 @@ use rustc::dep_graph::{DepGraph, DepKind, WorkProduct, WorkProductId}; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::join; use rustc_serialize::opaque::Encoder; use rustc_serialize::Encodable as RustcEncodable; +use rustc_session::Session; use std::fs; use std::path::PathBuf; diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index b1861acec04..aa3588b284b 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -2,8 +2,8 @@ use crate::persist::fs::*; use rustc::dep_graph::{WorkProduct, WorkProductFileKind, WorkProductId}; -use rustc::session::Session; use rustc_fs_util::link_or_copy; +use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; diff --git a/src/librustc_infer/Cargo.toml b/src/librustc_infer/Cargo.toml index 4f97fd82874..9ecd056430c 100644 --- a/src/librustc_infer/Cargo.toml +++ b/src/librustc_infer/Cargo.toml @@ -18,6 +18,7 @@ rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_index = { path = "../librustc_index" } rustc_macros = { path = "../librustc_macros" } +rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } rustc_target = { path = "../librustc_target" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 9ae131c568d..a90ff673e46 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -5,7 +5,6 @@ pub use self::LateBoundRegionConversionTime::*; pub use self::RegionVariableOrigin::*; pub use self::SubregionOrigin::*; pub use self::ValuePairs::*; -pub use rustc::ty::IntVarValue; use crate::traits::{self, ObligationCause, PredicateObligations, TraitEngine}; @@ -16,15 +15,14 @@ use rustc::middle::free_region::RegionRelations; use rustc::middle::region; use rustc::mir; use rustc::mir::interpret::ConstEvalResult; -use rustc::session::config::BorrowckMode; use rustc::traits::select; use rustc::ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric}; use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::relate::RelateResult; use rustc::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; +pub use rustc::ty::IntVarValue; use rustc::ty::{self, GenericParamDefKind, InferConst, Ty, TyCtxt}; use rustc::ty::{ConstVid, FloatVid, IntVid, TyVid}; - use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::sync::Lrc; @@ -32,8 +30,10 @@ use rustc_data_structures::unify as ut; use rustc_errors::DiagnosticBuilder; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_session::config::BorrowckMode; use rustc_span::symbol::Symbol; use rustc_span::Span; + use std::cell::{Cell, Ref, RefCell}; use std::collections::BTreeMap; use std::fmt; diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index e15217dfa67..c5ebcf0696f 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -1,10 +1,6 @@ pub use crate::passes::BoxedResolver; use crate::util; -use rustc::lint; -use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames}; -use rustc::session::early_error; -use rustc::session::{DiagnosticOutput, Session}; use rustc::ty; use rustc::util::common::ErrorReported; use rustc_ast::ast::{self, MetaItemKind}; @@ -16,7 +12,11 @@ use rustc_data_structures::OnDrop; use rustc_errors::registry::Registry; use rustc_lint::LintStore; use rustc_parse::new_parser_from_source_str; +use rustc_session::config::{self, ErrorOutputType, Input, OutputFilenames}; +use rustc_session::early_error; +use rustc_session::lint; use rustc_session::parse::{CrateConfig, ParseSess}; +use rustc_session::{DiagnosticOutput, Session}; use rustc_span::edition; use rustc_span::source_map::{FileLoader, FileName, SourceMap}; use std::path::PathBuf; diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 4fe7a06e560..e736628416f 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -6,13 +6,8 @@ use log::{info, log_enabled, warn}; use rustc::arena::Arena; use rustc::dep_graph::DepGraph; use rustc::hir::map::Definitions; -use rustc::lint; use rustc::middle; use rustc::middle::cstore::{CrateStore, MetadataLoader, MetadataLoaderDyn}; -use rustc::session::config::{self, CrateType, Input, OutputFilenames, OutputType}; -use rustc::session::config::{PpMode, PpSourceMode}; -use rustc::session::search_paths::PathKind; -use rustc::session::Session; use rustc::ty::steal::Steal; use rustc::ty::{self, GlobalCtxt, ResolverOutputs, TyCtxt}; use rustc::util::common::ErrorReported; @@ -34,6 +29,11 @@ use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str}; use rustc_passes::{self, hir_stats, layout_test}; use rustc_plugin_impl as plugin; use rustc_resolve::{Resolver, ResolverArenas}; +use rustc_session::config::{self, CrateType, Input, OutputFilenames, OutputType}; +use rustc_session::config::{PpMode, PpSourceMode}; +use rustc_session::lint; +use rustc_session::search_paths::PathKind; +use rustc_session::Session; use rustc_span::symbol::Symbol; use rustc_span::FileName; use rustc_trait_selection::traits; diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 426d97cc09b..3514829dca7 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -3,8 +3,6 @@ use crate::passes::{self, BoxedResolver, QueryContext}; use rustc::arena::Arena; use rustc::dep_graph::DepGraph; -use rustc::session::config::{OutputFilenames, OutputType}; -use rustc::session::Session; use rustc::ty::steal::Steal; use rustc::ty::{GlobalCtxt, ResolverOutputs}; use rustc::util::common::ErrorReported; @@ -15,6 +13,8 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::Crate; use rustc_incremental::DepGraphFuture; use rustc_lint::LintStore; +use rustc_session::config::{OutputFilenames, OutputType}; +use rustc_session::Session; use std::any::Any; use std::cell::{Ref, RefCell, RefMut}; use std::mem; diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 1b80cf4e3db..db5ada92914 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -2,16 +2,16 @@ extern crate getopts; use crate::interface::parse_cfgspecs; -use rustc::lint::Level; use rustc::middle::cstore; -use rustc::session::config::{build_configuration, build_session_options, to_crate_config}; -use rustc::session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; -use rustc::session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; -use rustc::session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; -use rustc::session::search_paths::SearchPath; -use rustc::session::{build_session, Session}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig}; +use rustc_session::config::{build_configuration, build_session_options, to_crate_config}; +use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes}; +use rustc_session::config::{ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath}; +use rustc_session::config::{Externs, OutputType, OutputTypes, SymbolManglingVersion}; +use rustc_session::lint::Level; +use rustc_session::search_paths::SearchPath; +use rustc_session::{build_session, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index df05bd7c511..26e854ee69f 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -1,5 +1,4 @@ use log::info; -use rustc::lint; use rustc::ty; use rustc_ast::ast::{AttrVec, BlockCheckMode}; use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; @@ -18,7 +17,7 @@ use rustc_metadata::dynamic_lib::DynamicLibrary; use rustc_resolve::{self, Resolver}; use rustc_session as session; use rustc_session::config::{ErrorOutputType, Input, OutputFilenames}; -use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; +use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; use rustc_session::CrateDisambiguator; use rustc_session::{config, early_error, filesearch, DiagnosticOutput, Session}; diff --git a/src/librustc_metadata/Cargo.toml b/src/librustc_metadata/Cargo.toml index a8e308c5c9e..088cba83ef9 100644 --- a/src/librustc_metadata/Cargo.toml +++ b/src/librustc_metadata/Cargo.toml @@ -26,6 +26,7 @@ stable_deref_trait = "1.0.0" rustc_ast = { path = "../librustc_ast" } rustc_expand = { path = "../librustc_expand" } rustc_span = { path = "../librustc_span" } +rustc_session = { path = "../librustc_session" } [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["errhandlingapi", "libloaderapi"] } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 18b4c9ad504..9616e1249dc 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -6,19 +6,18 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob use rustc::hir::map::Definitions; use rustc::middle::cstore::DepKind; use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}; -use rustc::session::config; -use rustc::session::search_paths::PathKind; -use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::TyCtxt; -use rustc_ast::ast; -use rustc_ast::attr; use rustc_ast::expand::allocator::{global_allocator_spans, AllocatorKind}; +use rustc_ast::{ast, attr}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_index::vec::IndexVec; +use rustc_session::config; +use rustc_session::search_paths::PathKind; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; diff --git a/src/librustc_metadata/dependency_format.rs b/src/librustc_metadata/dependency_format.rs index 9e71839dbfd..2eff07b2eb2 100644 --- a/src/librustc_metadata/dependency_format.rs +++ b/src/librustc_metadata/dependency_format.rs @@ -56,10 +56,10 @@ use crate::creader::CStore; use rustc::middle::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic}; use rustc::middle::cstore::{self, DepKind}; use rustc::middle::dependency_format::{Dependencies, DependencyList, Linkage}; -use rustc::session::config; use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::CrateNum; +use rustc_session::config; use rustc_target::spec::PanicStrategy; crate fn calculate(tcx: TyCtxt<'_>) -> Dependencies { diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index d4cc3c32616..e401dc0f6e7 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -31,7 +31,7 @@ pub mod dynamic_lib; pub mod locator; pub fn validate_crate_name( - sess: Option<&rustc::session::Session>, + sess: Option<&rustc_session::Session>, s: &str, sp: Option, ) { diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index efa259d0c4e..1ede629e7ef 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -216,13 +216,13 @@ use crate::creader::Library; use crate::rmeta::{rustc_version, MetadataBlob, METADATA_HEADER}; use rustc::middle::cstore::{CrateSource, MetadataLoader}; -use rustc::session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; -use rustc::session::search_paths::PathKind; -use rustc::session::{config, CrateDisambiguator, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::MetadataRef; use rustc_errors::{struct_span_err, DiagnosticBuilder}; +use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; +use rustc_session::search_paths::PathKind; +use rustc_session::{config, CrateDisambiguator, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index 2fa9cb099dd..64bbf393ba0 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -1,12 +1,12 @@ use rustc::middle::cstore::{self, NativeLibrary}; -use rustc::session::parse::feature_err; -use rustc::session::Session; use rustc::ty::TyCtxt; use rustc_attr as attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::itemlikevisit::ItemLikeVisitor; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::source_map::Span; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::spec::abi::Abi; diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 7126f86c326..ff4f4bc901a 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -14,36 +14,35 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use rustc::mir::{self, interpret, BodyAndCache, Promoted}; -use rustc::session::Session; use rustc::ty::codec::TyDecoder; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::common::record_time; +use rustc_ast::ast::{self, Ident}; +use rustc_attr as attr; use rustc_data_structures::captures::Captures; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AtomicCell, Lock, LockGuard, Lrc, Once}; +use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder}; +use rustc_session::Session; +use rustc_span::source_map::{self, respan, Spanned}; +use rustc_span::symbol::{sym, Symbol}; +use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP}; +use log::debug; +use proc_macro::bridge::client::ProcMacro; use std::io; use std::mem; use std::num::NonZeroUsize; use std::u32; -use log::debug; -use proc_macro::bridge::client::ProcMacro; -use rustc_ast::ast::{self, Ident}; -use rustc_attr as attr; -use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; -use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, ProcMacroDerive}; -use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder}; -use rustc_span::source_map::{self, respan, Spanned}; -use rustc_span::symbol::{sym, Symbol}; -use rustc_span::{self, hygiene::MacroKind, BytePos, Pos, Span, DUMMY_SP}; - pub use cstore_impl::{provide, provide_extern}; mod cstore_impl; diff --git a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs index d87e24eeed1..cc2bd51f92f 100644 --- a/src/librustc_metadata/rmeta/decoder/cstore_impl.rs +++ b/src/librustc_metadata/rmeta/decoder/cstore_impl.rs @@ -10,7 +10,6 @@ use rustc::hir::map::{DefKey, DefPath, DefPathHash}; use rustc::middle::cstore::{CrateSource, CrateStore, EncodedMetadata, NativeLibraryKind}; use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; -use rustc::session::{CrateDisambiguator, Session}; use rustc::ty::query::Providers; use rustc::ty::query::QueryConfig; use rustc::ty::{self, TyCtxt}; @@ -20,6 +19,7 @@ use rustc_ast::expand::allocator::AllocatorKind; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::{self, Span, Spanned}; use rustc_span::symbol::Symbol; diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 8b589f70651..40a50dcdae2 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -12,33 +12,31 @@ use rustc::traits::specialization_graph; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; use rustc::ty::{self, SymbolName, Ty, TyCtxt}; +use rustc_ast::ast; +use rustc_ast::attr; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::Lrc; +use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{AnonConst, GenericParamKind}; use rustc_index::vec::Idx; - -use rustc::session::config::{self, CrateType}; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::stable_hasher::StableHasher; -use rustc_data_structures::sync::Lrc; use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; - -use log::{debug, trace}; -use rustc_ast::ast; -use rustc_ast::attr; +use rustc_session::config::{self, CrateType}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{self, FileName, SourceFile, Span}; + +use log::{debug, trace}; use std::hash::Hash; use std::num::NonZeroUsize; use std::path::Path; use std::u32; -use rustc_hir as hir; -use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; -use rustc_hir::itemlikevisit::ItemLikeVisitor; - struct EncodeContext<'tcx> { opaque: opaque::Encoder, tcx: TyCtxt<'tcx>, diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index 152bb257fa2..bd2d9915393 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -7,8 +7,6 @@ use rustc::middle::cstore::{DepKind, ForeignModule, LinkagePreference, NativeLib use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; -use rustc::session::config::SymbolManglingVersion; -use rustc::session::CrateDisambiguator; use rustc::ty::{self, ReprOptions, Ty}; use rustc_ast::ast::{self, MacroDef}; use rustc_attr as attr; @@ -19,6 +17,8 @@ use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, DefIndex}; use rustc_index::vec::IndexVec; use rustc_serialize::opaque::Encoder; +use rustc_session::config::SymbolManglingVersion; +use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; use rustc_span::symbol::Symbol; use rustc_span::{self, Span}; diff --git a/src/librustc_mir/Cargo.toml b/src/librustc_mir/Cargo.toml index cad50d50f3c..256a80076b9 100644 --- a/src/librustc_mir/Cargo.toml +++ b/src/librustc_mir/Cargo.toml @@ -27,6 +27,7 @@ rustc_infer = { path = "../librustc_infer" } rustc_lexer = { path = "../librustc_lexer" } rustc_macros = { path = "../librustc_macros" } rustc_serialize = { path = "../libserialize", package = "serialize" } +rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } rustc_trait_selection = { path = "../librustc_trait_selection" } rustc_ast = { path = "../librustc_ast" } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index a61d00b0120..6c1901455fd 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1,7 +1,5 @@ //! This query borrow-checks the MIR to (further) ensure it is not broken. -use rustc::lint::builtin::MUTABLE_BORROW_RESERVATION_CONFLICT; -use rustc::lint::builtin::UNUSED_MUT; use rustc::mir::{ read_only, traversal, Body, BodyAndCache, ClearCrossCrate, Local, Location, Mutability, Operand, Place, PlaceElem, PlaceRef, ReadOnlyBodyAndCache, @@ -11,7 +9,7 @@ use rustc::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKi use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, RegionVid, TyCtxt}; - +use rustc_ast::ast::Name; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder}; @@ -20,6 +18,8 @@ use rustc_hir::{def_id::DefId, HirId, Node}; use rustc_index::bit_set::BitSet; use rustc_index::vec::IndexVec; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT}; +use rustc_span::{Span, DUMMY_SP}; use either::Either; use smallvec::SmallVec; @@ -28,9 +28,6 @@ use std::collections::BTreeMap; use std::mem; use std::rc::Rc; -use rustc_ast::ast::Name; -use rustc_span::{Span, DUMMY_SP}; - use crate::dataflow; use crate::dataflow::generic::{Analysis, BorrowckFlowState as Flows, BorrowckResults}; use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathIndex}; diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index b4e33b9502e..dd0f9ff75b9 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -1,16 +1,14 @@ +use rustc::mir::traversal; +use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator}; +use rustc::ty::{self, TyCtxt}; use rustc_ast::ast::{self, MetaItem}; use rustc_ast_pretty::pprust; -use rustc_span::symbol::{sym, Symbol}; - use rustc_data_structures::work_queue::WorkQueue; +use rustc_hir::def_id::DefId; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_index::vec::Idx; - -use rustc::mir::traversal; -use rustc::mir::{self, BasicBlock, BasicBlockData, Body, Location, Statement, Terminator}; -use rustc::session::Session; -use rustc::ty::{self, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc_session::Session; +use rustc_span::symbol::{sym, Symbol}; use std::borrow::Borrow; use std::fmt; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 862a7ef1e73..c37ad815760 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -183,7 +183,6 @@ use rustc::mir::interpret::{ErrorHandled, GlobalAlloc, Scalar}; use rustc::mir::mono::{InstantiationMode, MonoItem}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::{self, Local, Location}; -use rustc::session::config::EntryFnType; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::subst::{InternalSubsts, SubstsRef}; @@ -194,6 +193,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_index::bit_set::GrowableBitSet; +use rustc_session::config::EntryFnType; use smallvec::SmallVec; use std::iter; diff --git a/src/librustc_mir/transform/check_consts/ops.rs b/src/librustc_mir/transform/check_consts/ops.rs index d06a2aa44f2..af7af7388bd 100644 --- a/src/librustc_mir/transform/check_consts/ops.rs +++ b/src/librustc_mir/transform/check_consts/ops.rs @@ -1,9 +1,9 @@ //! Concrete error types for all operations which may be invalid in a certain const context. -use rustc::session::config::nightly_options; -use rustc::session::parse::feature_err; use rustc_errors::struct_span_err; use rustc_hir::def_id::DefId; +use rustc_session::config::nightly_options; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{Span, Symbol}; diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 78440c8437d..437a154a9b8 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -1,4 +1,3 @@ -use rustc::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc::mir::*; use rustc::ty::cast::CastTy; @@ -10,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::Node; +use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE}; use rustc_span::symbol::{sym, Symbol}; use std::ops::Bound; diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 289b198d2c9..ca23c44f646 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -4,7 +4,6 @@ use std::borrow::Cow; use std::cell::Cell; -use rustc::lint; use rustc::mir::interpret::{InterpResult, Scalar}; use rustc::mir::visit::{ MutVisitor, MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor, @@ -25,6 +24,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::HirId; use rustc_index::vec::IndexVec; +use rustc_session::lint; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index 5dec2c6df99..795bcb57d06 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -8,8 +8,8 @@ use std::io; use crate::transform::{MirPass, MirSource}; use crate::util as mir_util; use rustc::mir::{Body, BodyAndCache}; -use rustc::session::config::{OutputFilenames, OutputType}; use rustc::ty::TyCtxt; +use rustc_session::config::{OutputFilenames, OutputType}; pub struct Marker(pub &'static str); diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index b6802505df7..769f3fdcc01 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -1,25 +1,22 @@ //! Inlining pass for MIR functions -use rustc_hir::def_id::DefId; - -use rustc_index::bit_set::BitSet; -use rustc_index::vec::{Idx, IndexVec}; - use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc::mir::visit::*; use rustc::mir::*; -use rustc::session::config::Sanitizer; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeFoldable}; +use rustc_attr as attr; +use rustc_hir::def_id::DefId; +use rustc_index::bit_set::BitSet; +use rustc_index::vec::{Idx, IndexVec}; +use rustc_session::config::Sanitizer; +use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; use crate::transform::{MirPass, MirSource}; use std::collections::VecDeque; use std::iter; -use rustc_attr as attr; -use rustc_target::spec::abi::Abi; - const DEFAULT_THRESHOLD: usize = 50; const HINT_THRESHOLD: usize = 100; diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 37ad5f5ea4e..a71f56154db 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -235,17 +235,15 @@ use rustc_index::vec::Idx; use super::{compare_const_vals, PatternFoldable, PatternFolder}; use super::{FieldPat, Pat, PatKind, PatRange}; -use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx}; -use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; -use rustc_hir::def_id::DefId; -use rustc_hir::{HirId, RangeEnd}; - -use rustc::lint; use rustc::mir::interpret::{truncate, AllocId, ConstValue, Pointer, Scalar}; use rustc::mir::Field; +use rustc::ty::layout::{Integer, IntegerExt, Size, VariantIdx}; +use rustc::ty::{self, Const, Ty, TyCtxt, TypeFoldable, VariantDef}; use rustc::util::common::ErrorReported; - use rustc_attr::{SignedInt, UnsignedInt}; +use rustc_hir::def_id::DefId; +use rustc_hir::{HirId, RangeEnd}; +use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; use arena::TypedArena; diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 214e75fbdde..ae951e810e3 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -1,16 +1,14 @@ -use rustc::lint; use rustc::mir::Field; use rustc::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; +use rustc_index::vec::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_session::lint; +use rustc_span::Span; use rustc_trait_selection::traits::predicate_for_trait_def; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, PredicateObligation}; -use rustc_index::vec::Idx; - -use rustc_span::Span; - use std::cell::Cell; use super::{FieldPat, Pat, PatCtxt, PatKind}; @@ -182,7 +180,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { let kind = match cv.ty.kind { ty::Float(_) => { tcx.struct_span_lint_hir( - ::rustc::lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, + lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN, id, span, |lint| lint.build("floating-point types cannot be used in patterns").emit(), diff --git a/src/librustc_mir_build/lints.rs b/src/librustc_mir_build/lints.rs index 0017f800de7..8b1ddf7461a 100644 --- a/src/librustc_mir_build/lints.rs +++ b/src/librustc_mir_build/lints.rs @@ -1,11 +1,11 @@ use rustc::hir::map::blocks::FnLikeNode; -use rustc::lint::builtin::UNCONDITIONAL_RECURSION; use rustc::mir::{self, Body, TerminatorKind}; use rustc::ty::subst::InternalSubsts; use rustc::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::FnKind; use rustc_index::bit_set::BitSet; +use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; crate fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); diff --git a/src/librustc_passes/check_const.rs b/src/librustc_passes/check_const.rs index af06fc0c002..30737360b9c 100644 --- a/src/librustc_passes/check_const.rs +++ b/src/librustc_passes/check_const.rs @@ -8,8 +8,6 @@ //! through, but errors for structured control flow in a `const` should be emitted here. use rustc::hir::map::Map; -use rustc::session::config::nightly_options; -use rustc::session::parse::feature_err; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::ast::Mutability; @@ -17,6 +15,8 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; +use rustc_session::config::nightly_options; +use rustc_session::parse::feature_err; use rustc_span::{sym, Span, Symbol}; use std::fmt; diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index 2cabe786d0c..598d6bb3c48 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -1,6 +1,4 @@ use rustc::hir::map::Map; -use rustc::session::config::EntryFnType; -use rustc::session::{config, Session}; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::attr; @@ -9,6 +7,8 @@ use rustc_errors::struct_span_err; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ImplItem, Item, ItemKind, TraitItem}; +use rustc_session::config::EntryFnType; +use rustc_session::{config, Session}; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 161aad253f2..4f4d9f93eb6 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -97,7 +97,6 @@ use self::LiveNodeKind::*; use self::VarKind::*; use rustc::hir::map::Map; -use rustc::lint; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc_ast::ast; @@ -108,6 +107,7 @@ use rustc_hir::def::*; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, HirId, HirIdMap, HirIdSet, Node}; +use rustc_session::lint; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 34af0d5b03e..7d35b74b2a4 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -7,7 +7,6 @@ use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::middle::privacy; -use rustc::session::config; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashSet; @@ -19,6 +18,7 @@ use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirIdSet, Node}; +use rustc_session::config; use rustc_target::spec::abi::Abi; // Returns true if the given item must be inlined because it may be diff --git a/src/librustc_passes/stability.rs b/src/librustc_passes/stability.rs index 6cf4132141b..11311a3e8aa 100644 --- a/src/librustc_passes/stability.rs +++ b/src/librustc_passes/stability.rs @@ -2,11 +2,8 @@ //! propagating default levels lexically from parent to children ast nodes. use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::privacy::AccessLevels; use rustc::middle::stability::{DeprecationEntry, Index}; -use rustc::session::parse::feature_err; -use rustc::session::Session; use rustc::ty::query::Providers; use rustc::ty::TyCtxt; use rustc_ast::ast::Attribute; @@ -18,6 +15,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{Generics, HirId, Item, StructField, Variant}; +use rustc_session::lint; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_trait_selection::traits::misc::can_type_implement_copy; diff --git a/src/librustc_passes/weak_lang_items.rs b/src/librustc_passes/weak_lang_items.rs index 2aef080a677..cde489e8d2c 100644 --- a/src/librustc_passes/weak_lang_items.rs +++ b/src/librustc_passes/weak_lang_items.rs @@ -2,14 +2,13 @@ use rustc::middle::lang_items; use rustc::middle::lang_items::whitelisted; -use rustc::session::config; - use rustc::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::weak_lang_items::WEAK_ITEMS_REFS; +use rustc_session::config; use rustc_span::symbol::Symbol; use rustc_span::Span; diff --git a/src/librustc_plugin_impl/Cargo.toml b/src/librustc_plugin_impl/Cargo.toml index 89313072590..372d6a534c8 100644 --- a/src/librustc_plugin_impl/Cargo.toml +++ b/src/librustc_plugin_impl/Cargo.toml @@ -17,4 +17,5 @@ rustc_hir = { path = "../librustc_hir" } rustc_lint = { path = "../librustc_lint" } rustc_metadata = { path = "../librustc_metadata" } rustc_ast = { path = "../librustc_ast" } +rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_plugin_impl/load.rs b/src/librustc_plugin_impl/load.rs index 9bd9bcb25ba..0810cf56d17 100644 --- a/src/librustc_plugin_impl/load.rs +++ b/src/librustc_plugin_impl/load.rs @@ -2,10 +2,10 @@ use crate::Registry; use rustc::middle::cstore::MetadataLoader; -use rustc::session::Session; use rustc_ast::ast::{Crate, Ident}; use rustc_errors::struct_span_err; use rustc_metadata::locator; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::Span; diff --git a/src/librustc_privacy/Cargo.toml b/src/librustc_privacy/Cargo.toml index 6d1272c117b..9854e0f6c53 100644 --- a/src/librustc_privacy/Cargo.toml +++ b/src/librustc_privacy/Cargo.toml @@ -14,6 +14,7 @@ rustc_attr = { path = "../librustc_attr" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_typeck = { path = "../librustc_typeck" } +rustc_session = { path = "../librustc_session" } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 8dd4fadc026..86f3c80069c 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -5,7 +5,6 @@ use rustc::bug; use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::privacy::{AccessLevel, AccessLevels}; use rustc::ty::fold::TypeVisitor; use rustc::ty::query::Providers; @@ -20,6 +19,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::intravisit::{self, DeepVisitor, NestedVisitorMap, Visitor}; use rustc_hir::{AssocItemKind, HirIdSet, Node, PatKind}; +use rustc_session::lint; use rustc_span::hygiene::Transparency; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index 722f843ab6e..35876176e3e 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -26,12 +26,13 @@ use crate::imports::ImportKind; use crate::Resolver; -use rustc::{lint, ty}; +use rustc::ty; use rustc_ast::ast; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; +use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_span::{MultiSpan, Span, DUMMY_SP}; @@ -232,7 +233,7 @@ impl Resolver<'_> { if let ImportKind::MacroUse = import.kind { if !import.span.is_dummy() { self.lint_buffer.buffer_lint( - lint::builtin::MACRO_USE_EXTERN_CRATE, + MACRO_USE_EXTERN_CRATE, import.id, import.span, "deprecated `#[macro_use]` attribute used to \ @@ -247,9 +248,8 @@ impl Resolver<'_> { self.maybe_unused_extern_crates.push((import.id, import.span)); } ImportKind::MacroUse => { - let lint = lint::builtin::UNUSED_IMPORTS; let msg = "unused `#[macro_use]` import"; - self.lint_buffer.buffer_lint(lint, import.id, import.span, msg); + self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.id, import.span, msg); } _ => {} } @@ -314,7 +314,7 @@ impl Resolver<'_> { }; visitor.r.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNUSED_IMPORTS, + UNUSED_IMPORTS, unused.use_tree_id, ms, &msg, diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs index 47a05ec90d4..aa69682fadd 100644 --- a/src/librustc_resolve/diagnostics.rs +++ b/src/librustc_resolve/diagnostics.rs @@ -2,7 +2,6 @@ use std::cmp::Reverse; use log::debug; use rustc::bug; -use rustc::session::Session; use rustc::ty::{self, DefIdTree}; use rustc_ast::ast::{self, Ident, Path}; use rustc_ast::util::lev_distance::find_best_match_for_name; @@ -13,6 +12,7 @@ use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, NonMacroAttrKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_session::Session; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, Symbol}; diff --git a/src/librustc_resolve/imports.rs b/src/librustc_resolve/imports.rs index 485b86636a0..4cd3bcee0a1 100644 --- a/src/librustc_resolve/imports.rs +++ b/src/librustc_resolve/imports.rs @@ -10,7 +10,6 @@ use crate::{CrateLint, Module, ModuleOrUniformRoot, ParentScope, PerNS, ScopeSet use crate::{NameBinding, NameBindingKind, PathResult, PrivacyError, ToNameBinding}; use rustc::hir::exports::Export; -use rustc::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc::ty; use rustc::{bug, span_bug}; use rustc_ast::ast::{Ident, Name, NodeId}; @@ -21,6 +20,7 @@ use rustc_data_structures::ptr_key::PtrKey; use rustc_errors::{pluralize, struct_span_err, Applicability}; use rustc_hir::def::{self, PartialRes}; use rustc_hir::def_id::DefId; +use rustc_session::lint::builtin::{PUB_USE_OF_PRIVATE_EXTERN_CRATE, UNUSED_IMPORTS}; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::DiagnosticMessageId; use rustc_span::hygiene::ExpnId; diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index 7efd9e90ceb..d196813bf7d 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -11,7 +11,7 @@ use crate::{path_names_to_string, BindingError, CrateLint, LexicalScopeBinding}; use crate::{Module, ModuleOrUniformRoot, NameBindingKind, ParentScope, PathResult}; use crate::{ResolutionError, Resolver, Segment, UseError}; -use rustc::{bug, lint, span_bug}; +use rustc::{bug, span_bug}; use rustc_ast::ast::*; use rustc_ast::ptr::P; use rustc_ast::util::lev_distance::find_best_match_for_name; @@ -23,6 +23,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, PartialRes, PerNS}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::TraitCandidate; +use rustc_session::lint; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; diff --git a/src/librustc_resolve/late/diagnostics.rs b/src/librustc_resolve/late/diagnostics.rs index 13d43305280..41380b2a4b7 100644 --- a/src/librustc_resolve/late/diagnostics.rs +++ b/src/librustc_resolve/late/diagnostics.rs @@ -5,7 +5,6 @@ use crate::path_names_to_string; use crate::{CrateLint, Module, ModuleKind, ModuleOrUniformRoot}; use crate::{PathResult, PathSource, Segment}; -use rustc::session::config::nightly_options; use rustc_ast::ast::{self, Expr, ExprKind, Ident, Item, ItemKind, NodeId, Path, Ty, TyKind}; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_data_structures::fx::FxHashSet; @@ -15,6 +14,7 @@ use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind}; use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::PrimTy; +use rustc_session::config::nightly_options; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index e28b4884b88..1e4131b93f5 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -7,7 +7,6 @@ use crate::late::diagnostics::{ForLifetimeSpanType, MissingLifetimeSpot}; use rustc::hir::map::Map; -use rustc::lint; use rustc::middle::resolve_lifetime::*; use rustc::ty::{self, DefIdTree, GenericParamDefKind, TyCtxt}; use rustc::{bug, span_bug}; @@ -22,6 +21,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}; +use rustc_session::lint; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use std::borrow::Cow; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 37a800a0b7b..d6cb618d950 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -18,7 +18,6 @@ use Determinacy::*; use rustc::hir::exports::ExportMap; use rustc::hir::map::{DefKey, Definitions}; -use rustc::lint; use rustc::middle::cstore::{CrateStore, MetadataLoaderDyn}; use rustc::span_bug; use rustc::ty::query::Providers; @@ -42,6 +41,7 @@ use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE} use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; +use rustc_session::lint; use rustc_session::lint::{BuiltinLintDiagnostics, LintBuffer}; use rustc_session::Session; use rustc_span::hygiene::{ExpnId, ExpnKind, MacroKind, SyntaxContext, Transparency}; diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index e11aec90669..4d758dc2633 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -7,9 +7,7 @@ use crate::{AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, Determinacy}; use crate::{CrateLint, ParentScope, ResolutionError, Resolver, Scope, ScopeSet, Weak}; use crate::{ModuleKind, ModuleOrUniformRoot, NameBinding, PathResult, Segment, ToNameBinding}; use rustc::middle::stability; -use rustc::session::parse::feature_err; -use rustc::session::Session; -use rustc::{lint, span_bug, ty}; +use rustc::{span_bug, ty}; use rustc_ast::ast::{self, Ident, NodeId}; use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, StabilityLevel}; @@ -21,6 +19,9 @@ use rustc_expand::expand::{AstFragment, AstFragmentKind, Invocation, InvocationK use rustc_feature::is_builtin_attr_name; use rustc_hir::def::{self, DefKind, NonMacroAttrKind}; use rustc_hir::def_id; +use rustc_session::lint::builtin::UNUSED_MACROS; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::{self, ExpnData, ExpnId, ExpnKind}; use rustc_span::symbol::{kw, sym, Symbol}; @@ -323,12 +324,7 @@ impl<'a> base::Resolver for Resolver<'a> { fn check_unused_macros(&mut self) { for (&node_id, &span) in self.unused_macros.iter() { - self.lint_buffer.buffer_lint( - lint::builtin::UNUSED_MACROS, - node_id, - span, - "unused macro definition", - ); + self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition"); } } diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index 0f4cc4192b6..4717664b6ba 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -18,6 +18,7 @@ rustc_hir = { path = "../librustc_hir" } rustc_parse = { path = "../librustc_parse" } serde_json = "1" rustc_ast = { path = "../librustc_ast" } +rustc_session = { path = "../librustc_session" } rustc_span = { path = "../librustc_span" } rls-data = "0.19" rls-span = "0.5" diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index cf4a9e947be..8d1a39eab89 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -13,7 +13,6 @@ //! DumpVisitor walks the AST and processes it, and Dumper is used for //! recording the output. -use rustc::session::config::Input; use rustc::span_bug; use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc_ast::ast::{self, Attribute, NodeId, PatKind}; @@ -25,6 +24,7 @@ use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind as HirDefKind, Res}; use rustc_hir::def_id::DefId; +use rustc_session::config::Input; use rustc_span::source_map::{respan, DUMMY_SP}; use rustc_span::*; diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 8b0120c34e0..98d81c62522 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -10,7 +10,6 @@ mod sig; use rustc::middle::cstore::ExternCrate; use rustc::middle::privacy::AccessLevels; -use rustc::session::config::{CrateType, Input, OutputType}; use rustc::ty::{self, DefIdTree, TyCtxt}; use rustc::{bug, span_bug}; use rustc_ast::ast::{self, Attribute, NodeId, PatKind, DUMMY_NODE_ID}; @@ -22,6 +21,7 @@ use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind as HirDefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; +use rustc_session::config::{CrateType, Input, OutputType}; use rustc_span::source_map::Spanned; use rustc_span::*; diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 152435206fe..6620941c440 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -1,7 +1,7 @@ use crate::generated_code; -use rustc::session::Session; use rustc_ast::token::{self, TokenKind}; use rustc_parse::lexer::{self, StringReader}; +use rustc_session::Session; use rustc_span::*; #[derive(Clone)] diff --git a/src/librustc_trait_selection/opaque_types.rs b/src/librustc_trait_selection/opaque_types.rs index 6cf1302783c..785d8b892be 100644 --- a/src/librustc_trait_selection/opaque_types.rs +++ b/src/librustc_trait_selection/opaque_types.rs @@ -1,6 +1,5 @@ use crate::infer::InferCtxtExt as _; use crate::traits::{self, PredicateObligation}; -use rustc::session::config::nightly_options; use rustc::ty::fold::{BottomUpFolder, TypeFoldable, TypeFolder, TypeVisitor}; use rustc::ty::free_region_map::FreeRegionRelations; use rustc::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, SubstsRef}; @@ -13,6 +12,7 @@ use rustc_hir::Node; use rustc_infer::infer::error_reporting::unexpected_hidden_region_diagnostic; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk}; +use rustc_session::config::nightly_options; use rustc_span::Span; pub type OpaqueTypeMap<'tcx> = DefIdMap>; diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index abd9638bfa7..32dfe1e6c5c 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -12,7 +12,6 @@ use crate::infer::error_reporting::{TyCategory, TypeAnnotationNeeded as ErrorCod use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use crate::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc::mir::interpret::ErrorHandled; -use rustc::session::DiagnosticMessageId; use rustc::ty::error::ExpectedFound; use rustc::ty::fast_reject; use rustc::ty::fold::TypeFolder; @@ -25,6 +24,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder} use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::{Node, QPath, TyKind, WhereBoundPredicate, WherePredicate}; +use rustc_session::DiagnosticMessageId; use rustc_span::source_map::SourceMap; use rustc_span::{ExpnKind, Span, DUMMY_SP}; use std::fmt; diff --git a/src/librustc_ty/Cargo.toml b/src/librustc_ty/Cargo.toml index 3c790bc4cb1..cf0b4b82eea 100644 --- a/src/librustc_ty/Cargo.toml +++ b/src/librustc_ty/Cargo.toml @@ -15,5 +15,6 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_hir = { path = "../librustc_hir" } rustc_infer = { path = "../librustc_infer" } rustc_span = { path = "../librustc_span" } +rustc_session = { path = "../librustc_session" } rustc_target = { path = "../librustc_target" } rustc_trait_selection = { path = "../librustc_trait_selection" } diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 387d1d9923d..4b522997537 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -1,10 +1,10 @@ use rustc::hir::map as hir_map; -use rustc::session::CrateDisambiguator; use rustc::ty::subst::Subst; use rustc::ty::{self, ToPredicate, Ty, TyCtxt, WithConstness}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_trait_selection::traits; diff --git a/src/librustc_typeck/Cargo.toml b/src/librustc_typeck/Cargo.toml index 83a48ee3995..e61a36f844f 100644 --- a/src/librustc_typeck/Cargo.toml +++ b/src/librustc_typeck/Cargo.toml @@ -19,6 +19,7 @@ rustc_data_structures = { path = "../librustc_data_structures" } rustc_errors = { path = "../librustc_errors" } rustc_hir = { path = "../librustc_hir" } rustc_target = { path = "../librustc_target" } +rustc_session = { path = "../librustc_session" } smallvec = { version = "1.0", features = ["union", "may_dangle"] } rustc_ast = { path = "../librustc_ast" } rustc_span = { path = "../librustc_span" } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index be8090cf21b..4cc8fb12660 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -6,13 +6,10 @@ // ignore-tidy-filelength use crate::collect::PlaceholderHirTyCollector; -use crate::lint; use crate::middle::lang_items::SizedTraitLangItem; use crate::middle::resolve_lifetime as rl; use crate::require_c_abi_if_c_variadic; use crate::util::common::ErrorReported; -use rustc::lint::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; -use rustc::session::{parse::feature_err, Session}; use rustc::ty::subst::{self, InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, Const, DefIdTree, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; @@ -26,6 +23,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::print; use rustc_hir::{Constness, ExprKind, GenericArg, GenericArgs}; +use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, LATE_BOUND_LIFETIME_ARGUMENTS}; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::symbol::sym; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use rustc_target::spec::abi; @@ -33,8 +33,8 @@ use rustc_trait_selection::traits; use rustc_trait_selection::traits::astconv_object_safety_violations; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; use rustc_trait_selection::traits::wf::object_region_bounds; -use smallvec::SmallVec; +use smallvec::SmallVec; use std::collections::BTreeSet; use std::iter; use std::slice; @@ -340,7 +340,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut multispan = MultiSpan::from_span(span); multispan.push_span_label(span_late, note.to_string()); tcx.struct_span_lint_hir( - lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS, + LATE_BOUND_LIFETIME_ARGUMENTS, args.args[0].id(), multispan, |lint| lint.build(msg).emit(), diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs index 991347714e8..2315b42aec5 100644 --- a/src/librustc_typeck/check/autoderef.rs +++ b/src/librustc_typeck/check/autoderef.rs @@ -1,19 +1,18 @@ use super::method::MethodCallee; use super::{FnCtxt, Needs, PlaceOp}; -use rustc::session::DiagnosticMessageId; use rustc::ty::adjustment::{Adjust, Adjustment, OverloadedDeref}; use rustc::ty::{self, TraitRef, Ty, TyCtxt, WithConstness}; use rustc::ty::{ToPredicate, TypeFoldable}; +use rustc_ast::ast::Ident; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_infer::infer::{InferCtxt, InferOk}; +use rustc_session::DiagnosticMessageId; +use rustc_span::Span; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, TraitEngine}; -use rustc_ast::ast::Ident; -use rustc_span::Span; - use std::iter; #[derive(Copy, Clone, Debug)] diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index d52b6c39ab5..2875d38a996 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -31,11 +31,9 @@ use super::FnCtxt; use crate::hir::def_id::DefId; -use crate::lint; use crate::type_error_struct; use crate::util::common::ErrorReported; use rustc::middle::lang_items; -use rustc::session::Session; use rustc::ty::adjustment::AllowTwoPhase; use rustc::ty::cast::{CastKind, CastTy}; use rustc::ty::error::TypeError; @@ -44,6 +42,8 @@ use rustc::ty::{self, Ty, TypeAndMut, TypeFoldable}; use rustc_ast::ast; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_session::lint; +use rustc_session::Session; use rustc_span::Span; use rustc_trait_selection::traits; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index d74623a063f..b0d74651847 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -52,7 +52,6 @@ use crate::astconv::AstConv; use crate::check::{FnCtxt, Needs}; -use rustc::session::parse::feature_err; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -66,11 +65,13 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, InferOk, InferResult}; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::{self, Span}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; + use smallvec::{smallvec, SmallVec}; use std::ops::Deref; diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 16bab09feee..45b1c7d6ea7 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -8,9 +8,7 @@ use crate::check::FnCtxt; use crate::hir::def::DefKind; use crate::hir::def_id::DefId; -use rustc::lint; use rustc::middle::stability; -use rustc::session::config::nightly_options; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ @@ -28,6 +26,8 @@ use rustc_infer::infer::canonical::{Canonical, QueryResponse}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferOk, TyCtxtInferExt}; +use rustc_session::config::nightly_options; +use rustc_session::lint; use rustc_span::{symbol::Symbol, Span, DUMMY_SP}; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::method_autoderef::MethodAutoderefBadTy; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bbc9171918f..ba0ae04b0d4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -92,7 +92,6 @@ use crate::middle::lang_items; use rustc::hir::map::blocks::FnLikeNode; use rustc::middle::region; use rustc::mir::interpret::ConstValue; -use rustc::session::parse::feature_err; use rustc::ty::adjustment::{ Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoBorrowMutability, PointerCast, }; @@ -123,6 +122,10 @@ use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_infer::infer::{self, InferCtxt, InferOk, InferResult, TyCtxtInferExt}; +use rustc_session::config::{self, EntryFnType}; +use rustc_session::lint; +use rustc_session::parse::feature_err; +use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; use rustc_span::source_map::{original_sp, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Ident}; @@ -145,10 +148,7 @@ use std::mem::replace; use std::ops::{self, Deref}; use std::slice; -use crate::lint; use crate::require_c_abi_if_c_variadic; -use crate::session::config::EntryFnType; -use crate::session::Session; use crate::util::common::{indenter, ErrorReported}; use crate::TypeAndSubsts; @@ -5787,7 +5787,7 @@ fn fatally_break_rust(sess: &Session) { handler.note_without_error(&format!( "rustc {} running on {}", option_env!("CFG_VERSION").unwrap_or("unknown_version"), - crate::session::config::host_triple(), + config::host_triple(), )); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 026e68e10e0..1f2904d7c49 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -2,7 +2,6 @@ use crate::check::{FnCtxt, Inherited}; use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter}; use rustc::middle::lang_items; -use rustc::session::parse::feature_err; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{ self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, @@ -10,17 +9,17 @@ use rustc::ty::{ use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; +use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::itemlikevisit::ParItemLikeVisitor; use rustc_hir::ItemKind; +use rustc_session::parse::feature_err; use rustc_span::symbol::sym; use rustc_span::Span; use rustc_trait_selection::opaque_types::may_define_opaque_type; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::{self, ObligationCause, ObligationCauseCode}; -use rustc_hir as hir; -use rustc_hir::itemlikevisit::ParItemLikeVisitor; - /// Helper type of a temporary returned by `.for_item(...)`. /// This is necessary because we can't write the following bound: /// diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs index 3517e09133c..d0414af5b21 100644 --- a/src/librustc_typeck/check_unused.rs +++ b/src/librustc_typeck/check_unused.rs @@ -1,4 +1,3 @@ -use crate::lint; use rustc::ty::TyCtxt; use rustc_ast::ast; use rustc_data_structures::fx::FxHashMap; @@ -7,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::visibility_qualified; +use rustc_session::lint; use rustc_span::Span; pub fn check_crate(tcx: TyCtxt<'_>) { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9bb1f7e3131..21e864df491 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -17,14 +17,12 @@ use crate::astconv::{AstConv, Bounds, SizedByDefault}; use crate::check::intrinsic::intrinsic_operation_unsafety; use crate::constrained_generic_params as cgp; -use crate::lint; use crate::middle::lang_items; use crate::middle::resolve_lifetime as rl; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::Map; use rustc::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc::mir::mono::Linkage; -use rustc::session::parse::feature_err; use rustc::ty::query::Providers; use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::util::Discr; @@ -42,6 +40,8 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericParamKind, Node, Unsafety}; +use rustc_session::lint; +use rustc_session::parse::feature_err; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi; diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs index c4a8edd86f8..ad0d14e9ba3 100644 --- a/src/librustc_typeck/collect/type_of.rs +++ b/src/librustc_typeck/collect/type_of.rs @@ -1,5 +1,4 @@ use rustc::hir::map::Map; -use rustc::session::parse::feature_err; use rustc::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc::ty::util::IntTypeExt; use rustc::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable}; @@ -11,6 +10,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; +use rustc_session::parse::feature_err; use rustc_span::symbol::{sym, Ident}; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits; diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 4e7985dd988..93404821f39 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -87,10 +87,7 @@ mod outlives; mod structured_errors; mod variance; -use rustc::lint; use rustc::middle; -use rustc::session; -use rustc::session::config::EntryFnType; use rustc::ty::query::Providers; use rustc::ty::subst::SubstsRef; use rustc::ty::{self, Ty, TyCtxt}; @@ -102,6 +99,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Node; use rustc_infer::infer::{InferOk, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; +use rustc_session::config::EntryFnType; use rustc_span::{Span, DUMMY_SP}; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _; diff --git a/src/librustc_typeck/structured_errors.rs b/src/librustc_typeck/structured_errors.rs index 99b7b2001a9..a4f8472ae28 100644 --- a/src/librustc_typeck/structured_errors.rs +++ b/src/librustc_typeck/structured_errors.rs @@ -1,6 +1,6 @@ -use rustc::session::Session; use rustc::ty::{Ty, TypeFoldable}; use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId}; +use rustc_session::Session; use rustc_span::Span; pub trait StructuredDiagnostic<'tcx> { diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 58c8a7d82bf..179c5bfacf3 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -4,15 +4,14 @@ use std::ffi::OsStr; use std::fmt; use std::path::PathBuf; -use rustc::lint::Level; -use rustc::session; -use rustc::session::config::{ +use rustc_session::config::{self, parse_crate_types_from_list, parse_externs, CrateType}; +use rustc_session::config::{ build_codegen_options, build_debugging_options, get_cmd_lint_options, host_triple, nightly_options, }; -use rustc::session::config::{parse_crate_types_from_list, parse_externs, CrateType}; -use rustc::session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; -use rustc::session::search_paths::SearchPath; +use rustc_session::config::{CodegenOptions, DebuggingOptions, ErrorOutputType, Externs}; +use rustc_session::lint::Level; +use rustc_session::search_paths::SearchPath; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_target::spec::TargetTriple; @@ -299,9 +298,9 @@ impl Options { return Err(0); } - let color = session::config::parse_color(&matches); - let (json_rendered, _artifacts) = session::config::parse_json(&matches); - let error_format = session::config::parse_error_format(&matches, color, json_rendered); + let color = config::parse_color(&matches); + let (json_rendered, _artifacts) = config::parse_json(&matches); + let error_format = config::parse_error_format(&matches, color, json_rendered); let codegen_options = build_codegen_options(matches, error_format); let debugging_options = build_debugging_options(matches, error_format); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b9ae3d53afc..f0b9ad2852f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -1,23 +1,22 @@ use rustc::middle::cstore::CrateStore; use rustc::middle::privacy::AccessLevels; -use rustc::session::config::ErrorOutputType; -use rustc::session::DiagnosticOutput; -use rustc::session::{self, config}; use rustc::ty::{Ty, TyCtxt}; +use rustc_ast::ast::CRATE_NODE_ID; +use rustc_attr as attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_driver::abort_on_err; +use rustc_errors::emitter::{Emitter, EmitterWriter}; +use rustc_errors::json::JsonEmitter; use rustc_feature::UnstableFeatures; use rustc_hir::def::Namespace::TypeNS; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; use rustc_hir::HirId; use rustc_interface::interface; use rustc_resolve as resolve; +use rustc_session::config::ErrorOutputType; use rustc_session::lint; - -use rustc_ast::ast::CRATE_NODE_ID; -use rustc_attr as attr; -use rustc_errors::emitter::{Emitter, EmitterWriter}; -use rustc_errors::json::JsonEmitter; +use rustc_session::DiagnosticOutput; +use rustc_session::{config, Session}; use rustc_span::source_map; use rustc_span::symbol::sym; use rustc_span::DUMMY_SP; @@ -34,8 +33,8 @@ use crate::html::render::RenderInfo; use crate::passes::{self, Condition::*, ConditionalPass}; -pub use rustc::session::config::{CodegenOptions, DebuggingOptions, Input, Options}; -pub use rustc::session::search_paths::SearchPath; +pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options}; +pub use rustc_session::search_paths::SearchPath; pub type ExternalPaths = FxHashMap, clean::TypeKind)>; @@ -68,7 +67,7 @@ pub struct DocContext<'tcx> { } impl<'tcx> DocContext<'tcx> { - pub fn sess(&self) -> &session::Session { + pub fn sess(&self) -> &Session { &self.tcx.sess } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 2e90d6082ba..3c1f0509bba 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -49,8 +49,8 @@ use std::env; use std::panic; use std::process; -use rustc::session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; -use rustc::session::{early_error, early_warn}; +use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; +use rustc_session::{early_error, early_warn}; #[macro_use] mod externalfiles; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 75355b84fee..72106afbe0e 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1,4 +1,3 @@ -use rustc::lint; use rustc::ty; use rustc_ast::ast::{self, Ident}; use rustc_errors::Applicability; @@ -12,6 +11,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::DefId; use rustc_resolve::ParentScope; +use rustc_session::lint; use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; diff --git a/src/librustdoc/passes/mod.rs b/src/librustdoc/passes/mod.rs index 71cff637c12..38f371783e9 100644 --- a/src/librustdoc/passes/mod.rs +++ b/src/librustdoc/passes/mod.rs @@ -1,9 +1,9 @@ //! Contains information about "passes", used to modify crate information during the documentation //! process. -use rustc::lint; use rustc::middle::privacy::AccessLevels; use rustc_hir::def_id::{DefId, DefIdSet}; +use rustc_session::lint; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use std::mem; use std::ops::Range; diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index b1a60e2746f..c5aa4677d56 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -1,5 +1,4 @@ use rustc::hir::map::Map; -use rustc::session::{self, config, DiagnosticOutput}; use rustc::util::common::ErrorReported; use rustc_ast::ast; use rustc_ast::with_globals; @@ -8,6 +7,7 @@ use rustc_feature::UnstableFeatures; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_interface::interface; +use rustc_session::{self, config, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; @@ -52,7 +52,7 @@ pub fn run(options: Options) -> i32 { cg: options.codegen_options.clone(), externs: options.externs.clone(), unstable_features: UnstableFeatures::from_environment(), - lint_cap: Some(::rustc::lint::Level::Allow), + lint_cap: Some(rustc_session::lint::Level::Allow), actually_rustdoc: true, debugging_opts: config::DebuggingOptions { ..config::basic_debugging_options() }, edition: options.edition, @@ -854,7 +854,7 @@ impl Tester for Collector { } struct HirCollector<'a, 'hir> { - sess: &'a session::Session, + sess: &'a Session, collector: &'a mut Collector, map: Map<'hir>, codes: ErrorCodes, diff --git a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs index 07ef2424cc8..d975af52f5b 100644 --- a/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs +++ b/src/test/run-make-fulldeps/hotplug_codegen_backend/the_backend.rs @@ -7,14 +7,12 @@ extern crate rustc_data_structures; extern crate rustc_hir; extern crate rustc_target; extern crate rustc_driver; +extern crate rustc_session; extern crate rustc_span; use std::any::Any; use std::sync::Arc; use std::path::Path; -use rustc_span::symbol::Symbol; -use rustc::session::Session; -use rustc::session::config::OutputFilenames; use rustc::ty::TyCtxt; use rustc::ty::query::Providers; use rustc::middle::cstore::{EncodedMetadata, MetadataLoader, MetadataLoaderDyn}; @@ -23,6 +21,9 @@ use rustc::util::common::ErrorReported; use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_data_structures::sync::MetadataRef; use rustc_data_structures::owning_ref::OwningRef; +use rustc_session::Session; +use rustc_session::config::OutputFilenames; +use rustc_span::symbol::Symbol; use rustc_target::spec::Target; pub struct NoLlvmMetadataLoader; @@ -89,7 +90,7 @@ impl CodegenBackend for TheBackend { outputs: &OutputFilenames, ) -> Result<(), ErrorReported> { use std::io::Write; - use rustc::session::config::CrateType; + use rustc_session::config::CrateType; use rustc_codegen_utils::link::out_filename; let crate_name = codegen_results.downcast::() .expect("in link: codegen_results is not a Symbol"); diff --git a/src/test/run-make-fulldeps/issue-19371/foo.rs b/src/test/run-make-fulldeps/issue-19371/foo.rs index 12da64fc88f..af84faa7511 100644 --- a/src/test/run-make-fulldeps/issue-19371/foo.rs +++ b/src/test/run-make-fulldeps/issue-19371/foo.rs @@ -1,13 +1,12 @@ #![feature(rustc_private)] -extern crate rustc; extern crate rustc_interface; extern crate rustc_driver; +extern crate rustc_session; extern crate rustc_span; -use rustc::session::DiagnosticOutput; -use rustc::session::config::{Input, Options, - OutputType, OutputTypes}; +use rustc_session::DiagnosticOutput; +use rustc_session::config::{Input, Options, OutputType, OutputTypes}; use rustc_interface::interface; use rustc_span::source_map::FileName; From 2c2d41dc000714ed3b8b734e608862ff6c74a8d4 Mon Sep 17 00:00:00 2001 From: mark Date: Sun, 15 Mar 2020 23:31:17 -0500 Subject: [PATCH 1178/1250] make article_and_description primarily use def_kind --- src/librustc/ty/context.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 6fab55e9fd9..ada14ec4d0b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1515,20 +1515,21 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns a displayable description and article for the given `def_id` (e.g. `("a", "struct")`). pub fn article_and_description(&self, def_id: DefId) -> (&'static str, &'static str) { - match self.def_key(def_id).disambiguated_data.data { - DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { - let kind = self.def_kind(def_id).unwrap(); - (kind.article(), kind.descr(def_id)) - } - DefPathData::ClosureExpr => match self.generator_kind(def_id) { - None => ("a", "closure"), - Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), - Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), - }, - DefPathData::LifetimeNs(..) => ("a", "lifetime"), - DefPathData::Impl => ("an", "implementation"), - _ => bug!("article_and_description called on def_id {:?}", def_id), - } + self.def_kind(def_id) + .map(|def_kind| (def_kind.article(), def_kind.descr(def_id))) + .unwrap_or_else(|| match self.def_key(def_id).disambiguated_data.data { + DefPathData::ClosureExpr => match self.generator_kind(def_id) { + None => ("a", "closure"), + Some(rustc_hir::GeneratorKind::Async(..)) => ("an", "async closure"), + Some(rustc_hir::GeneratorKind::Gen) => ("a", "generator"), + }, + DefPathData::LifetimeNs(..) => ("a", "lifetime"), + DefPathData::Impl => ("an", "implementation"), + DefPathData::TypeNs(..) | DefPathData::ValueNs(..) | DefPathData::MacroNs(..) => { + unreachable!() + } + _ => bug!("article_and_description called on def_id {:?}", def_id), + }) } } From 996a51bcd04e097254b5072270e10b1280ff1b28 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Mar 2020 14:38:33 +0100 Subject: [PATCH 1179/1250] init-large-type test needs optimizations --- src/test/ui/init-large-type.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/init-large-type.rs b/src/test/ui/init-large-type.rs index 7a3ffbb6ad7..ce905572f2a 100644 --- a/src/test/ui/init-large-type.rs +++ b/src/test/ui/init-large-type.rs @@ -1,3 +1,4 @@ +// compile-flags: -O // run-pass #![allow(unused_must_use)] From a2160e6a4a91490117b9f0469c49b6f86d0d20d2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 16 Mar 2020 17:37:26 +0100 Subject: [PATCH 1180/1250] make mem::{zeroed,uninitialized} inline(always) --- src/libcore/mem/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs index 9f786800522..ae4c0a98ea9 100644 --- a/src/libcore/mem/mod.rs +++ b/src/libcore/mem/mod.rs @@ -490,7 +490,7 @@ pub const fn needs_drop() -> bool { /// /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior! /// ``` -#[inline] +#[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] #[allow(deprecated)] @@ -525,7 +525,7 @@ pub unsafe fn zeroed() -> T { /// [uninit]: union.MaybeUninit.html#method.uninit /// [assume_init]: union.MaybeUninit.html#method.assume_init /// [inv]: union.MaybeUninit.html#initialization-invariant -#[inline] +#[inline(always)] #[rustc_deprecated(since = "1.39.0", reason = "use `mem::MaybeUninit` instead")] #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated_in_future)] From ce5e49f86fc8bff241695f8a62e77f517749bd6d Mon Sep 17 00:00:00 2001 From: lzutao Date: Mon, 16 Mar 2020 23:43:42 +0700 Subject: [PATCH 1181/1250] Use sublice patterns to avoid computing the len --- src/libstd/sys_common/wtf8.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 7509e1ee35d..77977e25517 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -599,24 +599,16 @@ impl Wtf8 { #[inline] fn final_lead_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match self.bytes[(len - 3)..] { - [0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)), _ => None, } } #[inline] fn initial_trail_surrogate(&self) -> Option { - let len = self.len(); - if len < 3 { - return None; - } - match self.bytes[..3] { - [0xED, b2 @ 0xB0..=0xBF, b3] => Some(decode_surrogate(b2, b3)), + match self.bytes { + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)), _ => None, } } From e1bc9af9eb503e7ca0027b4d7086c35cd661140e Mon Sep 17 00:00:00 2001 From: lzutao Date: Mon, 16 Mar 2020 23:54:32 +0700 Subject: [PATCH 1182/1250] Fix wrong deref --- src/libstd/sys_common/wtf8.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 77977e25517..498950e6821 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -600,7 +600,7 @@ impl Wtf8 { #[inline] fn final_lead_surrogate(&self) -> Option { match self.bytes { - [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(*b2, *b3)), + [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)), _ => None, } } @@ -608,7 +608,7 @@ impl Wtf8 { #[inline] fn initial_trail_surrogate(&self) -> Option { match self.bytes { - [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(*b2, *b3)), + [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)), _ => None, } } From ec862703fde44d23f7da8bc5fdd94a63354d5daf Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Wed, 11 Mar 2020 20:05:19 +0000 Subject: [PATCH 1183/1250] Make macro metavars respect (non-)hygiene --- src/librustc_expand/mbe/macro_check.rs | 13 +++++---- src/librustc_expand/mbe/macro_parser.rs | 17 ++++++----- src/librustc_expand/mbe/macro_rules.rs | 6 ++-- src/librustc_expand/mbe/transcribe.rs | 21 ++++++++------ src/librustc_span/symbol.rs | 25 ++++++++++++++++ src/test/ui/hygiene/macro-metavars-legacy.rs | 29 +++++++++++++++++++ .../ui/hygiene/macro-metavars-transparent.rs | 24 +++++++++++++++ 7 files changed, 111 insertions(+), 24 deletions(-) create mode 100644 src/test/ui/hygiene/macro-metavars-legacy.rs create mode 100644 src/test/ui/hygiene/macro-metavars-transparent.rs diff --git a/src/librustc_expand/mbe/macro_check.rs b/src/librustc_expand/mbe/macro_check.rs index 8c6bfbec902..582c26162ed 100644 --- a/src/librustc_expand/mbe/macro_check.rs +++ b/src/librustc_expand/mbe/macro_check.rs @@ -112,7 +112,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_session::lint::builtin::META_VARIABLE_MISUSE; use rustc_session::parse::ParseSess; use rustc_span::symbol::kw; -use rustc_span::{symbol::Ident, MultiSpan, Span}; +use rustc_span::{symbol::MacroRulesNormalizedIdent, MultiSpan, Span}; use smallvec::SmallVec; @@ -179,7 +179,7 @@ struct BinderInfo { } /// An environment of meta-variables to their binder information. -type Binders = FxHashMap; +type Binders = FxHashMap; /// The state at which we entered a macro definition in the RHS of another macro definition. struct MacroState<'a> { @@ -245,6 +245,7 @@ fn check_binders( if macros.is_empty() { sess.span_diagnostic.span_bug(span, "unexpected MetaVar in lhs"); } + let name = MacroRulesNormalizedIdent::new(name); // There are 3 possibilities: if let Some(prev_info) = binders.get(&name) { // 1. The meta-variable is already bound in the current LHS: This is an error. @@ -264,6 +265,7 @@ fn check_binders( if !macros.is_empty() { sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in nested lhs"); } + let name = MacroRulesNormalizedIdent::new(name); if let Some(prev_info) = get_binder_info(macros, binders, name) { // Duplicate binders at the top-level macro definition are errors. The lint is only // for nested macro definitions. @@ -300,7 +302,7 @@ fn check_binders( fn get_binder_info<'a>( mut macros: &'a Stack<'a, MacroState<'a>>, binders: &'a Binders, - name: Ident, + name: MacroRulesNormalizedIdent, ) -> Option<&'a BinderInfo> { binders.get(&name).or_else(|| macros.find_map(|state| state.binders.get(&name))) } @@ -331,6 +333,7 @@ fn check_occurrences( sess.span_diagnostic.span_bug(span, "unexpected MetaVarDecl in rhs") } TokenTree::MetaVar(span, name) => { + let name = MacroRulesNormalizedIdent::new(name); check_ops_is_prefix(sess, node_id, macros, binders, ops, span, name); } TokenTree::Delimited(_, ref del) => { @@ -552,7 +555,7 @@ fn check_ops_is_prefix( binders: &Binders, ops: &Stack<'_, KleeneToken>, span: Span, - name: Ident, + name: MacroRulesNormalizedIdent, ) { let macros = macros.push(MacroState { binders, ops: ops.into() }); // Accumulates the stacks the operators of each state until (and including when) the @@ -598,7 +601,7 @@ fn ops_is_prefix( sess: &ParseSess, node_id: NodeId, span: Span, - name: Ident, + name: MacroRulesNormalizedIdent, binder_ops: &[KleeneToken], occurrence_ops: &[KleeneToken], ) { diff --git a/src/librustc_expand/mbe/macro_parser.rs b/src/librustc_expand/mbe/macro_parser.rs index 6d4d7f5b4f3..3b9158f4445 100644 --- a/src/librustc_expand/mbe/macro_parser.rs +++ b/src/librustc_expand/mbe/macro_parser.rs @@ -76,13 +76,13 @@ use TokenTreeOrTokenTreeSlice::*; use crate::mbe::{self, TokenTree}; -use rustc_ast::ast::{Ident, Name}; +use rustc_ast::ast::Name; use rustc_ast::ptr::P; use rustc_ast::token::{self, DocComment, Nonterminal, Token}; use rustc_ast_pretty::pprust; use rustc_parse::parser::{FollowedByType, Parser, PathStyle}; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, MacroRulesNormalizedIdent, Symbol}; use rustc_errors::{FatalError, PResult}; use rustc_span::Span; @@ -273,9 +273,10 @@ crate enum ParseResult { Error(rustc_span::Span, String), } -/// A `ParseResult` where the `Success` variant contains a mapping of `Ident`s to `NamedMatch`es. -/// This represents the mapping of metavars to the token trees they bind to. -crate type NamedParseResult = ParseResult>; +/// A `ParseResult` where the `Success` variant contains a mapping of +/// `MacroRulesNormalizedIdent`s to `NamedMatch`es. This represents the mapping +/// of metavars to the token trees they bind to. +crate type NamedParseResult = ParseResult>; /// Count how many metavars are named in the given matcher `ms`. pub(super) fn count_names(ms: &[TokenTree]) -> usize { @@ -368,7 +369,7 @@ fn nameize>( sess: &ParseSess, m: &TokenTree, res: &mut I, - ret_val: &mut FxHashMap, + ret_val: &mut FxHashMap, ) -> Result<(), (rustc_span::Span, String)> { match *m { TokenTree::Sequence(_, ref seq) => { @@ -386,7 +387,9 @@ fn nameize>( return Err((span, "missing fragment specifier".to_string())); } } - TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val.entry(bind_name) { + TokenTree::MetaVarDecl(sp, bind_name, _) => match ret_val + .entry(MacroRulesNormalizedIdent::new(bind_name)) + { Vacant(spot) => { spot.insert(res.next().unwrap()); } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 3cad3ff55d9..2268c9b3854 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -22,7 +22,7 @@ use rustc_parse::Directory; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym, MacroRulesNormalizedIdent, Symbol}; use rustc_span::Span; use log::debug; @@ -411,7 +411,7 @@ pub fn compile_declarative_macro( let mut valid = true; // Extract the arguments: - let lhses = match argument_map[&lhs_nm] { + let lhses = match argument_map[&MacroRulesNormalizedIdent::new(lhs_nm)] { MatchedSeq(ref s) => s .iter() .map(|m| { @@ -428,7 +428,7 @@ pub fn compile_declarative_macro( _ => sess.span_diagnostic.span_bug(def.span, "wrong-structured lhs"), }; - let rhses = match argument_map[&rhs_nm] { + let rhses = match argument_map[&MacroRulesNormalizedIdent::new(rhs_nm)] { MatchedSeq(ref s) => s .iter() .map(|m| { diff --git a/src/librustc_expand/mbe/transcribe.rs b/src/librustc_expand/mbe/transcribe.rs index 7a64d40785e..1b1093c9529 100644 --- a/src/librustc_expand/mbe/transcribe.rs +++ b/src/librustc_expand/mbe/transcribe.rs @@ -2,7 +2,7 @@ use crate::base::ExtCtxt; use crate::mbe; use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, NamedMatch}; -use rustc_ast::ast::{Ident, MacCall}; +use rustc_ast::ast::MacCall; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::token::{self, NtTT, Token}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint}; @@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; use rustc_errors::pluralize; use rustc_span::hygiene::{ExpnId, Transparency}; +use rustc_span::symbol::MacroRulesNormalizedIdent; use rustc_span::Span; use smallvec::{smallvec, SmallVec}; @@ -81,7 +82,7 @@ impl Iterator for Frame { /// Along the way, we do some additional error checking. pub(super) fn transcribe( cx: &ExtCtxt<'_>, - interp: &FxHashMap, + interp: &FxHashMap, src: Vec, transparency: Transparency, ) -> TokenStream { @@ -223,9 +224,10 @@ pub(super) fn transcribe( } // Replace the meta-var with the matched token tree from the invocation. - mbe::TokenTree::MetaVar(mut sp, mut ident) => { + mbe::TokenTree::MetaVar(mut sp, mut orignal_ident) => { // Find the matched nonterminal from the macro invocation, and use it to replace // the meta-var. + let ident = MacroRulesNormalizedIdent::new(orignal_ident); if let Some(cur_matched) = lookup_cur_matched(ident, interp, &repeats) { if let MatchedNonterminal(ref nt) = cur_matched { // FIXME #2887: why do we apply a mark when matching a token tree meta-var @@ -249,9 +251,9 @@ pub(super) fn transcribe( // If we aren't able to match the meta-var, we push it back into the result but // with modified syntax context. (I believe this supports nested macros). marker.visit_span(&mut sp); - marker.visit_ident(&mut ident); + marker.visit_ident(&mut orignal_ident); result.push(TokenTree::token(token::Dollar, sp).into()); - result.push(TokenTree::Token(Token::from_ast_ident(ident)).into()); + result.push(TokenTree::Token(Token::from_ast_ident(orignal_ident)).into()); } } @@ -287,8 +289,8 @@ pub(super) fn transcribe( /// into the right place in nested matchers. If we attempt to descend too far, the macro writer has /// made a mistake, and we return `None`. fn lookup_cur_matched<'a>( - ident: Ident, - interpolations: &'a FxHashMap, + ident: MacroRulesNormalizedIdent, + interpolations: &'a FxHashMap, repeats: &[(usize, usize)], ) -> Option<&'a NamedMatch> { interpolations.get(&ident).map(|matched| { @@ -316,7 +318,7 @@ enum LockstepIterSize { /// A `MetaVar` with an actual `MatchedSeq`. The length of the match and the name of the /// meta-var are returned. - Constraint(usize, Ident), + Constraint(usize, MacroRulesNormalizedIdent), /// Two `Constraint`s on the same sequence had different lengths. This is an error. Contradiction(String), @@ -360,7 +362,7 @@ impl LockstepIterSize { /// multiple nested matcher sequences. fn lockstep_iter_size( tree: &mbe::TokenTree, - interpolations: &FxHashMap, + interpolations: &FxHashMap, repeats: &[(usize, usize)], ) -> LockstepIterSize { use mbe::TokenTree; @@ -376,6 +378,7 @@ fn lockstep_iter_size( }) } TokenTree::MetaVar(_, name) | TokenTree::MetaVarDecl(_, name, _) => { + let name = MacroRulesNormalizedIdent::new(name); match lookup_cur_matched(name, interpolations, repeats) { Some(matched) => match matched { MatchedNonterminal(_) => LockstepIterSize::Unconstrained, diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 5760e1d004e..7dfd6c58046 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -979,6 +979,31 @@ impl fmt::Display for IdentPrinter { } } +/// An newtype around `Ident` that calls [Ident::normalize_to_macro_rules] on +/// construction. +// FIXME(matthewj, petrochenkov) Use this more often, add a similar +// `ModernIdent` struct and use that as well. +#[derive(Copy, Clone, Eq, PartialEq, Hash)] +pub struct MacroRulesNormalizedIdent(Ident); + +impl MacroRulesNormalizedIdent { + pub fn new(ident: Ident) -> Self { + Self(ident.normalize_to_macro_rules()) + } +} + +impl fmt::Debug for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.0, f) + } +} + +impl fmt::Display for MacroRulesNormalizedIdent { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(&self.0, f) + } +} + /// An interned string. /// /// Internally, a `Symbol` is implemented as an index, and all operations diff --git a/src/test/ui/hygiene/macro-metavars-legacy.rs b/src/test/ui/hygiene/macro-metavars-legacy.rs new file mode 100644 index 00000000000..09070f0f561 --- /dev/null +++ b/src/test/ui/hygiene/macro-metavars-legacy.rs @@ -0,0 +1,29 @@ +// Ensure macro metavariables are compared with legacy hygiene + +#![feature(rustc_attrs)] + +// run-pass + +macro_rules! make_mac { + ( $($dollar:tt $arg:ident),+ ) => { + macro_rules! mac { + ( $($dollar $arg : ident),+ ) => { + $( $dollar $arg )-+ + } + } + } +} + +macro_rules! show_hygiene { + ( $dollar:tt $arg:ident ) => { + make_mac!($dollar $arg, $dollar arg); + } +} + +show_hygiene!( $arg ); + +fn main() { + let x = 5; + let y = 3; + assert_eq!(2, mac!(x, y)); +} diff --git a/src/test/ui/hygiene/macro-metavars-transparent.rs b/src/test/ui/hygiene/macro-metavars-transparent.rs new file mode 100644 index 00000000000..e475b5728a0 --- /dev/null +++ b/src/test/ui/hygiene/macro-metavars-transparent.rs @@ -0,0 +1,24 @@ +// Ensure macro metavariables are not compared without removing transparent +// marks. + +#![feature(rustc_attrs)] + +// run-pass + +#[rustc_macro_transparency = "transparent"] +macro_rules! k { + ($($s:tt)*) => { + macro_rules! m { + ($y:tt) => { + $($s)* + } + } + } +} + +k!(1 + $y); + +fn main() { + let x = 2; + assert_eq!(3, m!(x)); +} From b9167e6c7d09cdb31026c10954bb35d061308a63 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Feb 2020 02:38:33 +0100 Subject: [PATCH 1184/1250] Support type search for arguments and returned types --- src/librustdoc/clean/mod.rs | 20 ++++ src/librustdoc/clean/types.rs | 14 +-- src/librustdoc/clean/utils.rs | 40 +++++-- src/librustdoc/html/render.rs | 69 +++++++++-- src/librustdoc/html/render/cache.rs | 47 +++++--- src/librustdoc/html/static/main.js | 128 +++++++++++---------- src/test/rustdoc-js-std/return-specific.js | 7 ++ 7 files changed, 222 insertions(+), 103 deletions(-) create mode 100644 src/test/rustdoc-js-std/return-specific.js diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c4ad4554a00..e69d4ddc2d0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1078,6 +1078,26 @@ impl Clean for hir::PolyTraitRef<'_> { } } +impl Clean for hir::def::DefKind { + fn clean(&self, _: &DocContext<'_>) -> TypeKind { + match *self { + hir::def::DefKind::Mod => TypeKind::Module, + hir::def::DefKind::Struct => TypeKind::Struct, + hir::def::DefKind::Union => TypeKind::Union, + hir::def::DefKind::Enum => TypeKind::Enum, + hir::def::DefKind::Trait => TypeKind::Trait, + hir::def::DefKind::TyAlias => TypeKind::Typedef, + hir::def::DefKind::ForeignTy => TypeKind::Foreign, + hir::def::DefKind::TraitAlias => TypeKind::TraitAlias, + hir::def::DefKind::Fn => TypeKind::Function, + hir::def::DefKind::Const => TypeKind::Const, + hir::def::DefKind::Static => TypeKind::Static, + hir::def::DefKind::Macro(_) => TypeKind::Macro, + _ => TypeKind::Foreign, + } + } +} + impl Clean for hir::TraitItem<'_> { fn clean(&self, cx: &DocContext<'_>) -> Item { let inner = match self.kind { diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index b1aa094204a..73f2c399e56 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -836,8 +836,8 @@ pub struct Method { pub decl: FnDecl, pub header: hir::FnHeader, pub defaultness: Option, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, Debug)] @@ -845,8 +845,8 @@ pub struct TyMethod { pub header: hir::FnHeader, pub decl: FnDecl, pub generics: Generics, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, Debug)] @@ -854,8 +854,8 @@ pub struct Function { pub decl: FnDecl, pub generics: Generics, pub header: hir::FnHeader, - pub all_types: Vec, - pub ret_types: Vec, + pub all_types: Vec<(Type, TypeKind)>, + pub ret_types: Vec<(Type, TypeKind)>, } #[derive(Clone, PartialEq, Eq, Debug, Hash)] @@ -1042,7 +1042,7 @@ pub enum PrimitiveType { Never, } -#[derive(Clone, Copy, Debug)] +#[derive(Clone, PartialEq, Eq, Hash, Copy, Debug)] pub enum TypeKind { Enum, Function, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 21e3d24cc96..b54af499187 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -184,7 +184,7 @@ pub fn get_real_types( arg: &Type, cx: &DocContext<'_>, recurse: i32, -) -> FxHashSet { +) -> FxHashSet<(Type, TypeKind)> { let arg_s = arg.print().to_string(); let mut res = FxHashSet::default(); if recurse >= 10 { @@ -209,7 +209,11 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - res.insert(ty); + if let Some(did) = ty.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((ty, kind)); + } + } } } } @@ -225,13 +229,21 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } else if !ty.is_full_generic() { - res.insert(ty.clone()); + if let Some(did) = ty.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((ty.clone(), kind)); + } + } } } } } } else { - res.insert(arg.clone()); + if let Some(did) = arg.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((arg.clone(), kind)); + } + } if let Some(gens) = arg.generics() { for gen in gens.iter() { if gen.is_full_generic() { @@ -239,8 +251,10 @@ pub fn get_real_types( if !adds.is_empty() { res.extend(adds); } - } else { - res.insert(gen.clone()); + } else if let Some(did) = gen.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + res.insert((gen.clone(), kind)); + } } } } @@ -256,7 +270,7 @@ pub fn get_all_types( generics: &Generics, decl: &FnDecl, cx: &DocContext<'_>, -) -> (Vec, Vec) { +) -> (Vec<(Type, TypeKind)>, Vec<(Type, TypeKind)>) { let mut all_types = FxHashSet::default(); for arg in decl.inputs.values.iter() { if arg.type_.is_self_type() { @@ -266,7 +280,11 @@ pub fn get_all_types( if !args.is_empty() { all_types.extend(args); } else { - all_types.insert(arg.type_.clone()); + if let Some(did) = arg.type_.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + all_types.insert((arg.type_.clone(), kind)); + } + } } } @@ -274,7 +292,11 @@ pub fn get_all_types( FnRetTy::Return(ref return_type) => { let mut ret = get_real_types(generics, &return_type, cx, 0); if ret.is_empty() { - ret.insert(return_type.clone()); + if let Some(did) = return_type.def_id() { + if let Some(kind) = cx.tcx.def_kind(did).clean(cx) { + ret.insert((return_type.clone(), kind)); + } + } } ret.into_iter().collect() } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b3d70475bf3..8d60e087e04 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -58,7 +58,7 @@ use rustc_span::symbol::{sym, Symbol}; use serde::ser::SerializeSeq; use serde::{Serialize, Serializer}; -use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy}; +use crate::clean::{self, AttributesExt, Deprecation, GetDefId, SelfTy, TypeKind}; use crate::config::{OutputFormat, RenderOptions}; use crate::docfs::{DocFS, ErrorStorage, PathError}; use crate::doctree; @@ -303,8 +303,10 @@ impl Serialize for IndexItem { /// A type used for the search index. #[derive(Debug)] struct Type { + ty: Option, + idx: Option, name: Option, - generics: Option>, + generics: Option>, } impl Serialize for Type { @@ -314,7 +316,11 @@ impl Serialize for Type { { if let Some(name) = &self.name { let mut seq = serializer.serialize_seq(None)?; - seq.serialize_element(&name)?; + if let Some(id) = self.idx { + seq.serialize_element(&id)?; + } else { + seq.serialize_element(&name)?; + } if let Some(generics) = &self.generics { seq.serialize_element(&generics)?; } @@ -325,11 +331,32 @@ impl Serialize for Type { } } +/// A type used for the search index. +#[derive(Debug)] +struct Generic { + name: String, + defid: Option, + idx: Option, +} + +impl Serialize for Generic { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + if let Some(id) = self.idx { + serializer.serialize_some(&id) + } else { + serializer.serialize_some(&self.name) + } + } +} + /// Full type of functions/methods in the search index. #[derive(Debug)] struct IndexItemFunctionType { - inputs: Vec, - output: Option>, + inputs: Vec, + output: Option>, } impl Serialize for IndexItemFunctionType { @@ -340,8 +367,8 @@ impl Serialize for IndexItemFunctionType { // If we couldn't figure out a type, just write `null`. let mut iter = self.inputs.iter(); if match self.output { - Some(ref output) => iter.chain(output.iter()).any(|ref i| i.name.is_none()), - None => iter.any(|ref i| i.name.is_none()), + Some(ref output) => iter.chain(output.iter()).any(|ref i| i.ty.name.is_none()), + None => iter.any(|ref i| i.ty.name.is_none()), } { serializer.serialize_none() } else { @@ -359,6 +386,34 @@ impl Serialize for IndexItemFunctionType { } } +#[derive(Debug)] +pub struct TypeWithKind { + ty: Type, + kind: TypeKind, +} + +impl From<(Type, TypeKind)> for TypeWithKind { + fn from(x: (Type, TypeKind)) -> TypeWithKind { + TypeWithKind { + ty: x.0, + kind: x.1, + } + } +} + +impl Serialize for TypeWithKind { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_seq(None)?; + seq.serialize_element(&self.ty.name)?; + let x: ItemType = self.kind.into(); + seq.serialize_element(&x)?; + seq.end() + } +} + thread_local!(static CACHE_KEY: RefCell> = Default::default()); thread_local!(pub static CURRENT_DEPTH: Cell = Cell::new(0)); diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 4198369eca8..746146c5084 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; use serde::Serialize; use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType}; -use super::{RenderInfo, Type}; +use super::{Generic, RenderInfo, Type, TypeWithKind}; /// Indicates where an external crate can be found. pub enum ExternalLocation { @@ -588,19 +588,22 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut lastpathid = 0usize; for item in search_index { - item.parent_idx = item.parent.map(|defid| { - if defid_to_pathid.contains_key(&defid) { - *defid_to_pathid.get(&defid).expect("no pathid") - } else { - let pathid = lastpathid; - defid_to_pathid.insert(defid, pathid); - lastpathid += 1; + item.parent_idx = item.parent.and_then(|defid| { + if defid_to_pathid.contains_key(&defid) { + defid_to_pathid.get(&defid).map(|x| *x) + } else { + let pathid = lastpathid; + defid_to_pathid.insert(defid, pathid); + lastpathid += 1; - let &(ref fqp, short) = paths.get(&defid).unwrap(); + if let Some(&(ref fqp, short)) = paths.get(&defid) { crate_paths.push((short, fqp.last().unwrap().clone())); - pathid + Some(pathid) + } else { + None } - }); + } + }); // Omit the parent path if it is same to that of the prior item. if lastpath == item.path { @@ -647,12 +650,15 @@ fn get_index_search_type(item: &clean::Item) -> Option { _ => return None, }; - let inputs = - all_types.iter().map(|arg| get_index_type(&arg)).filter(|a| a.name.is_some()).collect(); + let inputs = all_types + .iter() + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) + .filter(|a| a.ty.name.is_some()) + .collect(); let output = ret_types .iter() - .map(|arg| get_index_type(&arg)) - .filter(|a| a.name.is_some()) + .map(|(ty, kind)| TypeWithKind::from((get_index_type(&ty), *kind))) + .filter(|a| a.ty.name.is_some()) .collect::>(); let output = if output.is_empty() { None } else { Some(output) }; @@ -661,6 +667,8 @@ fn get_index_search_type(item: &clean::Item) -> Option { fn get_index_type(clean_type: &clean::Type) -> Type { let t = Type { + ty: clean_type.def_id(), + idx: None, name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()), generics: get_generics(clean_type), }; @@ -685,12 +693,15 @@ fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option } } -fn get_generics(clean_type: &clean::Type) -> Option> { +fn get_generics(clean_type: &clean::Type) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() - .filter_map(|t| get_index_type_name(t, false)) - .map(|s| s.to_ascii_lowercase()) + .filter_map(|t| if let Some(name) = get_index_type_name(t, false) { + Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None }) + } else { + None + }) .collect::>(); if r.is_empty() { None } else { Some(r) } }) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a799aed6985..c936be1cfb3 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -523,13 +523,14 @@ function getSearchElement() { } function initSearch(rawSearchIndex) { - var currentResults, index, searchIndex; var MAX_LEV_DISTANCE = 3; var MAX_RESULTS = 200; var GENERICS_DATA = 1; var NAME = 0; var INPUTS_DATA = 0; var OUTPUT_DATA = 1; + var NO_TYPE_FILTER = -1; + var currentResults, index, searchIndex; var params = getQueryStringParams(); // Populate search bar with query string search term when provided, @@ -556,7 +557,7 @@ function getSearchElement() { return i; } } - return -1; + return NO_TYPE_FILTER; } var valLower = query.query.toLowerCase(), @@ -719,6 +720,13 @@ function getSearchElement() { }; } + function getObjectFromId(id) { + if (typeof id === "number") { + return searchIndex[id]; + } + return {'name': id}; + } + function checkGenerics(obj, val) { // The names match, but we need to be sure that all generics kinda // match as well. @@ -735,8 +743,10 @@ function getSearchElement() { for (var y = 0; y < vlength; ++y) { var lev = { pos: -1, lev: MAX_LEV_DISTANCE + 1}; var elength = elems.length; + var firstGeneric = getObjectFromId(val.generics[y]).name; for (var x = 0; x < elength; ++x) { - var tmp_lev = levenshtein(elems[x], val.generics[y]); + var tmp_lev = levenshtein(getObjectFromId(elems[x]).name, + firstGeneric); if (tmp_lev < lev.lev) { lev.lev = tmp_lev; lev.pos = x; @@ -771,8 +781,9 @@ function getSearchElement() { for (var y = 0; allFound === true && y < val.generics.length; ++y) { allFound = false; + var firstGeneric = getObjectFromId(val.generics[y]).name; for (x = 0; allFound === false && x < elems.length; ++x) { - allFound = elems[x] === val.generics[y]; + allFound = getObjectFromId(elems[x]).name === firstGeneric; } if (allFound === true) { elems.splice(x - 1, 1); @@ -829,16 +840,23 @@ function getSearchElement() { return lev_distance + 1; } - function findArg(obj, val, literalSearch) { + function findArg(obj, val, literalSearch, typeFilter) { var lev_distance = MAX_LEV_DISTANCE + 1; - if (obj && obj.type && obj.type[INPUTS_DATA] && - obj.type[INPUTS_DATA].length > 0) { + if (obj && obj.type && obj.type[INPUTS_DATA] && obj.type[INPUTS_DATA].length > 0) { var length = obj.type[INPUTS_DATA].length; for (var i = 0; i < length; i++) { - var tmp = checkType(obj.type[INPUTS_DATA][i], val, literalSearch); - if (literalSearch === true && tmp === true) { - return true; + var tmp = obj.type[INPUTS_DATA][i]; + if (typePassesFilter(typeFilter, tmp[1]) === false) { + continue; + } + tmp[0] = tmp[NAME]; + var tmp = checkType(tmp, val, literalSearch); + if (literalSearch === true) { + if (tmp === true) { + return true; + } + continue; } lev_distance = Math.min(tmp, lev_distance); if (lev_distance === 0) { @@ -849,19 +867,20 @@ function getSearchElement() { return literalSearch === true ? false : lev_distance; } - function checkReturned(obj, val, literalSearch) { + function checkReturned(obj, val, literalSearch, typeFilter) { var lev_distance = MAX_LEV_DISTANCE + 1; if (obj && obj.type && obj.type.length > OUTPUT_DATA) { var ret = obj.type[OUTPUT_DATA]; - if (!obj.type[OUTPUT_DATA].length) { + if (typeof ret[0] === "string") { ret = [ret]; } for (var x = 0; x < ret.length; ++x) { var r = ret[x]; - if (typeof r === "string") { - r = [r]; + if (typePassesFilter(typeFilter, r[1]) === false) { + continue; } + r[0] = r[NAME]; var tmp = checkType(r, val, literalSearch); if (literalSearch === true) { if (tmp === true) { @@ -917,7 +936,7 @@ function getSearchElement() { function typePassesFilter(filter, type) { // No filter - if (filter < 0) return true; + if (filter <= NO_TYPE_FILTER) return true; // Exact match if (filter === type) return true; @@ -926,11 +945,13 @@ function getSearchElement() { var name = itemTypes[type]; switch (itemTypes[filter]) { case "constant": - return (name == "associatedconstant"); + return name === "associatedconstant"; case "fn": - return (name == "method" || name == "tymethod"); + return name === "method" || name === "tymethod"; case "type": - return (name == "primitive" || name == "keyword"); + return name === "primitive" || name === "associatedtype"; + case "trait": + return name === "traitalias"; } // No match @@ -959,42 +980,33 @@ function getSearchElement() { if (filterCrates !== undefined && searchIndex[i].crate !== filterCrates) { continue; } - in_args = findArg(searchIndex[i], val, true); - returned = checkReturned(searchIndex[i], val, true); + in_args = findArg(searchIndex[i], val, true, typeFilter); + returned = checkReturned(searchIndex[i], val, true, typeFilter); ty = searchIndex[i]; fullId = generateId(ty); - if (searchWords[i] === val.name) { - // filter type: ... queries - if (typePassesFilter(typeFilter, searchIndex[i].ty) && - results[fullId] === undefined) - { - results[fullId] = {id: i, index: -1}; - } - } else if ((in_args === true || returned === true) && - typePassesFilter(typeFilter, searchIndex[i].ty)) { - if (in_args === true || returned === true) { - if (in_args === true) { - results_in_args[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - if (returned === true) { - results_returned[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } - } else { - results[fullId] = { - id: i, - index: -1, - dontValidate: true, - }; - } + if (searchWords[i] === val.name + && typePassesFilter(typeFilter, searchIndex[i].ty) + && results[fullId] === undefined) { + results[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (in_args === true && results_in_args[fullId] === undefined) { + results_in_args[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; + } + if (returned === true && results_returned[fullId] === undefined) { + results_returned[fullId] = { + id: i, + index: -1, + dontValidate: true, + }; } } query.inputs = [val]; @@ -1025,7 +1037,7 @@ function getSearchElement() { // allow searching for void (no output) functions as well var typeOutput = type.length > OUTPUT_DATA ? type[OUTPUT_DATA].name : ""; - returned = checkReturned(ty, output, true); + returned = checkReturned(ty, output, true, NO_TYPE_FILTER); if (output.name === "*" || returned === true) { in_args = false; var is_module = false; @@ -1126,16 +1138,8 @@ function getSearchElement() { lev += 1; } } - if ((in_args = findArg(ty, valGenerics)) <= MAX_LEV_DISTANCE) { - if (typePassesFilter(typeFilter, ty.ty) === false) { - in_args = MAX_LEV_DISTANCE + 1; - } - } - if ((returned = checkReturned(ty, valGenerics)) <= MAX_LEV_DISTANCE) { - if (typePassesFilter(typeFilter, ty.ty) === false) { - returned = MAX_LEV_DISTANCE + 1; - } - } + in_args = findArg(ty, valGenerics, false, typeFilter); + returned = checkReturned(ty, valGenerics, false, typeFilter); lev += lev_add; if (lev > 0 && val.length > 3 && searchWords[j].indexOf(val) > -1) { diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js new file mode 100644 index 00000000000..6cdeefd10ca --- /dev/null +++ b/src/test/rustdoc-js-std/return-specific.js @@ -0,0 +1,7 @@ +const QUERY = 'struct:chunksmut'; + +const EXPECTED = { + 'returned': [ + { 'path': 'std::slice::chunks_mut', 'name': 'chunks_mut' }, + ], +}; From 2f44857735d813d54713782e58f8b971fcc0d265 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Feb 2020 18:23:09 +0100 Subject: [PATCH 1185/1250] Update JS results tester --- src/test/rustdoc-js-std/return-specific.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc-js-std/return-specific.js b/src/test/rustdoc-js-std/return-specific.js index 6cdeefd10ca..d9a910553b8 100644 --- a/src/test/rustdoc-js-std/return-specific.js +++ b/src/test/rustdoc-js-std/return-specific.js @@ -1,7 +1,10 @@ -const QUERY = 'struct:chunksmut'; +const QUERY = 'struct:string'; const EXPECTED = { + 'in_args': [ + { 'path': 'std::string::String', 'name': 'ne' }, + ], 'returned': [ - { 'path': 'std::slice::chunks_mut', 'name': 'chunks_mut' }, + { 'path': 'std::string::String', 'name': 'add' }, ], }; From e78c451733f90307cbb34bc6527b0ad4d6c26915 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Feb 2020 18:23:52 +0100 Subject: [PATCH 1186/1250] Add tests for new of variables --- src/test/rustdoc-js-std/return-specific-literal.js | 10 ++++++++++ src/tools/rustdoc-js-std/tester.js | 4 ++-- 2 files changed, 12 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc-js-std/return-specific-literal.js diff --git a/src/test/rustdoc-js-std/return-specific-literal.js b/src/test/rustdoc-js-std/return-specific-literal.js new file mode 100644 index 00000000000..c7c347240b7 --- /dev/null +++ b/src/test/rustdoc-js-std/return-specific-literal.js @@ -0,0 +1,10 @@ +const QUERY = 'struct:"string"'; + +const EXPECTED = { + 'in_args': [ + { 'path': 'std::string::String', 'name': 'ne' }, + ], + 'returned': [ + { 'path': 'std::string::String', 'name': 'add' }, + ], +}; diff --git a/src/tools/rustdoc-js-std/tester.js b/src/tools/rustdoc-js-std/tester.js index 19cf0483b76..08930ff1227 100644 --- a/src/tools/rustdoc-js-std/tester.js +++ b/src/tools/rustdoc-js-std/tester.js @@ -263,7 +263,7 @@ function main(argv) { finalJS = ""; var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", "TY_PRIMITIVE", "TY_KEYWORD", "levenshtein_row2"]; @@ -336,7 +336,7 @@ function main(argv) { console.log("OK"); } }); - return errors; + return errors > 0 ? 1 : 0; } process.exit(main(process.argv)); From 5654cde729c99f894507141c391e0e8b2311e2fb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 23 Feb 2020 19:09:00 +0100 Subject: [PATCH 1187/1250] formatting --- src/librustdoc/html/render.rs | 5 +--- src/librustdoc/html/render/cache.rs | 36 +++++++++++++++-------------- src/librustdoc/html/static/main.js | 10 ++++---- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 8d60e087e04..d21fdeb492e 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -394,10 +394,7 @@ pub struct TypeWithKind { impl From<(Type, TypeKind)> for TypeWithKind { fn from(x: (Type, TypeKind)) -> TypeWithKind { - TypeWithKind { - ty: x.0, - kind: x.1, - } + TypeWithKind { ty: x.0, kind: x.1 } } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 746146c5084..90bbc8929c0 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -589,21 +589,21 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { for item in search_index { item.parent_idx = item.parent.and_then(|defid| { - if defid_to_pathid.contains_key(&defid) { - defid_to_pathid.get(&defid).map(|x| *x) - } else { - let pathid = lastpathid; - defid_to_pathid.insert(defid, pathid); - lastpathid += 1; - - if let Some(&(ref fqp, short)) = paths.get(&defid) { - crate_paths.push((short, fqp.last().unwrap().clone())); - Some(pathid) + if defid_to_pathid.contains_key(&defid) { + defid_to_pathid.get(&defid).map(|x| *x) } else { - None + let pathid = lastpathid; + defid_to_pathid.insert(defid, pathid); + lastpathid += 1; + + if let Some(&(ref fqp, short)) = paths.get(&defid) { + crate_paths.push((short, fqp.last().unwrap().clone())); + Some(pathid) + } else { + None + } } - } - }); + }); // Omit the parent path if it is same to that of the prior item. if lastpath == item.path { @@ -697,10 +697,12 @@ fn get_generics(clean_type: &clean::Type) -> Option> { clean_type.generics().and_then(|types| { let r = types .iter() - .filter_map(|t| if let Some(name) = get_index_type_name(t, false) { - Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None }) - } else { - None + .filter_map(|t| { + if let Some(name) = get_index_type_name(t, false) { + Some(Generic { name: name.to_ascii_lowercase(), defid: t.def_id(), idx: None }) + } else { + None + } }) .collect::>(); if r.is_empty() { None } else { Some(r) } diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index c936be1cfb3..fc07e9f8b03 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -850,8 +850,7 @@ function getSearchElement() { if (typePassesFilter(typeFilter, tmp[1]) === false) { continue; } - tmp[0] = tmp[NAME]; - var tmp = checkType(tmp, val, literalSearch); + tmp = checkType(tmp, val, literalSearch); if (literalSearch === true) { if (tmp === true) { return true; @@ -876,12 +875,11 @@ function getSearchElement() { ret = [ret]; } for (var x = 0; x < ret.length; ++x) { - var r = ret[x]; - if (typePassesFilter(typeFilter, r[1]) === false) { + var tmp = ret[x]; + if (typePassesFilter(typeFilter, tmp[1]) === false) { continue; } - r[0] = r[NAME]; - var tmp = checkType(r, val, literalSearch); + tmp = checkType(r, val, literalSearch); if (literalSearch === true) { if (tmp === true) { return true; From d964e60e4fffc95e8c1aee90badafdc83e9ea421 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Mar 2020 15:53:16 +0100 Subject: [PATCH 1188/1250] Rename render::Type to improve naming --- src/librustdoc/html/render.rs | 10 +++++----- src/librustdoc/html/render/cache.rs | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index d21fdeb492e..9e1e11c54d0 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -302,14 +302,14 @@ impl Serialize for IndexItem { /// A type used for the search index. #[derive(Debug)] -struct Type { +struct RenderType { ty: Option, idx: Option, name: Option, generics: Option>, } -impl Serialize for Type { +impl Serialize for RenderType { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -388,12 +388,12 @@ impl Serialize for IndexItemFunctionType { #[derive(Debug)] pub struct TypeWithKind { - ty: Type, + ty: RenderType, kind: TypeKind, } -impl From<(Type, TypeKind)> for TypeWithKind { - fn from(x: (Type, TypeKind)) -> TypeWithKind { +impl From<(RenderType, TypeKind)> for TypeWithKind { + fn from(x: (RenderType, TypeKind)) -> TypeWithKind { TypeWithKind { ty: x.0, kind: x.1 } } } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 90bbc8929c0..ed0de2b3119 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -12,7 +12,7 @@ use std::path::{Path, PathBuf}; use serde::Serialize; use super::{plain_summary_line, shorten, Impl, IndexItem, IndexItemFunctionType, ItemType}; -use super::{Generic, RenderInfo, Type, TypeWithKind}; +use super::{Generic, RenderInfo, RenderType, TypeWithKind}; /// Indicates where an external crate can be found. pub enum ExternalLocation { @@ -665,8 +665,8 @@ fn get_index_search_type(item: &clean::Item) -> Option { Some(IndexItemFunctionType { inputs, output }) } -fn get_index_type(clean_type: &clean::Type) -> Type { - let t = Type { +fn get_index_type(clean_type: &clean::Type) -> RenderType { + let t = RenderType { ty: clean_type.def_id(), idx: None, name: get_index_type_name(clean_type, true).map(|s| s.to_ascii_lowercase()), From 496256c561e43354710243e1882f8e5fa1fe9a0a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 9 Mar 2020 14:47:24 +0100 Subject: [PATCH 1189/1250] Update src/librustdoc/html/static/main.js Fix variable name Co-Authored-By: Mazdak Farrokhzad --- src/librustdoc/html/static/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index fc07e9f8b03..3f12fb893a4 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -879,7 +879,7 @@ function getSearchElement() { if (typePassesFilter(typeFilter, tmp[1]) === false) { continue; } - tmp = checkType(r, val, literalSearch); + tmp = checkType(tmp, val, literalSearch); if (literalSearch === true) { if (tmp === true) { return true; From 7894509b000157185b10cfae64ac1e88acd88f4a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 16 Mar 2020 18:51:55 +0100 Subject: [PATCH 1190/1250] Fiddle `ParamEnv` through to a place that used to use `ParamEnv::empty` in a buggy manner --- src/librustc/ty/inhabitedness/mod.rs | 49 +++++++++++++------ src/librustc_lint/unused.rs | 7 ++- .../build/matches/simplify.rs | 7 ++- src/librustc_mir_build/hair/pattern/_match.rs | 4 +- src/librustc_passes/liveness.rs | 21 ++++++-- 5 files changed, 64 insertions(+), 24 deletions(-) diff --git a/src/librustc/ty/inhabitedness/mod.rs b/src/librustc/ty/inhabitedness/mod.rs index 144e3bc9c8b..b166c4dea0c 100644 --- a/src/librustc/ty/inhabitedness/mod.rs +++ b/src/librustc/ty/inhabitedness/mod.rs @@ -90,30 +90,46 @@ impl<'tcx> TyCtxt<'tcx> { /// ``` /// This code should only compile in modules where the uninhabitedness of Foo is /// visible. - pub fn is_ty_uninhabited_from(self, module: DefId, ty: Ty<'tcx>) -> bool { + pub fn is_ty_uninhabited_from( + self, + module: DefId, + ty: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { // To check whether this type is uninhabited at all (not just from the // given node), you could check whether the forest is empty. // ``` // forest.is_empty() // ``` - ty.uninhabited_from(self).contains(self, module) + ty.uninhabited_from(self, param_env).contains(self, module) } - pub fn is_ty_uninhabited_from_any_module(self, ty: Ty<'tcx>) -> bool { - !ty.uninhabited_from(self).is_empty() + pub fn is_ty_uninhabited_from_any_module( + self, + ty: Ty<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> bool { + !ty.uninhabited_from(self, param_env).is_empty() } } impl<'tcx> AdtDef { /// Calculates the forest of `DefId`s from which this ADT is visibly uninhabited. - fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>) -> DefIdForest { + fn uninhabited_from( + &self, + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ) -> DefIdForest { // Non-exhaustive ADTs from other crates are always considered inhabited. if self.is_variant_list_non_exhaustive() && !self.did.is_local() { DefIdForest::empty() } else { DefIdForest::intersection( tcx, - self.variants.iter().map(|v| v.uninhabited_from(tcx, substs, self.adt_kind())), + self.variants + .iter() + .map(|v| v.uninhabited_from(tcx, substs, self.adt_kind(), param_env)), ) } } @@ -126,6 +142,7 @@ impl<'tcx> VariantDef { tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, adt_kind: AdtKind, + param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest { let is_enum = match adt_kind { // For now, `union`s are never considered uninhabited. @@ -140,7 +157,7 @@ impl<'tcx> VariantDef { } else { DefIdForest::union( tcx, - self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum)), + self.fields.iter().map(|f| f.uninhabited_from(tcx, substs, is_enum, param_env)), ) } } @@ -153,8 +170,9 @@ impl<'tcx> FieldDef { tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, is_enum: bool, + param_env: ty::ParamEnv<'tcx>, ) -> DefIdForest { - let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx); + let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env); // FIXME(canndrew): Currently enum fields are (incorrectly) stored with // `Visibility::Invisible` so we need to override `self.vis` if we're // dealing with an enum. @@ -176,20 +194,21 @@ impl<'tcx> FieldDef { impl<'tcx> TyS<'tcx> { /// Calculates the forest of `DefId`s from which this type is visibly uninhabited. - fn uninhabited_from(&self, tcx: TyCtxt<'tcx>) -> DefIdForest { + fn uninhabited_from(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> DefIdForest { match self.kind { - Adt(def, substs) => def.uninhabited_from(tcx, substs), + Adt(def, substs) => def.uninhabited_from(tcx, substs, param_env), Never => DefIdForest::full(tcx), - Tuple(ref tys) => { - DefIdForest::union(tcx, tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx))) - } + Tuple(ref tys) => DefIdForest::union( + tcx, + tys.iter().map(|ty| ty.expect_ty().uninhabited_from(tcx, param_env)), + ), - Array(ty, len) => match len.try_eval_usize(tcx, ty::ParamEnv::empty()) { + Array(ty, len) => match len.try_eval_usize(tcx, param_env) { // If the array is definitely non-empty, it's uninhabited if // the type of its elements is uninhabited. - Some(n) if n != 0 => ty.uninhabited_from(tcx), + Some(n) if n != 0 => ty.uninhabited_from(tcx, param_env), _ => DefIdForest::empty(), }, diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index d0bbc5ac26d..2ac461a0eb2 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -124,7 +124,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { descr_post: &str, plural_len: usize, ) -> bool { - if ty.is_unit() || cx.tcx.is_ty_uninhabited_from(cx.tcx.parent_module(expr.hir_id), ty) + if ty.is_unit() + || cx.tcx.is_ty_uninhabited_from( + cx.tcx.parent_module(expr.hir_id), + ty, + cx.param_env, + ) { return true; } diff --git a/src/librustc_mir_build/build/matches/simplify.rs b/src/librustc_mir_build/build/matches/simplify.rs index 80fa0c44860..aea4f5f1b3a 100644 --- a/src/librustc_mir_build/build/matches/simplify.rs +++ b/src/librustc_mir_build/build/matches/simplify.rs @@ -209,7 +209,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { i == variant_index || { self.hir.tcx().features().exhaustive_patterns && !v - .uninhabited_from(self.hir.tcx(), substs, adt_def.adt_kind()) + .uninhabited_from( + self.hir.tcx(), + substs, + adt_def.adt_kind(), + self.hir.param_env, + ) .is_empty() } }) && (adt_def.did.is_local() diff --git a/src/librustc_mir_build/hair/pattern/_match.rs b/src/librustc_mir_build/hair/pattern/_match.rs index 37ad5f5ea4e..486dd3579d2 100644 --- a/src/librustc_mir_build/hair/pattern/_match.rs +++ b/src/librustc_mir_build/hair/pattern/_match.rs @@ -598,7 +598,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { if self.tcx.features().exhaustive_patterns { - self.tcx.is_ty_uninhabited_from(self.module, ty) + self.tcx.is_ty_uninhabited_from(self.module, ty, self.param_env) } else { false } @@ -1267,7 +1267,7 @@ fn all_constructors<'a, 'tcx>( def.variants .iter() .filter(|v| { - !v.uninhabited_from(cx.tcx, substs, def.adt_kind()) + !v.uninhabited_from(cx.tcx, substs, def.adt_kind(), cx.param_env) .contains(cx.tcx, cx.module) }) .map(|v| Variant(v.def_id)) diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 030d0893b02..d7208a00e09 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -398,7 +398,7 @@ fn visit_fn<'tcx>( intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); // compute liveness - let mut lsets = Liveness::new(&mut fn_maps, body_id); + let mut lsets = Liveness::new(&mut fn_maps, def_id); let entry_ln = lsets.compute(&body.value); // check for various error conditions @@ -658,6 +658,7 @@ const ACC_USE: u32 = 4; struct Liveness<'a, 'tcx> { ir: &'a mut IrMaps<'tcx>, tables: &'a ty::TypeckTables<'tcx>, + param_env: ty::ParamEnv<'tcx>, s: Specials, successors: Vec, rwu_table: RWUTable, @@ -670,7 +671,7 @@ struct Liveness<'a, 'tcx> { } impl<'a, 'tcx> Liveness<'a, 'tcx> { - fn new(ir: &'a mut IrMaps<'tcx>, body: hir::BodyId) -> Liveness<'a, 'tcx> { + fn new(ir: &'a mut IrMaps<'tcx>, def_id: DefId) -> Liveness<'a, 'tcx> { // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or panic // - implicit_ret_var is a pseudo-variable that represents @@ -681,7 +682,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { clean_exit_var: ir.add_variable(CleanExit), }; - let tables = ir.tcx.body_tables(body); + let tables = ir.tcx.typeck_tables_of(def_id); + let param_env = ir.tcx.param_env(def_id); let num_live_nodes = ir.num_live_nodes; let num_vars = ir.num_vars; @@ -689,6 +691,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { Liveness { ir, tables, + param_env, s: specials, successors: vec![invalid_node(); num_live_nodes], rwu_table: RWUTable::new(num_live_nodes * num_vars), @@ -1126,7 +1129,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::Call(ref f, ref args) => { let m = self.ir.tcx.parent_module(expr.hir_id); - let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { + let succ = if self.ir.tcx.is_ty_uninhabited_from( + m, + self.tables.expr_ty(expr), + self.param_env, + ) { self.s.exit_ln } else { succ @@ -1137,7 +1144,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { hir::ExprKind::MethodCall(.., ref args) => { let m = self.ir.tcx.parent_module(expr.hir_id); - let succ = if self.ir.tcx.is_ty_uninhabited_from(m, self.tables.expr_ty(expr)) { + let succ = if self.ir.tcx.is_ty_uninhabited_from( + m, + self.tables.expr_ty(expr), + self.param_env, + ) { self.s.exit_ln } else { succ From 7e2ebb078997fcb29bd0a19efcbeb69b29bc10ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 16 Mar 2020 19:06:04 +0100 Subject: [PATCH 1191/1250] submodules: update clippy from 8485d40a to 23549a8c Changes: ```` rustup https://github.com/rust-lang/rust/pull/69738 rustup https://github.com/rust-lang/rust/pull/68944 Make use of `or_patterns` feature rustup https://github.com/rust-lang/rust/pull/69589/ Rustup to rust-lang/rust#69076 Don't convert Path to lossy str Use `into_path` Use pattern matching instead of manually checking condition Fix typo Remove git2 dependency. Document that wildcard_imports doesn't warn about `use ...::prelude::*;` Change changelog formatting Update changelog_update doc to reflect the actual ordering of the changelog Update CHANGELOG.md ```` Fixes #70007 --- Cargo.lock | 1 - src/tools/clippy | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 42049da8e6a..d1dcf99d884 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -455,7 +455,6 @@ dependencies = [ "clippy_lints", "compiletest_rs", "derive-new", - "git2", "lazy_static 1.4.0", "regex", "rustc-workspace-hack", diff --git a/src/tools/clippy b/src/tools/clippy index 8485d40a326..23549a8c362 160000 --- a/src/tools/clippy +++ b/src/tools/clippy @@ -1 +1 @@ -Subproject commit 8485d40a3264b15b92d391e99cb3d1abf8f25025 +Subproject commit 23549a8c362a403026432f65a6cb398cb10d44b7 From 9b852136109f3d29f87504c4f38a0e97d1bc2b06 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 16 Mar 2020 21:50:04 +0100 Subject: [PATCH 1192/1250] Add missing variable to load in non-std tester as well --- src/tools/rustdoc-js/tester.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 7174474be1c..143e1a7480d 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -231,7 +231,7 @@ function load_files(out_folder, crate) { finalJS = ""; var arraysToLoad = ["itemTypes"]; - var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", + var variablesToLoad = ["MAX_LEV_DISTANCE", "MAX_RESULTS", "NO_TYPE_FILTER", "GENERICS_DATA", "NAME", "INPUTS_DATA", "OUTPUT_DATA", "TY_PRIMITIVE", "TY_KEYWORD", "levenshtein_row2"]; @@ -328,7 +328,7 @@ function main(argv) { console.log("OK"); } } - return errors; + return errors > 0 ? 1 : 0; } process.exit(main(process.argv)); From cff1182bcdf0f35cdb65d4560270b6afed856064 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Thu, 6 Feb 2020 05:58:04 +0100 Subject: [PATCH 1193/1250] Fix FlattenCompat::{next, next_back} --- src/libcore/iter/adapters/flatten.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libcore/iter/adapters/flatten.rs b/src/libcore/iter/adapters/flatten.rs index 6000214af43..4202e52448d 100644 --- a/src/libcore/iter/adapters/flatten.rs +++ b/src/libcore/iter/adapters/flatten.rs @@ -264,8 +264,9 @@ where fn next(&mut self) -> Option { loop { if let Some(ref mut inner) = self.frontiter { - if let elt @ Some(_) = inner.next() { - return elt; + match inner.next() { + None => self.frontiter = None, + elt @ Some(_) => return elt, } } match self.iter.next() { @@ -351,8 +352,9 @@ where fn next_back(&mut self) -> Option { loop { if let Some(ref mut inner) = self.backiter { - if let elt @ Some(_) = inner.next_back() { - return elt; + match inner.next_back() { + None => self.backiter = None, + elt @ Some(_) => return elt, } } match self.iter.next_back() { From 8cf33b0d9d0d4948790ce2ea7f7bf786fb7759f1 Mon Sep 17 00:00:00 2001 From: Tim Vermeulen Date: Wed, 5 Feb 2020 00:09:11 +0100 Subject: [PATCH 1194/1250] Add tests --- src/libcore/tests/iter.rs | 72 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 5b41ef35065..98e3eeb982b 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + use core::cell::Cell; use core::convert::TryFrom; use core::iter::*; @@ -2940,3 +2942,73 @@ fn test_partition() { check(xs, |&x| x < 3, 3); // small check(xs, |&x| x > 6, 3); // large } + +/// An iterator that panics whenever `next` or next_back` is called +/// after `None` has already been returned. This does not violate +/// `Iterator`'s contract. Used to test that iterator adaptors don't +/// poll their inner iterators after exhausting them. +struct NonFused { + iter: I, + done: bool, +} + +impl NonFused { + fn new(iter: I) -> Self { + Self { iter, done: false } + } +} + +impl Iterator for NonFused +where + I: Iterator, +{ + type Item = I::Item; + + fn next(&mut self) -> Option { + assert!(!self.done, "this iterator has already returned None"); + self.iter.next().or_else(|| { + self.done = true; + None + }) + } +} + +impl DoubleEndedIterator for NonFused +where + I: DoubleEndedIterator, +{ + fn next_back(&mut self) -> Option { + assert!(!self.done, "this iterator has already returned None"); + self.iter.next_back().or_else(|| { + self.done = true; + None + }) + } +} + +#[test] +fn test_peekable_non_fused() { + let mut iter = NonFused::new(empty::()).peekable(); + + assert_eq!(iter.peek(), None); + assert_eq!(iter.next_back(), None); +} + +#[test] +fn test_flatten_non_fused_outer() { + let mut iter = NonFused::new(once(0..2)).flatten(); + + assert_eq!(iter.next_back(), Some(1)); + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), None); +} + +#[test] +fn test_flatten_non_fused_inner() { + let mut iter = once(0..1).chain(once(1..3)).flat_map(NonFused::new); + + assert_eq!(iter.next_back(), Some(2)); + assert_eq!(iter.next(), Some(0)); + assert_eq!(iter.next(), Some(1)); + assert_eq!(iter.next(), None); +} From 442e5ff982433ca23f47234a6d7e16358b26505e Mon Sep 17 00:00:00 2001 From: Youngsuk Kim Date: Mon, 16 Mar 2020 21:24:47 -0400 Subject: [PATCH 1195/1250] Small fixes in documentation typo fix + markdown fix for consistency --- src/librustc_mir/interpret/eval_context.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 482c143a73e..450e6b2e2d6 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -98,10 +98,10 @@ pub enum StackPopCleanup { /// Jump to the next block in the caller, or cause UB if None (that's a function /// that may never return). Also store layout of return place so /// we can validate it at that layout. - /// `ret` stores the block we jump to on a normal return, while 'unwind' - /// stores the block used for cleanup during unwinding + /// `ret` stores the block we jump to on a normal return, while `unwind` + /// stores the block used for cleanup during unwinding. Goto { ret: Option, unwind: Option }, - /// Just do nohing: Used by Main and for the box_alloc hook in miri. + /// Just do nothing: Used by Main and for the `box_alloc` hook in miri. /// `cleanup` says whether locals are deallocated. Static computation /// wants them leaked to intern what they need (and just throw away /// the entire `ecx` when it is done). From afd374ff3608570cdbc8889a52299d52ee52c7e2 Mon Sep 17 00:00:00 2001 From: 12101111 Date: Tue, 17 Mar 2020 09:57:11 +0800 Subject: [PATCH 1196/1250] Ignore wasm32 --- src/test/ui/proc-macro/crt-static.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/proc-macro/crt-static.rs b/src/test/ui/proc-macro/crt-static.rs index bed45c6a5b8..90e3d422b3c 100644 --- a/src/test/ui/proc-macro/crt-static.rs +++ b/src/test/ui/proc-macro/crt-static.rs @@ -2,6 +2,7 @@ // on musl target // override -Ctarget-feature=-crt-static from compiletest // compile-flags: -Ctarget-feature= +// ignore-wasm32 // build-pass #![crate_type = "proc-macro"] From 194de274d32215bba9364a6185ee8b9896c95295 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 16 Mar 2020 19:09:54 -0700 Subject: [PATCH 1197/1250] Update books --- src/doc/embedded-book | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/embedded-book b/src/doc/embedded-book index b81ffb7a6f4..d22a9c487c7 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit b81ffb7a6f4c5aaed92786e770e99db116aa4ebd +Subproject commit d22a9c487c78095afc4584f1d9b4ec43529d713c diff --git a/src/doc/reference b/src/doc/reference index 559e09caa96..e2f11fe4d6a 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit 559e09caa9661043744cf7af7bd88432d966f743 +Subproject commit e2f11fe4d6a5ecb471c70323197da43c70cb96b6 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index db57f899ea2..cb369ae95ca 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit db57f899ea2a56a544c8d280cbf033438666273d +Subproject commit cb369ae95ca36b841960182d26f6d5d9b2e3cc18 From 5a9ccc9ce7242afd866af3321c400c1a87c745a8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 30 Nov 2019 10:35:31 +0000 Subject: [PATCH 1198/1250] Remove `free_region_map` from `TypeckTables` It was unused. --- src/librustc/ty/context.rs | 9 --------- src/librustc_typeck/check/regionck.rs | 9 --------- src/librustc_typeck/check/writeback.rs | 6 ------ 3 files changed, 24 deletions(-) diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d6f6788697c..d7a259cc870 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -23,7 +23,6 @@ use crate::mir::{ }; use crate::traits; use crate::traits::{Clause, Clauses, Goal, GoalKind, Goals}; -use crate::ty::free_region_map::FreeRegionMap; use crate::ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; use crate::ty::query; use crate::ty::steal::Steal; @@ -416,11 +415,6 @@ pub struct TypeckTables<'tcx> { /// this field will be set to `true`. pub tainted_by_errors: bool, - /// Stores the free-region relationships that were deduced from - /// its where-clauses and parameter types. These are then - /// read-again by borrowck. - pub free_region_map: FreeRegionMap<'tcx>, - /// All the opaque types that are restricted to concrete types /// by this function. pub concrete_opaque_types: FxHashMap>, @@ -456,7 +450,6 @@ impl<'tcx> TypeckTables<'tcx> { coercion_casts: Default::default(), used_trait_imports: Lrc::new(Default::default()), tainted_by_errors: false, - free_region_map: Default::default(), concrete_opaque_types: Default::default(), upvar_list: Default::default(), generator_interior_types: Default::default(), @@ -719,7 +712,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { ref used_trait_imports, tainted_by_errors, - ref free_region_map, ref concrete_opaque_types, ref upvar_list, ref generator_interior_types, @@ -757,7 +749,6 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { coercion_casts.hash_stable(hcx, hasher); used_trait_imports.hash_stable(hcx, hasher); tainted_by_errors.hash_stable(hcx, hasher); - free_region_map.hash_stable(hcx, hasher); concrete_opaque_types.hash_stable(hcx, hasher); upvar_list.hash_stable(hcx, hasher); generator_interior_types.hash_stable(hcx, hasher); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 975c6e101a6..ecc9a423b91 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -125,9 +125,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_region_obligations(id); } rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); } /// Region checking during the WF phase for items. `wf_tys` are the @@ -169,12 +166,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); - - // In this mode, we also copy the free-region-map into the - // tables of the enclosing fcx. In the other regionck modes - // (e.g., `regionck_item`), we don't have an enclosing tables. - assert!(self.tables.borrow().free_region_map.is_empty()); - self.tables.borrow_mut().free_region_map = rcx.outlives_environment.into_free_region_map(); } } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index b8f8030e3cd..21536503ef7 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -62,7 +62,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { wbcx.visit_fru_field_types(); wbcx.visit_opaque_types(body.value.span); wbcx.visit_coercion_casts(); - wbcx.visit_free_region_map(); wbcx.visit_user_provided_tys(); wbcx.visit_user_provided_sigs(); wbcx.visit_generator_interior_types(); @@ -358,11 +357,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } - fn visit_free_region_map(&mut self) { - self.tables.free_region_map = self.fcx.tables.borrow().free_region_map.clone(); - debug_assert!(!self.tables.free_region_map.elements().any(|r| r.has_local_value())); - } - fn visit_user_provided_tys(&mut self) { let fcx_tables = self.fcx.tables.borrow(); debug_assert_eq!(fcx_tables.local_id_root, self.tables.local_id_root); From cefd0305b1e67ad95f86c273e5cf76f189a7206e Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Feb 2020 12:07:20 +0000 Subject: [PATCH 1199/1250] Don't use `TypeckTables` in NiceRegionError Regions in TypeckTables will be erased, so are unusable for error reporting. --- .../nice_region_error/different_lifetimes.rs | 11 +++ .../error_reporting/nice_region_error/mod.rs | 19 +---- .../error_reporting/nice_region_error/util.rs | 78 +++++++++---------- .../borrow_check/diagnostics/region_errors.rs | 3 +- 4 files changed, 51 insertions(+), 60 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs index 1a09729ef64..50b324c7227 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs @@ -3,6 +3,8 @@ use crate::infer::error_reporting::nice_region_error::util::AnonymousParamInfo; use crate::infer::error_reporting::nice_region_error::NiceRegionError; +use crate::infer::lexical_region_resolve::RegionResolutionError; +use crate::infer::SubregionOrigin; use rustc::util::common::ErrorReported; use rustc_errors::struct_span_err; @@ -47,6 +49,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { pub(super) fn try_report_anon_anon_conflict(&self) -> Option { let (span, sub, sup) = self.regions()?; + if let Some(RegionResolutionError::ConcreteFailure( + SubregionOrigin::ReferenceOutlivesReferent(..), + .., + )) = self.error + { + // This error doesn't make much sense in this case. + return None; + } + // Determine whether the sub and sup consist of both anonymous (elided) regions. let anon_reg_sup = self.tcx().is_suitable_region(sup)?; diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs index d8c314a0d2f..2357ee689d5 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs @@ -17,12 +17,7 @@ mod util; impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { pub fn try_report_nice_region_error(&self, error: &RegionResolutionError<'tcx>) -> bool { - if let Some(tables) = self.in_progress_tables { - let tables = tables.borrow(); - NiceRegionError::new(self, error.clone(), Some(&tables)).try_report().is_some() - } else { - NiceRegionError::new(self, error.clone(), None).try_report().is_some() - } + NiceRegionError::new(self, error.clone()).try_report().is_some() } } @@ -30,16 +25,11 @@ pub struct NiceRegionError<'cx, 'tcx> { infcx: &'cx InferCtxt<'cx, 'tcx>, error: Option>, regions: Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, } impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { - pub fn new( - infcx: &'cx InferCtxt<'cx, 'tcx>, - error: RegionResolutionError<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, - ) -> Self { - Self { infcx, error: Some(error), regions: None, tables } + pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>, error: RegionResolutionError<'tcx>) -> Self { + Self { infcx, error: Some(error), regions: None } } pub fn new_from_span( @@ -47,9 +37,8 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { span: Span, sub: ty::Region<'tcx>, sup: ty::Region<'tcx>, - tables: Option<&'cx ty::TypeckTables<'tcx>>, ) -> Self { - Self { infcx, error: None, regions: Some((span, sub, sup)), tables } + Self { infcx, error: None, regions: Some((span, sub, sup)) } } fn tcx(&self) -> TyCtxt<'tcx> { diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs index cab632935fd..de72c276595 100644 --- a/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs +++ b/src/librustc_infer/infer/error_reporting/nice_region_error/util.rs @@ -51,52 +51,44 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }; let hir = &self.tcx().hir(); - if let Some(hir_id) = hir.as_local_hir_id(id) { - if let Some(body_id) = hir.maybe_body_owned_by(hir_id) { - let body = hir.body(body_id); - let owner_id = hir.body_owner(body_id); - let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); - if let Some(tables) = self.tables { - body.params - .iter() - .enumerate() - .filter_map(|(index, param)| { - // May return None; sometimes the tables are not yet populated. - let ty_hir_id = fn_decl.inputs[index].hir_id; - let param_ty_span = hir.span(ty_hir_id); - let ty = tables.node_type_opt(param.hir_id)?; - let mut found_anon_region = false; - let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { - if *r == *anon_region { - found_anon_region = true; - replace_region - } else { - r - } - }); - if found_anon_region { - let is_first = index == 0; - Some(AnonymousParamInfo { - param, - param_ty: new_param_ty, - param_ty_span, - bound_region, - is_first, - }) - } else { - None - } - }) - .next() + let hir_id = hir.as_local_hir_id(id)?; + let body_id = hir.maybe_body_owned_by(hir_id)?; + let body = hir.body(body_id); + let owner_id = hir.body_owner(body_id); + let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap(); + let poly_fn_sig = self.tcx().fn_sig(id); + let fn_sig = self.tcx().liberate_late_bound_regions(id, &poly_fn_sig); + body.params + .iter() + .enumerate() + .filter_map(|(index, param)| { + // May return None; sometimes the tables are not yet populated. + let ty = fn_sig.inputs()[index]; + let mut found_anon_region = false; + let new_param_ty = self.tcx().fold_regions(&ty, &mut false, |r, _| { + if *r == *anon_region { + found_anon_region = true; + replace_region + } else { + r + } + }); + if found_anon_region { + let ty_hir_id = fn_decl.inputs[index].hir_id; + let param_ty_span = hir.span(ty_hir_id); + let is_first = index == 0; + Some(AnonymousParamInfo { + param, + param_ty: new_param_ty, + param_ty_span, + bound_region, + is_first, + }) } else { None } - } else { - None - } - } else { - None - } + }) + .next() } // Here, we check for the case where the anonymous region diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs index f751a16cfce..494b6421fd5 100644 --- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs @@ -284,8 +284,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { debug!("report_region_error: category={:?} {:?}", category, span); // Check if we can use one of the "nice region errors". if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { - let tables = self.infcx.tcx.typeck_tables_of(self.mir_def_id); - let nice = NiceRegionError::new_from_span(self.infcx, span, o, f, Some(tables)); + let nice = NiceRegionError::new_from_span(self.infcx, span, o, f); if let Some(diag) = nice.try_report_from_nll() { diag.buffer(&mut self.errors_buffer); return; From 0a7f16e7d851f99816114cbc830c662d55376fbd Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Feb 2020 12:11:59 +0000 Subject: [PATCH 1200/1250] Erase regions in writeback Also skip duplicated region solving entirely with `-Zborrowck=mir`. --- .../infer/error_reporting/mod.rs | 13 +--- .../infer/lexical_region_resolve/mod.rs | 35 ++++++++++- src/librustc_infer/infer/mod.rs | 62 ++++++++++++------- src/librustc_trait_selection/traits/mod.rs | 4 +- src/librustc_typeck/check/dropck.rs | 4 +- src/librustc_typeck/check/regionck.rs | 12 ++-- src/librustc_typeck/check/writeback.rs | 27 ++++---- src/librustc_typeck/coherence/builtin.rs | 6 +- .../impl_wf_check/min_specialization.rs | 4 +- 9 files changed, 103 insertions(+), 64 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs index a544381f33d..ebbfcb28db2 100644 --- a/src/librustc_infer/infer/error_reporting/mod.rs +++ b/src/librustc_infer/infer/error_reporting/mod.rs @@ -49,7 +49,7 @@ use super::lexical_region_resolve::RegionResolutionError; use super::region_constraints::GenericKind; use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; -use crate::infer::{self, SuppressRegionErrors}; +use crate::infer; use crate::traits::error_reporting::report_object_safety_error; use crate::traits::{ IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode, @@ -372,17 +372,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { &self, region_scope_tree: ®ion::ScopeTree, errors: &Vec>, - suppress: SuppressRegionErrors, ) { - debug!( - "report_region_errors(): {} errors to start, suppress = {:?}", - errors.len(), - suppress - ); - - if suppress.suppressed() { - return; - } + debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them // together into a `ProcessedErrors` group: diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index b7278ecd5e4..3af10e850d5 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -7,6 +7,7 @@ use crate::infer::region_constraints::RegionConstraintData; use crate::infer::region_constraints::VarInfos; use crate::infer::region_constraints::VerifyBound; use crate::infer::RegionVariableOrigin; +use crate::infer::RegionckMode; use crate::infer::SubregionOrigin; use rustc::middle::free_region::RegionRelations; use rustc::ty::fold::TypeFoldable; @@ -33,12 +34,29 @@ pub fn resolve<'tcx>( region_rels: &RegionRelations<'_, 'tcx>, var_infos: VarInfos, data: RegionConstraintData<'tcx>, + mode: RegionckMode, ) -> (LexicalRegionResolutions<'tcx>, Vec>) { debug!("RegionConstraintData: resolve_regions()"); let mut errors = vec![]; let mut resolver = LexicalResolver { region_rels, var_infos, data }; - let values = resolver.infer_variable_values(&mut errors); - (values, errors) + match mode { + RegionckMode::Solve => { + let values = resolver.infer_variable_values(&mut errors); + (values, errors) + } + RegionckMode::Erase { suppress_errors: false } => { + // Do real inference to get errors, then erase the results. + let mut values = resolver.infer_variable_values(&mut errors); + let re_erased = region_rels.tcx.lifetimes.re_erased; + + values.values.iter_mut().for_each(|v| *v = VarValue::Value(re_erased)); + (values, errors) + } + RegionckMode::Erase { suppress_errors: true } => { + // Skip region inference entirely. + (resolver.erased_data(region_rels.tcx), Vec::new()) + } + } } /// Contains the result of lexical region resolution. Offers methods @@ -163,6 +181,19 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } + /// An erased version of the lexical region resolutions. Used when we're + /// erasing regions and suppressing errors: in item bodies with + /// `-Zborrowck=mir`. + fn erased_data(&self, tcx: TyCtxt<'tcx>) -> LexicalRegionResolutions<'tcx> { + LexicalRegionResolutions { + error_region: tcx.lifetimes.re_static, + values: IndexVec::from_elem_n( + VarValue::Value(tcx.lifetimes.re_erased), + self.num_vars(), + ), + } + } + fn dump_constraints(&self, free_regions: &RegionRelations<'_, 'tcx>) { debug!("----() Start constraint listing (context={:?}) ()----", free_regions.context); for (idx, (constraint, _)) in self.data.constraints.iter().enumerate() { diff --git a/src/librustc_infer/infer/mod.rs b/src/librustc_infer/infer/mod.rs index 9ae131c568d..c5f06d53b8f 100644 --- a/src/librustc_infer/infer/mod.rs +++ b/src/librustc_infer/infer/mod.rs @@ -79,31 +79,50 @@ pub type Bound = Option; pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result" pub type FixupResult<'tcx, T> = Result>; // "fixup result" -/// A flag that is used to suppress region errors. This is normally -/// false, but sometimes -- when we are doing region checks that the -/// NLL borrow checker will also do -- it might be set to true. -#[derive(Copy, Clone, Default, Debug)] -pub struct SuppressRegionErrors { - suppressed: bool, +/// How we should handle region solving. +/// +/// This is used so that the region values inferred by HIR region solving are +/// not exposed, and so that we can avoid doing work in HIR typeck that MIR +/// typeck will also do. +#[derive(Copy, Clone, Debug)] +pub enum RegionckMode { + /// The default mode: report region errors, don't erase regions. + Solve, + /// Erase the results of region after solving. + Erase { + /// A flag that is used to suppress region errors, when we are doing + /// region checks that the NLL borrow checker will also do -- it might + /// be set to true. + suppress_errors: bool, + }, +} + +impl Default for RegionckMode { + fn default() -> Self { + RegionckMode::Solve + } } -impl SuppressRegionErrors { +impl RegionckMode { pub fn suppressed(self) -> bool { - self.suppressed + match self { + Self::Solve => false, + Self::Erase { suppress_errors } => suppress_errors, + } } /// Indicates that the MIR borrowck will repeat these region /// checks, so we should ignore errors if NLL is (unconditionally) /// enabled. - pub fn when_nll_is_enabled(tcx: TyCtxt<'_>) -> Self { + pub fn for_item_body(tcx: TyCtxt<'_>) -> Self { // FIXME(Centril): Once we actually remove `::Migrate` also make // this always `true` and then proceed to eliminate the dead code. match tcx.borrowck_mode() { // If we're on Migrate mode, report AST region errors - BorrowckMode::Migrate => SuppressRegionErrors { suppressed: false }, + BorrowckMode::Migrate => RegionckMode::Erase { suppress_errors: false }, // If we're on MIR, don't report AST region errors as they should be reported by NLL - BorrowckMode::Mir => SuppressRegionErrors { suppressed: true }, + BorrowckMode::Mir => RegionckMode::Erase { suppress_errors: true }, } } } @@ -1207,20 +1226,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { region_context: DefId, region_map: ®ion::ScopeTree, outlives_env: &OutlivesEnvironment<'tcx>, - suppress: SuppressRegionErrors, + mode: RegionckMode, ) { assert!( self.is_tainted_by_errors() || self.inner.borrow().region_obligations.is_empty(), "region_obligations not empty: {:#?}", self.inner.borrow().region_obligations ); - - let region_rels = &RegionRelations::new( - self.tcx, - region_context, - region_map, - outlives_env.free_region_map(), - ); let (var_infos, data) = self .inner .borrow_mut() @@ -1228,8 +1240,16 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .take() .expect("regions already resolved") .into_infos_and_data(); + + let region_rels = &RegionRelations::new( + self.tcx, + region_context, + region_map, + outlives_env.free_region_map(), + ); + let (lexical_region_resolutions, errors) = - lexical_region_resolve::resolve(region_rels, var_infos, data); + lexical_region_resolve::resolve(region_rels, var_infos, data, mode); let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions)); assert!(old_value.is_none()); @@ -1240,7 +1260,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(region_map, &errors, suppress); + self.report_region_errors(region_map, &errors); } } diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 7b93982db97..43a90c4a6c1 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -21,7 +21,7 @@ mod util; pub mod wf; use crate::infer::outlives::env::OutlivesEnvironment; -use crate::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use crate::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use crate::traits::error_reporting::InferCtxtExt as _; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc::middle::region; @@ -244,7 +244,7 @@ fn do_normalize_predicates<'tcx>( region_context, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); let predicates = match infcx.fully_resolve(&predicates) { diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index dca4f9e7cbe..e48ebbbb235 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -9,7 +9,7 @@ use rustc::ty::subst::{Subst, SubstsRef}; use rustc::ty::{self, Predicate, Ty, TyCtxt}; use rustc_errors::struct_span_err; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferOk, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{InferOk, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::TraitEngineExt as _; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; @@ -139,7 +139,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>( drop_impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); Ok(()) }) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index ecc9a423b91..b6d6d3a7a87 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -85,7 +85,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::PatKind; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{self, RegionObligation, SuppressRegionErrors}; +use rustc_infer::infer::{self, RegionObligation, RegionckMode}; use rustc_span::Span; use rustc_trait_selection::infer::OutlivesEnvironmentExt; use rustc_trait_selection::opaque_types::InferCtxtExt; @@ -124,7 +124,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_body(body); rcx.visit_region_obligations(id); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } /// Region checking during the WF phase for items. `wf_tys` are the @@ -142,7 +142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.outlives_environment.add_implied_bounds(self, wf_tys, item_id, span); rcx.outlives_environment.save_implied_bounds(item_id); rcx.visit_region_obligations(item_id); - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::default()); + rcx.resolve_regions_and_report_errors(RegionckMode::default()); } /// Region check a function body. Not invoked on closures, but @@ -165,7 +165,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcx.visit_fn_body(fn_id, body, self.tcx.hir().span(fn_id)); } - rcx.resolve_regions_and_report_errors(SuppressRegionErrors::when_nll_is_enabled(self.tcx)); + rcx.resolve_regions_and_report_errors(RegionckMode::for_item_body(self.tcx)); } } @@ -346,7 +346,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.select_all_obligations_or_error(); } - fn resolve_regions_and_report_errors(&self, suppress: SuppressRegionErrors) { + fn resolve_regions_and_report_errors(&self, mode: RegionckMode) { self.infcx.process_registered_region_obligations( self.outlives_environment.region_bound_pairs_map(), self.implicit_region_bound, @@ -357,7 +357,7 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> { self.subject_def_id, &self.region_scope_tree, &self.outlives_environment, - suppress, + mode, ); } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 21536503ef7..8ed6cc3a943 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -124,7 +124,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn write_ty_to_tables(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) { debug!("write_ty_to_tables({:?}, {:?})", hir_id, ty); - assert!(!ty.needs_infer() && !ty.has_placeholders()); + assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions()); self.tables.node_types_mut().insert(hir_id, ty); } @@ -326,9 +326,10 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let new_upvar_capture = match *upvar_capture { ty::UpvarCapture::ByValue => ty::UpvarCapture::ByValue, ty::UpvarCapture::ByRef(ref upvar_borrow) => { - let r = upvar_borrow.region; - let r = self.resolve(&r, &upvar_id.var_path.hir_id); - ty::UpvarCapture::ByRef(ty::UpvarBorrow { kind: upvar_borrow.kind, region: r }) + ty::UpvarCapture::ByRef(ty::UpvarBorrow { + kind: upvar_borrow.kind, + region: self.tcx().lifetimes.re_erased, + }) } }; debug!("Upvar capture for {:?} resolved to {:?}", upvar_id, new_upvar_capture); @@ -421,8 +422,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { fn visit_opaque_types(&mut self, span: Span) { for (&def_id, opaque_defn) in self.fcx.opaque_types.borrow().iter() { let hir_id = self.tcx().hir().as_local_hir_id(def_id).unwrap(); - let instantiated_ty = - self.tcx().erase_regions(&self.resolve(&opaque_defn.concrete_ty, &hir_id)); + let instantiated_ty = self.resolve(&opaque_defn.concrete_ty, &hir_id); debug_assert!(!instantiated_ty.has_escaping_bound_vars()); @@ -611,10 +611,8 @@ impl Locatable for hir::HirId { } } -/////////////////////////////////////////////////////////////////////////// -// The Resolver. This is the type folding engine that detects -// unresolved types and so forth. - +/// The Resolver. This is the type folding engine that detects +/// unresolved types and so forth. struct Resolver<'cx, 'tcx> { tcx: TyCtxt<'tcx>, infcx: &'cx InferCtxt<'cx, 'tcx>, @@ -647,7 +645,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { match self.infcx.fully_resolve(&t) { - Ok(t) => t, + Ok(t) => self.infcx.tcx.erase_regions(&t), Err(_) => { debug!("Resolver::fold_ty: input type `{:?}` not fully resolvable", t); self.report_error(t); @@ -656,15 +654,14 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> { } } - // FIXME This should be carefully checked - // We could use `self.report_error` but it doesn't accept a ty::Region, right now. fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - self.infcx.fully_resolve(&r).unwrap_or(self.tcx.lifetimes.re_static) + debug_assert!(!r.is_late_bound(), "Should not be resolving bound region."); + self.tcx.lifetimes.re_erased } fn fold_const(&mut self, ct: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> { match self.infcx.fully_resolve(&ct) { - Ok(ct) => ct, + Ok(ct) => self.infcx.tcx.erase_regions(&ct), Err(_) => { debug!("Resolver::fold_const: input const `{:?}` not fully resolvable", ct); // FIXME: we'd like to use `self.report_error`, but it doesn't yet diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 2ea7601ae65..e24d9bebf65 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{RegionckMode, TyCtxtInferExt}; use rustc_trait_selection::traits::error_reporting::InferCtxtExt; use rustc_trait_selection::traits::misc::{can_type_implement_copy, CopyImplementationError}; use rustc_trait_selection::traits::predicate_for_trait_def; @@ -307,7 +307,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: DefId) { impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); } } @@ -568,7 +568,7 @@ pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedI impl_did, ®ion_scope_tree, &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); CoerceUnsizedInfo { custom_kind: kind } diff --git a/src/librustc_typeck/impl_wf_check/min_specialization.rs b/src/librustc_typeck/impl_wf_check/min_specialization.rs index e96a8c454b8..cae88376118 100644 --- a/src/librustc_typeck/impl_wf_check/min_specialization.rs +++ b/src/librustc_typeck/impl_wf_check/min_specialization.rs @@ -75,7 +75,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_infer::infer::outlives::env::OutlivesEnvironment; -use rustc_infer::infer::{InferCtxt, SuppressRegionErrors, TyCtxtInferExt}; +use rustc_infer::infer::{InferCtxt, RegionckMode, TyCtxtInferExt}; use rustc_infer::traits::specialization_graph::Node; use rustc_span::Span; use rustc_trait_selection::traits::{self, translate_substs, wf}; @@ -162,7 +162,7 @@ fn get_impl_substs<'tcx>( impl1_def_id, &ScopeTree::default(), &outlives_env, - SuppressRegionErrors::default(), + RegionckMode::default(), ); let impl2_substs = match infcx.fully_resolve(&impl2_substs) { Ok(s) => s, From 1ee5829575e73f217674f0a4e271c2e4246546e1 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 15 Feb 2020 12:13:20 +0000 Subject: [PATCH 1201/1250] Update tests for erasing regions in typeck --- .../incremental/hashes/closure_expressions.rs | 4 +- src/test/incremental/hashes/inherent_impls.rs | 2 +- .../hashes/unary_and_binary_exprs.rs | 2 +- .../mir-opt/const-promotion-extern-static.rs | 20 +++---- .../mir-opt/no-drop-for-inactive-variant.rs | 2 +- src/test/mir-opt/remove_fake_borrows.rs | 10 ++-- .../mir-opt/storage_live_dead_in_statics.rs | 12 ++-- src/test/pretty/issue-4264.pp | 44 +++++++------- ...ansmute-size-mismatch-before-typeck.stderr | 2 +- src/test/ui/error-codes/E0121.stderr | 2 +- src/test/ui/issues/issue-21174.stderr | 4 +- src/test/ui/lint/uninitialized-zeroed.stderr | 16 ++--- .../usefulness/always-inhabited-union-ref.rs | 2 +- .../always-inhabited-union-ref.stderr | 2 +- ...free-region-ordering-caller.migrate.stderr | 58 +++++++++++++------ .../regions-free-region-ordering-caller.rs | 6 +- src/test/ui/suggestions/const-no-type.rs | 2 +- src/test/ui/suggestions/const-no-type.stderr | 2 +- src/test/ui/transmute/main.stderr | 3 +- .../typeck_type_placeholder_item.stderr | 4 +- 20 files changed, 110 insertions(+), 89 deletions(-) diff --git a/src/test/incremental/hashes/closure_expressions.rs b/src/test/incremental/hashes/closure_expressions.rs index 3d9db340f63..8edece2c8d3 100644 --- a/src/test/incremental/hashes/closure_expressions.rs +++ b/src/test/incremental/hashes/closure_expressions.rs @@ -84,8 +84,8 @@ pub fn add_type_ascription_to_parameter() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="hir_owner_items, mir_built, typeck_tables_of")] -#[rustc_clean(cfg="cfail3")] +#[rustc_clean(cfg = "cfail2", except = "hir_owner_items, typeck_tables_of")] +#[rustc_clean(cfg = "cfail3")] pub fn add_type_ascription_to_parameter() { let closure = |x: u32| x + 1u32; let _: u32 = closure(1); diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index c0b80a92df6..139c265164b 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -360,7 +360,7 @@ impl Foo { impl Foo { #[rustc_clean( cfg="cfail2", - except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of,typeck_tables_of" + except="hir_owner,hir_owner_items,generics_of,predicates_of,type_of" )] #[rustc_clean(cfg="cfail3")] pub fn add_lifetime_bound_to_lifetime_param_of_method<'a, 'b: 'a>(&self) { } diff --git a/src/test/incremental/hashes/unary_and_binary_exprs.rs b/src/test/incremental/hashes/unary_and_binary_exprs.rs index 9b63003482f..89aa0b1a58b 100644 --- a/src/test/incremental/hashes/unary_and_binary_exprs.rs +++ b/src/test/incremental/hashes/unary_and_binary_exprs.rs @@ -81,7 +81,7 @@ pub fn var_deref(x: &i32, y: &i32) -> i32 { } #[cfg(not(cfail1))] -#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built,typeck_tables_of", cfg="cfail2")] +#[rustc_clean(except="hir_owner_items,optimized_mir,mir_built", cfg="cfail2")] #[rustc_clean(cfg="cfail3")] pub fn var_deref(x: &i32, y: &i32) -> i32 { *y diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index 0d4a6d1bafd..c858a4c5ee7 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -4,9 +4,9 @@ extern "C" { static Y: i32 = 42; -static mut BAR: *const &'static i32 = [&Y].as_ptr(); +static mut BAR: *const &i32 = [&Y].as_ptr(); -static mut FOO: *const &'static i32 = [unsafe { &X }].as_ptr(); +static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); fn main() {} @@ -18,8 +18,8 @@ fn main() {} // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -35,8 +35,8 @@ fn main() {} // _4 = &(*_5); // _3 = [move _4]; // _2 = &_3; -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -50,8 +50,8 @@ fn main() {} // ... // _6 = const BAR::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { @@ -63,8 +63,8 @@ fn main() {} // ... // _6 = const FOO::promoted[0]; // _2 = &(*_6); -// _1 = move _2 as &[&'static i32] (Pointer(Unsize)); -// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; +// _1 = move _2 as &[&i32] (Pointer(Unsize)); +// _0 = const core::slice::::as_ptr(move _1) -> [return: bb2, unwind: bb1]; // } // ... // bb2: { diff --git a/src/test/mir-opt/no-drop-for-inactive-variant.rs b/src/test/mir-opt/no-drop-for-inactive-variant.rs index f9067616845..74a606af28f 100644 --- a/src/test/mir-opt/no-drop-for-inactive-variant.rs +++ b/src/test/mir-opt/no-drop-for-inactive-variant.rs @@ -27,7 +27,7 @@ fn main() { // } // bb2: { // ... -// const std::rt::begin_panic::<&'static str>(const "explicit panic") -> bb5; +// const std::rt::begin_panic::<&str>(const "explicit panic") -> bb5; // } // bb3: { // unreachable; diff --git a/src/test/mir-opt/remove_fake_borrows.rs b/src/test/mir-opt/remove_fake_borrows.rs index 294fe247c38..ea106eaf595 100644 --- a/src/test/mir-opt/remove_fake_borrows.rs +++ b/src/test/mir-opt/remove_fake_borrows.rs @@ -26,16 +26,16 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; // } // bb4: { // _4 = &shallow _1; -// _5 = &shallow ((_1 as Some).0: &' &' i32); -// _6 = &shallow (*((_1 as Some).0: &' &' i32)); -// _7 = &shallow (*(*((_1 as Some).0: &' &' i32))); +// _5 = &shallow ((_1 as Some).0: &&i32); +// _6 = &shallow (*((_1 as Some).0: &&i32)); +// _7 = &shallow (*(*((_1 as Some).0: &&i32))); // StorageLive(_8); // _8 = _2; // switchInt(move _8) -> [false: bb6, otherwise: bb5]; @@ -72,7 +72,7 @@ fn main() { // goto -> bb7; // } // bb2: { -// switchInt((*(*((_1 as Some).0: &' &' i32)))) -> [0i32: bb3, otherwise: bb1]; +// switchInt((*(*((_1 as Some).0: &&i32)))) -> [0i32: bb3, otherwise: bb1]; // } // bb3: { // goto -> bb4; diff --git a/src/test/mir-opt/storage_live_dead_in_statics.rs b/src/test/mir-opt/storage_live_dead_in_statics.rs index 5dc15286bab..1c98766b968 100644 --- a/src/test/mir-opt/storage_live_dead_in_statics.rs +++ b/src/test/mir-opt/storage_live_dead_in_statics.rs @@ -35,12 +35,12 @@ fn main() { // END RUST SOURCE // START rustc.XXX.mir_map.0.mir -// let mut _0: &'static Foo; -// let _1: &'static Foo; +// let mut _0: &Foo; +// let _1: &Foo; // let _2: Foo; -// let mut _3: &'static [(u32, u32)]; -// let mut _4: &'static [(u32, u32); 42]; -// let _5: &'static [(u32, u32); 42]; +// let mut _3: &[(u32, u32)]; +// let mut _4: &[(u32, u32); 42]; +// let _5: &[(u32, u32); 42]; // let _6: [(u32, u32); 42]; // let mut _7: (u32, u32); // let mut _8: (u32, u32); @@ -178,7 +178,7 @@ fn main() { // _6 = [move _7, move _8, move _9, move _10, move _11, move _12, move _13, move _14, move _15, move _16, move _17, move _18, move _19, move _20, move _21, move _22, move _23, move _24, move _25, move _26, move _27, move _28, move _29, move _30, move _31, move _32, move _33, move _34, move _35, move _36, move _37, move _38, move _39, move _40, move _41, move _42, move _43, move _44, move _45, move _46, move _47, move _48]; // _5 = &_6; // _4 = &(*_5); -// _3 = move _4 as &'static [(u32, u32)] (Pointer(Unsize)); +// _3 = move _4 as &[(u32, u32)] (Pointer(Unsize)); // _2 = Foo { tup: const "hi", data: move _3 }; // _1 = &_2; // _0 = &(*_1); diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index 8aa4cdeb539..ee7586bae82 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -34,29 +34,29 @@ ((::alloc::fmt::format as for<'r> fn(std::fmt::Arguments<'r>) -> std::string::String {std::fmt::format})(((::core::fmt::Arguments::new_v1 as - fn(&[&str], &[std::fmt::ArgumentV1<'_>]) -> std::fmt::Arguments<'_> {std::fmt::Arguments::<'_>::new_v1})((&([("test" - as - &'static str)] - as - [&str; 1]) - as - &[&str; 1]), - (&(match (() - as - ()) - { - () - => - ([] - as - [std::fmt::ArgumentV1<'_>; 0]), - } - as - [std::fmt::ArgumentV1<'_>; 0]) - as - &[std::fmt::ArgumentV1<'_>; 0])) + fn(&[&str], &[std::fmt::ArgumentV1]) -> std::fmt::Arguments {std::fmt::Arguments::new_v1})((&([("test" + as + &str)] + as + [&str; 1]) + as + &[&str; 1]), + (&(match (() + as + ()) + { + () + => + ([] + as + [std::fmt::ArgumentV1; 0]), + } + as + [std::fmt::ArgumentV1; 0]) + as + &[std::fmt::ArgumentV1; 0])) as - std::fmt::Arguments<'_>)) + std::fmt::Arguments)) as std::string::String); (res as std::string::String) } as std::string::String); diff --git a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr index 296a55ef160..5a477714596 100644 --- a/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr +++ b/src/test/ui/consts/transmute-size-mismatch-before-typeck.stderr @@ -21,7 +21,7 @@ LL | const ZST: &[u8] = unsafe { std::mem::transmute(1usize) }; | ^^^^^^^^^^^^^^^^^^^ | = note: source type: `usize` (word size) - = note: target type: `&'static [u8]` (2 * word size) + = note: target type: `&[u8]` (2 * word size) error: could not evaluate constant pattern --> $DIR/transmute-size-mismatch-before-typeck.rs:10:9 diff --git a/src/test/ui/error-codes/E0121.stderr b/src/test/ui/error-codes/E0121.stderr index 5a5c6b40c5a..ad854837ae5 100644 --- a/src/test/ui/error-codes/E0121.stderr +++ b/src/test/ui/error-codes/E0121.stderr @@ -14,7 +14,7 @@ LL | static BAR: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-21174.stderr b/src/test/ui/issues/issue-21174.stderr index 5ac5a8665bc..09402c3d814 100644 --- a/src/test/ui/issues/issue-21174.stderr +++ b/src/test/ui/issues/issue-21174.stderr @@ -4,8 +4,8 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | let new: T::B = unsafe { std::mem::transmute(value) }; | ^^^^^^^^^^^^^^^^^^^ | - = note: source type: `>::A` (size can vary because of ::A) - = note: target type: `>::B` (size can vary because of ::B) + = note: source type: `::A` (this type does not have a fixed size) + = note: target type: `::B` (this type does not have a fixed size) error: aborting due to previous error diff --git a/src/test/ui/lint/uninitialized-zeroed.stderr b/src/test/ui/lint/uninitialized-zeroed.stderr index 6d669184deb..bf0562713a4 100644 --- a/src/test/ui/lint/uninitialized-zeroed.stderr +++ b/src/test/ui/lint/uninitialized-zeroed.stderr @@ -1,4 +1,4 @@ -error: the type `&'static T` does not permit zero-initialization +error: the type `&T` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:29:32 | LL | let _val: &'static T = mem::zeroed(); @@ -14,7 +14,7 @@ LL | #![deny(invalid_value)] | ^^^^^^^^^^^^^ = note: references must be non-null -error: the type `&'static T` does not permit being left uninitialized +error: the type `&T` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:30:32 | LL | let _val: &'static T = mem::uninitialized(); @@ -25,7 +25,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 +error: the type `Wrap<&T>` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:32:38 | LL | let _val: Wrap<&'static T> = mem::zeroed(); @@ -40,7 +40,7 @@ note: references must be non-null (in this struct field) LL | struct Wrap { wrapped: T } | ^^^^^^^^^^ -error: the type `Wrap<&'static T>` does not permit being left uninitialized +error: the type `Wrap<&T>` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:33:38 | LL | let _val: Wrap<&'static T> = mem::uninitialized(); @@ -121,7 +121,7 @@ LL | let _val: Void = mem::uninitialized(); | = note: enums with no variants have no valid value -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:49:34 | LL | let _val: &'static i32 = mem::zeroed(); @@ -132,7 +132,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 +error: the type `&i32` does not permit being left uninitialized --> $DIR/uninitialized-zeroed.rs:50:34 | LL | let _val: &'static i32 = mem::uninitialized(); @@ -366,7 +366,7 @@ LL | let _val: NonBig = mem::uninitialized(); | = note: `NonBig` must be initialized inside its custom valid range -error: the type `&'static i32` does not permit zero-initialization +error: the type `&i32` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:84:34 | LL | let _val: &'static i32 = mem::transmute(0usize); @@ -377,7 +377,7 @@ LL | let _val: &'static i32 = mem::transmute(0usize); | = note: references must be non-null -error: the type `&'static [i32]` does not permit zero-initialization +error: the type `&[i32]` does not permit zero-initialization --> $DIR/uninitialized-zeroed.rs:85:36 | LL | let _val: &'static [i32] = mem::transmute((0usize, 0usize)); diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs index 11eae2af9c9..7d1cac8a442 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.rs @@ -21,7 +21,7 @@ fn uninhab_union() -> Foo { fn match_on_uninhab() { match uninhab_ref() { - //~^ ERROR non-exhaustive patterns: type `&'static !` is non-empty + //~^ ERROR non-exhaustive patterns: type `&!` is non-empty } match uninhab_union() { diff --git a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr index 1b1096c977a..e1079f912d0 100644 --- a/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr +++ b/src/test/ui/pattern/usefulness/always-inhabited-union-ref.stderr @@ -1,4 +1,4 @@ -error[E0004]: non-exhaustive patterns: type `&'static !` is non-empty +error[E0004]: non-exhaustive patterns: type `&!` is non-empty --> $DIR/always-inhabited-union-ref.rs:23:11 | LL | match uninhab_ref() { diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr index a33d3583552..06e1b0f1ac2 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr +++ b/src/test/ui/regions/regions-free-region-ordering-caller.migrate.stderr @@ -1,32 +1,54 @@ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b &'a usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:11:12 | -LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... LL | let z: Option<&'b &'a usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 10:14 + --> $DIR/regions-free-region-ordering-caller.rs:10:14 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 10:10 + --> $DIR/regions-free-region-ordering-caller.rs:10:10 + | +LL | fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'b Paramd<'a>`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:17:12 | -LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- - | | - | these two types are declared with different lifetimes... -LL | let y: Paramd<'a> = Paramd { x: a }; LL | let z: Option<&'b Paramd<'a>> = None; - | ^^^^^^^^^^^^^^^^^^^^^^ ...but data from `a` flows into `b` here + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'b` as defined on the function body at 15:14 + --> $DIR/regions-free-region-ordering-caller.rs:15:14 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 15:10 + --> $DIR/regions-free-region-ordering-caller.rs:15:10 + | +LL | fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ -error[E0623]: lifetime mismatch +error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references --> $DIR/regions-free-region-ordering-caller.rs:22:12 | -LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - | --------- --------- these two types are declared with different lifetimes... LL | let z: Option<&'a &'b usize> = None; - | ^^^^^^^^^^^^^^^^^^^^^ ...but data from `b` flows into `a` here + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined on the function body at 21:10 + --> $DIR/regions-free-region-ordering-caller.rs:21:10 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 21:14 + --> $DIR/regions-free-region-ordering-caller.rs:21:14 + | +LL | fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { + | ^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0623`. +For more information about this error, try `rustc --explain E0491`. diff --git a/src/test/ui/regions/regions-free-region-ordering-caller.rs b/src/test/ui/regions/regions-free-region-ordering-caller.rs index c0b12f23cdb..2bf4734cf73 100644 --- a/src/test/ui/regions/regions-free-region-ordering-caller.rs +++ b/src/test/ui/regions/regions-free-region-ordering-caller.rs @@ -8,18 +8,18 @@ struct Paramd<'a> { x: &'a usize } fn call2<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b &'a usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call3<'a, 'b>(a: &'a usize, b: &'b usize) { let y: Paramd<'a> = Paramd { x: a }; - let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0623 + let z: Option<&'b Paramd<'a>> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } fn call4<'a, 'b>(a: &'a usize, b: &'b usize) { - let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0623 + let z: Option<&'a &'b usize> = None;//[migrate]~ ERROR E0491 //[nll]~^ ERROR lifetime may not live long enough } diff --git a/src/test/ui/suggestions/const-no-type.rs b/src/test/ui/suggestions/const-no-type.rs index 99200a965dd..6b79697e983 100644 --- a/src/test/ui/suggestions/const-no-type.rs +++ b/src/test/ui/suggestions/const-no-type.rs @@ -43,4 +43,4 @@ static S = Vec::::new(); static mut SM = "abc"; //~^ ERROR missing type for `static mut` item //~| HELP provide a type for the item -//~| SUGGESTION &'static str +//~| SUGGESTION &str diff --git a/src/test/ui/suggestions/const-no-type.stderr b/src/test/ui/suggestions/const-no-type.stderr index c4f17109dc5..a7b5aa5e5b1 100644 --- a/src/test/ui/suggestions/const-no-type.stderr +++ b/src/test/ui/suggestions/const-no-type.stderr @@ -14,7 +14,7 @@ error: missing type for `static mut` item --> $DIR/const-no-type.rs:43:12 | LL | static mut SM = "abc"; - | ^^ help: provide a type for the item: `SM: &'static str` + | ^^ help: provide a type for the item: `SM: &str` error: missing type for `const` item --> $DIR/const-no-type.rs:14:7 diff --git a/src/test/ui/transmute/main.stderr b/src/test/ui/transmute/main.stderr index c72876e050f..4e781318329 100644 --- a/src/test/ui/transmute/main.stderr +++ b/src/test/ui/transmute/main.stderr @@ -4,8 +4,7 @@ error[E0512]: cannot transmute between types of different sizes, or dependently- LL | transmute(x) | ^^^^^^^^^ | - = note: source type: `>::T` (size can vary because of ::T) - = note: target type: `>::T` (size can vary because of ::T) + = note: `::T` does not have a fixed size error[E0512]: cannot transmute between types of different sizes, or dependently-sized types --> $DIR/main.rs:20:17 diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index f2d02f70f4a..dc86ab30dfe 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -70,7 +70,7 @@ LL | static TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:15:15 @@ -232,7 +232,7 @@ LL | static FN_TEST3: _ = "test"; | ^ | | | not allowed in type signatures - | help: replace `_` with the correct type: `&'static str` + | help: replace `_` with the correct type: `&str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:88:22 From aa20d96c31fed2dad509391109545d8ebba824c7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Mar 2020 15:08:11 +0100 Subject: [PATCH 1202/1250] Don't prepend with space before paren --- src/librustc_ast_pretty/pprust.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/librustc_ast_pretty/pprust.rs b/src/librustc_ast_pretty/pprust.rs index b2e6ab7c5e7..bb73e982a9c 100644 --- a/src/librustc_ast_pretty/pprust.rs +++ b/src/librustc_ast_pretty/pprust.rs @@ -148,12 +148,19 @@ pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String { // This makes comma-separated lists look slightly nicer, // and also addresses a specific regression described in issue #63896. -fn tt_prepend_space(tt: &TokenTree) -> bool { +fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool { match tt { TokenTree::Token(token) => match token.kind { token::Comma => false, _ => true, }, + TokenTree::Delimited(_, DelimToken::Paren, _) => match prev { + TokenTree::Token(token) => match token.kind { + token::Ident(_, _) => false, + _ => true, + }, + _ => true, + }, _ => true, } } @@ -650,11 +657,14 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere } fn print_tts(&mut self, tts: tokenstream::TokenStream, convert_dollar_crate: bool) { - for (i, tt) in tts.into_trees().enumerate() { - if i != 0 && tt_prepend_space(&tt) { + let mut iter = tts.into_trees().peekable(); + while let Some(tt) = iter.next() { + let show_space = + if let Some(next) = iter.peek() { tt_prepend_space(next, &tt) } else { false }; + self.print_tt(tt, convert_dollar_crate); + if show_space { self.space(); } - self.print_tt(tt, convert_dollar_crate); } } From 429b16e907238ef7f39dc7119263e661ec270b71 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Mar 2020 13:44:40 -0700 Subject: [PATCH 1203/1250] Make `newtype_index` methods const --- src/librustc_index/vec.rs | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index 7020939fa20..bae97a4fa08 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -120,10 +120,10 @@ macro_rules! newtype_index { impl $type { $v const MAX_AS_U32: u32 = $max; - $v const MAX: Self = Self::from_u32_const($max); + $v const MAX: Self = Self::from_u32($max); #[inline] - $v fn from_usize(value: usize) -> Self { + $v const fn from_usize(value: usize) -> Self { assert!(value <= ($max as usize)); unsafe { Self::from_u32_unchecked(value as u32) @@ -131,31 +131,13 @@ macro_rules! newtype_index { } #[inline] - $v fn from_u32(value: u32) -> Self { + $v const fn from_u32(value: u32) -> Self { assert!(value <= $max); unsafe { Self::from_u32_unchecked(value) } } - /// Hacky variant of `from_u32` for use in constants. - /// This version checks the "max" constraint by using an - /// invalid array dereference. - #[inline] - $v const fn from_u32_const(value: u32) -> Self { - // This will fail at const eval time unless `value <= - // max` is true (in which case we get the index 0). - // It will also fail at runtime, of course, but in a - // kind of wacky way. - let _ = ["out of range value used"][ - !(value <= $max) as usize - ]; - - unsafe { - Self { private: value } - } - } - #[inline] $v const unsafe fn from_u32_unchecked(value: u32) -> Self { Self { private: value } @@ -163,19 +145,19 @@ macro_rules! newtype_index { /// Extracts the value of this index as an integer. #[inline] - $v fn index(self) -> usize { + $v const fn index(self) -> usize { self.as_usize() } /// Extracts the value of this index as a `u32`. #[inline] - $v fn as_u32(self) -> u32 { + $v const fn as_u32(self) -> u32 { self.private } /// Extracts the value of this index as a `usize`. #[inline] - $v fn as_usize(self) -> usize { + $v const fn as_usize(self) -> usize { self.as_u32() as usize } } From 7f5a2841eaefab4e37b44d4c9fd9f60019f68c82 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Mar 2020 13:44:53 -0700 Subject: [PATCH 1204/1250] Rename `from_u32_const` -> `from_u32` --- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/mod.rs | 2 +- src/librustc_ast/node_id.rs | 2 +- src/librustc_hir/hir_id.rs | 2 +- src/librustc_index/vec.rs | 2 +- src/librustc_span/def_id.rs | 2 +- src/librustc_span/symbol.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 55ed07a97d1..ba1665fb530 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -346,7 +346,7 @@ impl<'hir> Map<'hir> { } fn get_entry(&self, id: HirId) -> Entry<'hir> { - if id.local_id == ItemLocalId::from_u32_const(0) { + if id.local_id == ItemLocalId::from_u32(0) { let owner = self.tcx.hir_owner(id.owner_def_id()); Entry { parent: owner.parent, node: owner.node } } else { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 338ff45a4ac..3f5c6c5f310 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1697,7 +1697,7 @@ rustc_index::newtype_index! { } impl UniverseIndex { - pub const ROOT: UniverseIndex = UniverseIndex::from_u32_const(0); + pub const ROOT: UniverseIndex = UniverseIndex::from_u32(0); /// Returns the "next" universe index in order -- this new index /// is considered to extend all previous universes. This diff --git a/src/librustc_ast/node_id.rs b/src/librustc_ast/node_id.rs index 58d2334a7b1..cd562c48e91 100644 --- a/src/librustc_ast/node_id.rs +++ b/src/librustc_ast/node_id.rs @@ -12,7 +12,7 @@ rustc_index::newtype_index! { rustc_data_structures::define_id_collections!(NodeMap, NodeSet, NodeId); /// `NodeId` used to represent the root of the crate. -pub const CRATE_NODE_ID: NodeId = NodeId::from_u32_const(0); +pub const CRATE_NODE_ID: NodeId = NodeId::from_u32(0); /// When parsing and doing expansions, we initially give all AST nodes this AST /// node value. Then later, in the renumber pass, we renumber them to have diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs index 6d2ec445763..a11638a3bb2 100644 --- a/src/librustc_hir/hir_id.rs +++ b/src/librustc_hir/hir_id.rs @@ -71,7 +71,7 @@ rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. pub const CRATE_HIR_ID: HirId = - HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32_const(0) }; + HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32(0) }; pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID }; diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index bae97a4fa08..d8c67f6210c 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -482,7 +482,7 @@ macro_rules! newtype_index { const $name:ident = $constant:expr, $($tokens:tt)*) => ( $(#[doc = $doc])* - $v const $name: $type = $type::from_u32_const($constant); + $v const $name: $type = $type::from_u32($constant); $crate::newtype_index!( @derives [$($derives,)*] @attrs [$(#[$attrs])*] diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index a2944782e91..af8d5ce09b5 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -25,7 +25,7 @@ pub enum CrateNum { /// Item definitions in the currently-compiled crate would have the `CrateNum` /// `LOCAL_CRATE` in their `DefId`. -pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32_const(0)); +pub const LOCAL_CRATE: CrateNum = CrateNum::Index(CrateId::from_u32(0)); impl Idx for CrateNum { #[inline] diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs index 5760e1d004e..3a6847878cf 100644 --- a/src/librustc_span/symbol.rs +++ b/src/librustc_span/symbol.rs @@ -997,7 +997,7 @@ rustc_index::newtype_index! { impl Symbol { const fn new(n: u32) -> Self { - Symbol(SymbolIndex::from_u32_const(n)) + Symbol(SymbolIndex::from_u32(n)) } /// Maps a string to its interned representation. From cc4a5770fa7d059166dd01d45c0596641905c59a Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Mar 2020 13:41:33 -0700 Subject: [PATCH 1205/1250] Add requisite feature gates for const assert --- src/librustc/lib.rs | 3 +++ src/librustc_ast/lib.rs | 2 ++ src/librustc_hir/lib.rs | 2 ++ src/librustc_index/lib.rs | 3 +++ src/librustc_mir/lib.rs | 3 +++ src/librustc_mir_build/lib.rs | 3 +++ src/librustc_span/lib.rs | 3 +++ src/librustc_target/lib.rs | 3 +++ 8 files changed, 22 insertions(+) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 24237235e0c..555a85fbfb3 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -26,6 +26,9 @@ #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(const_transmute)] #![feature(core_intrinsics)] #![feature(drain_filter)] diff --git a/src/librustc_ast/lib.rs b/src/librustc_ast/lib.rs index adb96356aae..2594cc536ac 100644 --- a/src/librustc_ast/lib.rs +++ b/src/librustc_ast/lib.rs @@ -7,7 +7,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))] #![feature(bool_to_option)] #![feature(box_syntax)] +#![feature(const_if_match)] #![feature(const_fn)] // For the `transmute` in `P::new` +#![feature(const_panic)] #![feature(const_transmute)] #![feature(crate_visibility_modifier)] #![feature(label_break_value)] diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 45f806b53f5..fa5c72b060d 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -3,7 +3,9 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] #![feature(const_fn)] // For the unsizing cast on `&[]` +#![feature(const_panic)] #![feature(in_band_lifetimes)] #![feature(specialization)] #![recursion_limit = "256"] diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs index 86dd1a29d0c..e8aa1a209e9 100644 --- a/src/librustc_index/lib.rs +++ b/src/librustc_index/lib.rs @@ -1,4 +1,7 @@ #![feature(allow_internal_unstable)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(unboxed_closures)] #![feature(test)] #![feature(fn_traits)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 284dd74ce99..7d3aba3ff03 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -9,6 +9,9 @@ Rust MIR: a lowered representation of Rust. #![feature(bool_to_option)] #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] #![feature(exhaustive_patterns)] diff --git a/src/librustc_mir_build/lib.rs b/src/librustc_mir_build/lib.rs index 3c35827d15d..5a8b5a32963 100644 --- a/src/librustc_mir_build/lib.rs +++ b/src/librustc_mir_build/lib.rs @@ -4,6 +4,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(crate_visibility_modifier)] #![feature(bool_to_option)] #![recursion_limit = "256"] diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index caa50e9a41c..1f6d10f4e8f 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -6,6 +6,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(crate_visibility_modifier)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] #![feature(optin_builtin_traits)] #![feature(specialization)] diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index 3c397eb444d..98190867d49 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -9,6 +9,9 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")] #![feature(bool_to_option)] +#![feature(const_if_match)] +#![feature(const_fn)] +#![feature(const_panic)] #![feature(nll)] #![feature(never_type)] #![feature(associated_type_bounds)] From 9ac93eee6df4ca08e69ec97a112657640deb8bb3 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Tue, 10 Mar 2020 13:51:07 -0700 Subject: [PATCH 1206/1250] Hold index of generator `self` arg in `const` --- src/librustc_mir/transform/generator.rs | 39 ++++++++++++------------- 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 7418a7519ba..a179cd31075 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -107,15 +107,15 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Deref]), }, self.tcx, @@ -125,7 +125,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -143,15 +143,15 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { } fn visit_local(&mut self, local: &mut Local, _: PlaceContext, _: Location) { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) { - if place.local == self_arg() { + if place.local == SELF_ARG { replace_base( place, Place { - local: self_arg(), + local: SELF_ARG, projection: self.tcx().intern_place_elems(&[ProjectionElem::Field( Field::new(0), self.ref_gen_ty, @@ -164,7 +164,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> { for elem in place.projection.iter() { if let PlaceElem::Index(local) = elem { - assert_ne!(*local, self_arg()); + assert_ne!(*local, SELF_ARG); } } } @@ -180,9 +180,7 @@ fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>, tcx: TyCtx place.projection = tcx.intern_place_elems(&new_projection); } -fn self_arg() -> Local { - Local::new(1) -} +const SELF_ARG: Local = Local::from_u32(1); /// Generator has not been resumed yet. const UNRESUMED: usize = GeneratorSubsts::UNRESUMED; @@ -237,7 +235,7 @@ impl TransformVisitor<'tcx> { // Create a Place referencing a generator struct field fn make_field(&self, variant_index: VariantIdx, idx: usize, ty: Ty<'tcx>) -> Place<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let base = self.tcx.mk_place_downcast_unnamed(self_place, variant_index); let mut projection = base.projection.to_vec(); projection.push(ProjectionElem::Field(Field::new(idx), ty)); @@ -247,7 +245,7 @@ impl TransformVisitor<'tcx> { // Create a statement which changes the discriminant fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo) -> Statement<'tcx> { - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); Statement { source_info, kind: StatementKind::SetDiscriminant { @@ -263,7 +261,7 @@ impl TransformVisitor<'tcx> { let local_decls_len = body.local_decls.push(temp_decl); let temp = Place::from(local_decls_len); - let self_place = Place::from(self_arg()); + let self_place = Place::from(SELF_ARG); let assign = Statement { source_info: source_info(body), kind: StatementKind::Assign(box (temp, Rvalue::Discriminant(self_place))), @@ -540,7 +538,7 @@ fn locals_live_across_suspend_points( live_locals_here.intersect(&liveness.outs[block]); // The generator argument is ignored. - live_locals_here.remove(self_arg()); + live_locals_here.remove(SELF_ARG); debug!("loc = {:?}, live_locals_here = {:?}", loc, live_locals_here); @@ -837,7 +835,6 @@ fn elaborate_generator_drops<'tcx>( // generator's resume function. let param_env = tcx.param_env(def_id); - let gen = self_arg(); let mut elaborator = DropShimElaborator { body, patch: MirPatch::new(body), tcx, param_env }; @@ -845,7 +842,7 @@ fn elaborate_generator_drops<'tcx>( let (target, unwind, source_info) = match block_data.terminator() { Terminator { source_info, kind: TerminatorKind::Drop { location, target, unwind } } => { if let Some(local) = location.as_local() { - if local == gen { + if local == SELF_ARG { (target, unwind, source_info) } else { continue; @@ -864,7 +861,7 @@ fn elaborate_generator_drops<'tcx>( elaborate_drop( &mut elaborator, *source_info, - &Place::from(gen), + &Place::from(SELF_ARG), (), *target, unwind, @@ -918,7 +915,7 @@ fn create_generator_drop_shim<'tcx>( make_generator_state_argument_indirect(tcx, def_id, &mut body); // Change the generator argument from &mut to *mut - body.local_decls[self_arg()] = LocalDecl { + body.local_decls[SELF_ARG] = LocalDecl { mutability: Mutability::Mut, ty: tcx.mk_ptr(ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut }), user_ty: UserTypeProjections::none(), @@ -933,7 +930,7 @@ fn create_generator_drop_shim<'tcx>( 0, Statement { source_info, - kind: StatementKind::Retag(RetagKind::Raw, box Place::from(self_arg())), + kind: StatementKind::Retag(RetagKind::Raw, box Place::from(SELF_ARG)), }, ) } @@ -1042,7 +1039,7 @@ fn insert_clean_drop(body: &mut BodyAndCache<'_>) -> BasicBlock { // Create a block to destroy an unresumed generators. This can only destroy upvars. let drop_clean = BasicBlock::new(body.basic_blocks().len()); let term = TerminatorKind::Drop { - location: Place::from(self_arg()), + location: Place::from(SELF_ARG), target: return_block, unwind: None, }; From 81172d8f39685fe52aac077c18ccdc899f94d363 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Mar 2020 15:08:18 +0100 Subject: [PATCH 1207/1250] Update pretty tests --- src/test/pretty/attr-literals.rs | 2 +- src/test/pretty/delimited-token-groups.rs | 7 +++---- .../pretty/issue-68710-field-attr-proc-mac-lost.rs | 2 +- src/test/ui/macros/trace-macro.stderr | 2 +- .../ui/proc-macro/attribute-spans-preserved.stdout | 2 +- .../ui/proc-macro/dollar-crate-issue-57089.stdout | 4 ++-- .../ui/proc-macro/dollar-crate-issue-62325.stdout | 4 ++-- src/test/ui/proc-macro/dollar-crate.stdout | 12 ++++++------ 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/test/pretty/attr-literals.rs b/src/test/pretty/attr-literals.rs index 9db7e27b161..44d2c5db3e6 100644 --- a/src/test/pretty/attr-literals.rs +++ b/src/test/pretty/attr-literals.rs @@ -5,7 +5,7 @@ #![feature(rustc_attrs)] fn main() { - #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name ("John"))] + #![rustc_dummy("hi", 1, 2, 1.012, pi = 3.14, bye, name("John"))] #[rustc_dummy = 8] fn f() { } diff --git a/src/test/pretty/delimited-token-groups.rs b/src/test/pretty/delimited-token-groups.rs index 7bbb7dc911f..66de0fc6cf7 100644 --- a/src/test/pretty/delimited-token-groups.rs +++ b/src/test/pretty/delimited-token-groups.rs @@ -7,7 +7,7 @@ macro_rules! mac { ($ ($ tt : tt) *) => () } mac! { struct S { field1 : u8, field2 : u16, } impl Clone for S { - fn clone () -> S + fn clone() -> S { panic ! () ; @@ -16,9 +16,8 @@ mac! { } mac! { - a - (aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa - aaaaaaaa aaaaaaaa) a + a(aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa + aaaaaaaa aaaaaaaa) a [aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa aaaaaaaa] a { diff --git a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs index 643ca761aac..031a4825959 100644 --- a/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs +++ b/src/test/pretty/issue-68710-field-attr-proc-mac-lost.rs @@ -12,5 +12,5 @@ const C: C = #[cfg(debug_assertions)] field: 0, - #[cfg(not (debug_assertions))] + #[cfg(not(debug_assertions))] field: 1,}; diff --git a/src/test/ui/macros/trace-macro.stderr b/src/test/ui/macros/trace-macro.stderr index 202a9235adb..6217decd8ef 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 ($crate :: format_args_nl ! ("Hello, World!")) ; }` + = note: to `{ $crate :: io :: _print($crate :: format_args_nl ! ("Hello, World!")) ; }` diff --git a/src/test/ui/proc-macro/attribute-spans-preserved.stdout b/src/test/ui/proc-macro/attribute-spans-preserved.stdout index faf31712156..cf9a97491f0 100644 --- a/src/test/ui/proc-macro/attribute-spans-preserved.stdout +++ b/src/test/ui/proc-macro/attribute-spans-preserved.stdout @@ -1 +1 @@ -fn main () { let y : u32 = "z" ; { let x : u32 = "y" ; } } +fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } } diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout index ea06f6c1aca..15433bebde9 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout index 619b2fd5321..73e407918ec 100644 --- a/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout +++ b/src/test/ui/proc-macro/dollar-crate-issue-62325.stdout @@ -1,5 +1,5 @@ PRINT-ATTR INPUT (DISPLAY): struct A(identity!(crate :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -55,7 +55,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct B(identity!(::dollar_crate_external :: S)); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct B (identity ! ($crate :: S)) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity ! ($crate :: S)) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", diff --git a/src/test/ui/proc-macro/dollar-crate.stdout b/src/test/ui/proc-macro/dollar-crate.stdout index 5fdc6f8ee96..e125a3e7f17 100644 --- a/src/test/ui/proc-macro/dollar-crate.stdout +++ b/src/test/ui/proc-macro/dollar-crate.stdout @@ -1,4 +1,4 @@ -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -39,7 +39,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(crate::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -80,7 +80,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(crate::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -120,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [ span: #3 bytes(LO..HI), }, ] -PRINT-BANG INPUT (DISPLAY): struct M ($crate :: S) ; +PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ; PRINT-BANG INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -161,7 +161,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [ }, ] PRINT-ATTR INPUT (DISPLAY): struct A(::dollar_crate_external::S); -PRINT-ATTR RE-COLLECTED (DISPLAY): struct A ($crate :: S) ; +PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ; PRINT-ATTR INPUT (DEBUG): TokenStream [ Ident { ident: "struct", @@ -202,7 +202,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [ }, ] PRINT-DERIVE INPUT (DISPLAY): struct D(::dollar_crate_external::S); -PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D ($crate :: S) ; +PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ; PRINT-DERIVE INPUT (DEBUG): TokenStream [ Ident { ident: "struct", From 9a017da45922efa25f3e40b6a999b47aa1af9c89 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 17 Mar 2020 15:08:44 +0100 Subject: [PATCH 1208/1250] Update rustdoc test and remove TODO comment --- src/librustdoc/html/render.rs | 1 - src/test/rustdoc/attributes.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index b3d70475bf3..d782a9d5a09 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -3151,7 +3151,6 @@ fn render_attributes(w: &mut Buffer, it: &clean::Item, top: bool) { continue; } - // FIXME: this currently renders too many spaces as in: `#[repr(C, align (8))]`. attrs.push_str(&pprust::attribute_to_string(&attr)); } if !attrs.is_empty() { diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs index d5772e183bc..e9cd3514a07 100644 --- a/src/test/rustdoc/attributes.rs +++ b/src/test/rustdoc/attributes.rs @@ -16,6 +16,6 @@ pub enum Foo { Bar, } -// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align (8))]' +// @has foo/struct.Repr.html '//*[@class="docblock attributes top-attr"]' '#[repr(C, align(8))]' #[repr(C, align(8))] pub struct Repr; From af0d6fc0070065df30af99fe8f1995548d81e903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 17 Mar 2020 00:00:00 +0000 Subject: [PATCH 1209/1250] Use copy bound in atomic operations to generate simpler MIR --- src/libcore/sync/atomic.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 3ba15968f89..220f221cdd3 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -2259,7 +2259,7 @@ fn strongest_failure_ordering(order: Ordering) -> Ordering { } #[inline] -unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { +unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { match order { Release => intrinsics::atomic_store_rel(dst, val), Relaxed => intrinsics::atomic_store_relaxed(dst, val), @@ -2270,7 +2270,7 @@ unsafe fn atomic_store(dst: *mut T, val: T, order: Ordering) { } #[inline] -unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { +unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_load_acq(dst), Relaxed => intrinsics::atomic_load_relaxed(dst), @@ -2282,7 +2282,7 @@ unsafe fn atomic_load(dst: *const T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xchg_acq(dst, val), Release => intrinsics::atomic_xchg_rel(dst, val), @@ -2295,7 +2295,7 @@ unsafe fn atomic_swap(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_add). #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xadd_acq(dst, val), Release => intrinsics::atomic_xadd_rel(dst, val), @@ -2308,7 +2308,7 @@ unsafe fn atomic_add(dst: *mut T, val: T, order: Ordering) -> T { /// Returns the previous value (like __sync_fetch_and_sub). #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xsub_acq(dst, val), Release => intrinsics::atomic_xsub_rel(dst, val), @@ -2320,7 +2320,7 @@ unsafe fn atomic_sub(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_compare_exchange( +unsafe fn atomic_compare_exchange( dst: *mut T, old: T, new: T, @@ -2346,7 +2346,7 @@ unsafe fn atomic_compare_exchange( #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_compare_exchange_weak( +unsafe fn atomic_compare_exchange_weak( dst: *mut T, old: T, new: T, @@ -2372,7 +2372,7 @@ unsafe fn atomic_compare_exchange_weak( #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_and_acq(dst, val), Release => intrinsics::atomic_and_rel(dst, val), @@ -2384,7 +2384,7 @@ unsafe fn atomic_and(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_nand_acq(dst, val), Release => intrinsics::atomic_nand_rel(dst, val), @@ -2396,7 +2396,7 @@ unsafe fn atomic_nand(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_or_acq(dst, val), Release => intrinsics::atomic_or_rel(dst, val), @@ -2408,7 +2408,7 @@ unsafe fn atomic_or(dst: *mut T, val: T, order: Ordering) -> T { #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_xor_acq(dst, val), Release => intrinsics::atomic_xor_rel(dst, val), @@ -2421,7 +2421,7 @@ unsafe fn atomic_xor(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (signed comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_max_acq(dst, val), Release => intrinsics::atomic_max_rel(dst, val), @@ -2434,7 +2434,7 @@ unsafe fn atomic_max(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (signed comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_min_acq(dst, val), Release => intrinsics::atomic_min_rel(dst, val), @@ -2447,7 +2447,7 @@ unsafe fn atomic_min(dst: *mut T, val: T, order: Ordering) -> T { /// returns the max value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umax_acq(dst, val), Release => intrinsics::atomic_umax_rel(dst, val), @@ -2460,7 +2460,7 @@ unsafe fn atomic_umax(dst: *mut T, val: T, order: Ordering) -> T { /// returns the min value (unsigned comparison) #[inline] #[cfg(target_has_atomic = "8")] -unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { +unsafe fn atomic_umin(dst: *mut T, val: T, order: Ordering) -> T { match order { Acquire => intrinsics::atomic_umin_acq(dst, val), Release => intrinsics::atomic_umin_rel(dst, val), From d79c1d3428d74b9ca5d9fc52484d726e1e1b2ac1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 10 Mar 2020 23:16:19 -0700 Subject: [PATCH 1210/1250] Update cargo --- Cargo.lock | 16 ++++++++-------- src/tools/cargo | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1dcf99d884..3f7427f5940 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -281,7 +281,7 @@ dependencies = [ [[package]] name = "cargo" -version = "0.44.0" +version = "0.45.0" dependencies = [ "anyhow", "atty", @@ -292,7 +292,6 @@ dependencies = [ "clap", "core-foundation 0.7.0", "crates-io", - "crossbeam-channel", "crossbeam-utils 0.7.0", "crypto-hash", "curl", @@ -338,6 +337,7 @@ dependencies = [ "termcolor", "toml", "unicode-width", + "unicode-xid 0.2.0", "url 2.1.0", "walkdir", "winapi 0.3.8", @@ -1234,9 +1234,9 @@ dependencies = [ [[package]] name = "git2" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26e07ef27260a78f7e8d218ebac2c72f2c4db50493741b190b6e8eade1da7c68" +checksum = "b7da16ceafe24cedd9ba02c4463a2b506b6493baf4317c79c5acb553134a3c15" dependencies = [ "bitflags", "libc", @@ -1249,9 +1249,9 @@ dependencies = [ [[package]] name = "git2-curl" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1754ec4170e7dcaf9bb43743bb16eddb8d827b2e0291deb6f220a6e16fe46a" +checksum = "502d532a2d06184beb3bc869d4d90236e60934e3382c921b203fa3c33e212bd7" dependencies = [ "curl", "git2", @@ -1778,9 +1778,9 @@ dependencies = [ [[package]] name = "libgit2-sys" -version = "0.11.0+0.99.0" +version = "0.12.0+0.99.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d1459353d397a029fb18862166338de938e6be976606bd056cf8f1a912ecf" +checksum = "05dff41ac39e7b653f5f1550886cf00ba52f8e7f57210b633cdeedb3de5b236c" dependencies = [ "cc", "libc", diff --git a/src/tools/cargo b/src/tools/cargo index bda50510d1d..7019b3ed3d5 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit bda50510d1daf6e9c53ad6ccf603da6e0fa8103f +Subproject commit 7019b3ed3d539db7429d10a343b69be8c426b576 From d5b6a20557743911ff9f90af5d8ad24c699570d3 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 12 Mar 2020 13:03:48 -0700 Subject: [PATCH 1211/1250] std: Don't abort process when printing panics in tests This commit fixes an issue when using `set_print` and friends, notably used by libtest, to avoid aborting the process if printing panics. This previously panicked due to borrowing a mutable `RefCell` twice, and this is worked around by borrowing these cells for less time, instead taking out and removing contents temporarily. Closes #69558 --- src/libstd/io/stdio.rs | 12 ++++++++---- src/test/ui/panic-while-printing.rs | 24 ++++++++++++++++++++++++ src/test/ui/test-panic-while-printing.rs | 24 ++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/panic-while-printing.rs create mode 100644 src/test/ui/test-panic-while-printing.rs diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index d410faca30d..0fb0757792e 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -792,10 +792,14 @@ fn print_to( { let result = local_s .try_with(|s| { - if let Ok(mut borrowed) = s.try_borrow_mut() { - if let Some(w) = borrowed.as_mut() { - return w.write_fmt(args); - } + // Note that we completely remove a local sink to write to in case + // our printing recursively panics/prints, so the recursive + // panic/print goes to the global sink instead of our local sink. + let prev = s.borrow_mut().take(); + if let Some(mut w) = prev { + let result = w.write_fmt(args); + *s.borrow_mut() = Some(w); + return result; } global_s().write_fmt(args) }) diff --git a/src/test/ui/panic-while-printing.rs b/src/test/ui/panic-while-printing.rs new file mode 100644 index 00000000000..7e9fa16b084 --- /dev/null +++ b/src/test/ui/panic-while-printing.rs @@ -0,0 +1,24 @@ +// run-pass +// ignore-emscripten no subprocess support + +#![feature(set_stdio)] + +use std::fmt; +use std::fmt::{Display, Formatter}; +use std::io::set_panic; + +pub struct A; + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + panic!(); + } +} + +fn main() { + set_panic(Some(Box::new(Vec::new()))); + assert!(std::panic::catch_unwind(|| { + eprintln!("{}", A); + }) + .is_err()); +} diff --git a/src/test/ui/test-panic-while-printing.rs b/src/test/ui/test-panic-while-printing.rs new file mode 100644 index 00000000000..23f45407c1a --- /dev/null +++ b/src/test/ui/test-panic-while-printing.rs @@ -0,0 +1,24 @@ +// compile-flags:--test +// run-pass +// ignore-emscripten no subprocess support + +use std::fmt; +use std::fmt::{Display, Formatter}; + +pub struct A(Vec); + +impl Display for A { + fn fmt(&self, _f: &mut Formatter<'_>) -> fmt::Result { + self.0[0]; + Ok(()) + } +} + +#[test] +fn main() { + let result = std::panic::catch_unwind(|| { + let a = A(vec![]); + eprintln!("{}", a); + }); + assert!(result.is_err()); +} From bc75cba23feb45b2d1b67ee07e6eb8264c0d5fd6 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 18:59:44 +0100 Subject: [PATCH 1212/1250] submod_path_from_attr: simplify & document --- src/librustc_parse/parser/module.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 7b46601cc7d..4965615c64c 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -179,21 +179,22 @@ impl<'a> Parser<'a> { } } + /// Derive a submodule path from the first found `#[path = "path_string"]`. + /// The provided `dir_path` is joined with the `path_string`. // Public for rustfmt usage. pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - if let Some(s) = attr::first_attr_value_str_by_name(attrs, sym::path) { - let s = s.as_str(); + // Extract path string from first `#[path = "path_string"]` attribute. + let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; + let path_string = path_string.as_str(); - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let s = s.replace("/", "\\"); - Some(dir_path.join(&*s)) - } else { - None - } + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(dir_path.join(&*path_string)) } /// Returns a path to a module. From 2899a58cab62e132dc7af7b7e0446a90b6d0feff Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:11:47 +0100 Subject: [PATCH 1213/1250] extract error_cannot_declare_mod_here --- src/librustc_parse/parser/module.rs | 54 ++++++++++++++--------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 4965615c64c..43d93e39575 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -142,41 +142,41 @@ impl<'a> Parser<'a> { } Err(err) } - DirectoryOwnership::UnownedViaMod => { - let mut err = - self.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - let src_path = self.sess.source_map().span_to_filename(id_sp); - if let FileName::Real(src_path) = src_path { - if let Some(stem) = src_path.file_stem() { - let mut dest_path = src_path.clone(); - dest_path.set_file_name(stem); - dest_path.push("mod.rs"); - err.span_note( - id_sp, - &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", - src_path.display(), - dest_path.display() - ), - ); - } - } - } - if paths.path_exists { + DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), + } + } + + fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { + let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); + if !id_sp.is_dummy() { + if let FileName::Real(src_path) = self.sess.source_map().span_to_filename(id_sp) { + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); err.span_note( id_sp, &format!( - "... or maybe `use` the module `{}` instead \ - of possibly redeclaring it", - paths.name + "maybe move this module `{}` to its own \ + directory via `{}`", + src_path.display(), + dest_path.display() ), ); } - Err(err) } } + if paths.path_exists { + err.span_note( + id_sp, + &format!( + "... or maybe `use` the module `{}` instead \ + of possibly redeclaring it", + paths.name + ), + ); + } + Err(err) } /// Derive a submodule path from the first found `#[path = "path_string"]`. From 185c1d340c5b985195abf15f69b06aa6572d793c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:15:35 +0100 Subject: [PATCH 1214/1250] extract error_decl_mod_in_block --- src/librustc_parse/parser/module.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 43d93e39575..c7d120e3cc6 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -129,23 +129,22 @@ impl<'a> Parser<'a> { DirectoryOwnership::Owned { .. } => { paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) } - DirectoryOwnership::UnownedViaBlock => { - let msg = "Cannot declare a non-inline module inside a block \ - unless it has a path attribute"; - let mut err = self.struct_span_err(id_sp, msg); - if paths.path_exists { - let msg = format!( - "Maybe `use` the module `{}` instead of redeclaring it", - paths.name - ); - err.span_note(id_sp, &msg); - } - Err(err) - } + DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id_sp, paths), DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), } } + fn error_decl_mod_in_block(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { + let msg = + "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = self.struct_span_err(id_sp, msg); + if paths.path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", paths.name); + err.span_note(id_sp, &msg); + } + Err(err) + } + fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); if !id_sp.is_dummy() { From 2db5d49d4791723b5335d5b66a0e2c304bf37d4c Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:20:31 +0100 Subject: [PATCH 1215/1250] simplify submod_path --- src/librustc_parse/parser/module.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index c7d120e3cc6..c426b073a05 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -102,20 +102,18 @@ impl<'a> Parser<'a> { id_sp: Span, ) -> PResult<'a, ModulePathSuccess> { if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { - return Ok(ModulePathSuccess { - directory_ownership: match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }, - path, - }); + let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + Some(_) => DirectoryOwnership::Owned { relative: None }, + _ => DirectoryOwnership::UnownedViaMod, + }; + return Ok(ModulePathSuccess { directory_ownership, path }); } let relative = match self.directory.ownership { From 803de3188c59ecc782db46e3fc9e9f668e260be9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:41:24 +0100 Subject: [PATCH 1216/1250] submod_path: use id.span --- src/librustc_parse/parser/module.rs | 12 +++++------- .../ui/directory_ownership/macro-expanded-mod.rs | 6 ++++-- .../ui/directory_ownership/macro-expanded-mod.stderr | 9 ++------- 3 files changed, 11 insertions(+), 16 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index c426b073a05..45387999196 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -45,14 +45,13 @@ impl<'a> Parser<'a> { pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - let id_span = self.token.span; let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &attrs, id_span)?; - self.eval_src_mod(path, directory_ownership, id.to_string(), id_span)? + self.submod_path(id, &attrs)?; + self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } @@ -99,7 +98,6 @@ impl<'a> Parser<'a> { &mut self, id: ast::Ident, outer_attrs: &[Attribute], - id_sp: Span, ) -> PResult<'a, ModulePathSuccess> { if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { @@ -125,10 +123,10 @@ impl<'a> Parser<'a> { match self.directory.ownership { DirectoryOwnership::Owned { .. } => { - paths.result.map_err(|err| self.span_fatal_err(id_sp, err)) + paths.result.map_err(|err| self.span_fatal_err(id.span, err)) } - DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id_sp, paths), - DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id_sp, paths), + DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id.span, paths), + DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id.span, paths), } } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 376c1a9cd66..1066a2ba712 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -1,7 +1,9 @@ // Test that macro-expanded non-inline modules behave correctly macro_rules! mod_decl { - ($i:ident) => { mod $i; } //~ ERROR Cannot declare a non-inline module inside a block + ($i:ident) => { + mod $i; + }; } mod macro_expanded_mod_helper { @@ -9,5 +11,5 @@ mod macro_expanded_mod_helper { } fn main() { - mod_decl!(foo); + mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index c7780c869d6..d9d8a8ffed7 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,13 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:4:25 + --> $DIR/macro-expanded-mod.rs:14:15 | -LL | ($i:ident) => { mod $i; } - | ^^ -... LL | mod_decl!(foo); - | --------------- in this macro invocation - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | ^^^ error: aborting due to previous error From 7108b7fbfea50bd311617cc217616b88c8b647c9 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 20:19:52 +0100 Subject: [PATCH 1217/1250] extract parse_mod --- src/librustc_parse/parser/module.rs | 35 +++++++++++++++-------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 45387999196..9ccafd7932a 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -31,14 +31,10 @@ impl<'a> Parser<'a> { /// Parses a source module as a crate. This is the main entry point for the parser. pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { let lo = self.token.span; - let krate = Ok(ast::Crate { - attrs: self.parse_inner_attributes()?, - module: self.parse_mod_items(&token::Eof, lo)?, - span: lo.to(self.token.span), - // Filled in by proc_macro_harness::inject() - proc_macros: Vec::new(), - }); - krate + let (module, attrs) = self.parse_mod(&token::Eof)?; + let span = lo.to(self.token.span); + let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. + Ok(ast::Crate { attrs, module, span, proc_macros }) } /// Parses a `mod { ... }` or `mod ;` item. @@ -60,17 +56,23 @@ impl<'a> Parser<'a> { self.push_directory(id, &attrs); self.expect(&token::OpenDelim(token::Brace))?; - let mod_inner_lo = self.token.span; - let inner_attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(&token::CloseDelim(token::Brace), mod_inner_lo)?; + let module = self.parse_mod(&token::CloseDelim(token::Brace))?; self.directory = old_directory; - (module, inner_attrs) + module }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) } + /// Parses the contents of a module (inner attributes followed by module items). + fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + let lo = self.token.span; + let attrs = self.parse_inner_attributes()?; + let module = self.parse_mod_items(term, lo)?; + Ok((module, attrs)) + } + /// Given a termination token, parses all of the items in a module. fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { let mut items = vec![]; @@ -268,12 +270,11 @@ impl<'a> Parser<'a> { let mut p0 = new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); p0.cfg_mods = self.cfg_mods; - let mod_inner_lo = p0.token.span; - let mod_attrs = p0.parse_inner_attributes()?; - let mut m0 = p0.parse_mod_items(&token::Eof, mod_inner_lo)?; - m0.inline = false; + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + self.sess.included_mod_stack.borrow_mut().pop(); - Ok((m0, mod_attrs)) + Ok(module) } fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { From dfcefa49ed5ce5018d279a8d1a60744da67c80c8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sat, 7 Mar 2020 19:53:25 +0100 Subject: [PATCH 1218/1250] extract error_on_circular_module --- src/librustc_parse/parser/module.rs | 30 +++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 9ccafd7932a..d203e665c95 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -254,16 +254,7 @@ impl<'a> Parser<'a> { id_sp: Span, ) -> PResult<'a, (Mod, Vec)> { let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - let len = included_mod_stack.len(); - for p in &included_mod_stack[i..len] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(self.struct_span_err(id_sp, &err[..])); - } + self.error_on_circular_module(id_sp, &path, &included_mod_stack)?; included_mod_stack.push(path.clone()); drop(included_mod_stack); @@ -277,6 +268,25 @@ impl<'a> Parser<'a> { Ok(module) } + fn error_on_circular_module( + &self, + span: Span, + path: &Path, + included_mod_stack: &[PathBuf], + ) -> PResult<'a, ()> { + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + let len = included_mod_stack.len(); + for p in &included_mod_stack[i..len] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); + } + err.push_str(&path.to_string_lossy()); + return Err(self.struct_span_err(span, &err[..])); + } + Ok(()) + } + fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { self.directory.path.push(&*path.as_str()); From ca098b16a4114fd96a4059ba3f807d33dde5ef07 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 09:28:46 +0100 Subject: [PATCH 1219/1250] detach submod_path from Parser --- src/librustc_parse/parser/diagnostics.rs | 31 -- src/librustc_parse/parser/module.rs | 348 +++++++++++++---------- 2 files changed, 192 insertions(+), 187 deletions(-) diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 8e52bb16147..87255386b9e 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -18,7 +18,6 @@ use rustc_span::{MultiSpan, Span, SpanSnippetError, DUMMY_SP}; use log::{debug, trace}; use std::mem; -use std::path::PathBuf; const TURBOFISH: &str = "use `::<...>` instead of `<...>` to specify type arguments"; @@ -41,42 +40,12 @@ pub(super) fn dummy_arg(ident: Ident) -> Param { } pub enum Error { - FileNotFoundForModule { mod_name: String, default_path: PathBuf }, - DuplicatePaths { mod_name: String, default_path: String, secondary_path: String }, UselessDocComment, } impl Error { fn span_err(self, sp: impl Into, handler: &Handler) -> DiagnosticBuilder<'_> { match self { - Error::FileNotFoundForModule { ref mod_name, ref default_path } => { - let mut err = struct_span_err!( - handler, - sp, - E0583, - "file not found for module `{}`", - mod_name, - ); - err.help(&format!( - "to create the module `{}`, create file \"{}\"", - mod_name, - default_path.display(), - )); - err - } - Error::DuplicatePaths { ref mod_name, ref default_path, ref secondary_path } => { - let mut err = struct_span_err!( - handler, - sp, - E0584, - "file for module `{}` found at both {} and {}", - mod_name, - default_path, - secondary_path, - ); - err.help("delete or rename one of them to remove the ambiguity"); - err - } Error::UselessDocComment => { let mut err = struct_span_err!( handler, diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index d203e665c95..a30d6da281a 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,4 +1,3 @@ -use super::diagnostics::Error; use super::item::ItemInfo; use super::Parser; @@ -7,18 +6,19 @@ use crate::{new_sub_parser_from_file, DirectoryOwnership}; use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; use rustc_ast::attr; use rustc_ast::token::{self, TokenKind}; -use rustc_errors::PResult; -use rustc_span::source_map::{FileName, SourceMap, Span, DUMMY_SP}; +use rustc_errors::{struct_span_err, PResult}; +use rustc_session::parse::ParseSess; +use rustc_span::source_map::{FileName, Span, DUMMY_SP}; use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; /// Information about the path to a module. // Public for rustfmt usage. -pub struct ModulePath { +pub struct ModulePath<'a> { name: String, path_exists: bool, - pub result: Result, + pub result: PResult<'a, ModulePathSuccess>, } // Public for rustfmt usage. @@ -45,8 +45,13 @@ impl<'a> Parser<'a> { let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! - let ModulePathSuccess { path, directory_ownership } = - self.submod_path(id, &attrs)?; + let ModulePathSuccess { path, directory_ownership } = submod_path( + self.sess, + id, + &attrs, + self.directory.ownership, + &self.directory.path, + )?; self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) @@ -96,155 +101,6 @@ impl<'a> Parser<'a> { Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) } - fn submod_path( - &mut self, - id: ast::Ident, - outer_attrs: &[Attribute], - ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = Parser::submod_path_from_attr(outer_attrs, &self.directory.path) { - let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { - // All `#[path]` files are treated as though they are a `mod.rs` file. - // This means that `mod foo;` declarations inside `#[path]`-included - // files are siblings, - // - // Note that this will produce weirdness when a file named `foo.rs` is - // `#[path]` included and contains a `mod foo;` declaration. - // If you encounter this, it's your own darn fault :P - Some(_) => DirectoryOwnership::Owned { relative: None }, - _ => DirectoryOwnership::UnownedViaMod, - }; - return Ok(ModulePathSuccess { directory_ownership, path }); - } - - let relative = match self.directory.ownership { - DirectoryOwnership::Owned { relative } => relative, - DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, - }; - let paths = - Parser::default_submod_path(id, relative, &self.directory.path, self.sess.source_map()); - - match self.directory.ownership { - DirectoryOwnership::Owned { .. } => { - paths.result.map_err(|err| self.span_fatal_err(id.span, err)) - } - DirectoryOwnership::UnownedViaBlock => self.error_decl_mod_in_block(id.span, paths), - DirectoryOwnership::UnownedViaMod => self.error_cannot_declare_mod_here(id.span, paths), - } - } - - fn error_decl_mod_in_block(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { - let msg = - "Cannot declare a non-inline module inside a block unless it has a path attribute"; - let mut err = self.struct_span_err(id_sp, msg); - if paths.path_exists { - let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", paths.name); - err.span_note(id_sp, &msg); - } - Err(err) - } - - fn error_cannot_declare_mod_here(&self, id_sp: Span, paths: ModulePath) -> PResult<'a, T> { - let mut err = self.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - if let FileName::Real(src_path) = self.sess.source_map().span_to_filename(id_sp) { - if let Some(stem) = src_path.file_stem() { - let mut dest_path = src_path.clone(); - dest_path.set_file_name(stem); - dest_path.push("mod.rs"); - err.span_note( - id_sp, - &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", - src_path.display(), - dest_path.display() - ), - ); - } - } - } - if paths.path_exists { - err.span_note( - id_sp, - &format!( - "... or maybe `use` the module `{}` instead \ - of possibly redeclaring it", - paths.name - ), - ); - } - Err(err) - } - - /// Derive a submodule path from the first found `#[path = "path_string"]`. - /// The provided `dir_path` is joined with the `path_string`. - // Public for rustfmt usage. - pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { - // Extract path string from first `#[path = "path_string"]` attribute. - let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; - let path_string = path_string.as_str(); - - // On windows, the base path might have the form - // `\\?\foo\bar` in which case it does not tolerate - // mixed `/` and `\` separators, so canonicalize - // `/` to `\`. - #[cfg(windows)] - let path_string = path_string.replace("/", "\\"); - - Some(dir_path.join(&*path_string)) - } - - /// Returns a path to a module. - // Public for rustfmt usage. - pub fn default_submod_path( - id: ast::Ident, - relative: Option, - dir_path: &Path, - source_map: &SourceMap, - ) -> ModulePath { - // If we're in a foo.rs file instead of a mod.rs file, - // we need to look for submodules in - // `./foo/.rs` and `./foo//mod.rs` rather than - // `./.rs` and `.//mod.rs`. - let relative_prefix_string; - let relative_prefix = if let Some(ident) = relative { - relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); - &relative_prefix_string - } else { - "" - }; - - let mod_name = id.name.to_string(); - let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); - let secondary_path_str = - format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); - let default_path = dir_path.join(&default_path_str); - let secondary_path = dir_path.join(&secondary_path_str); - let default_exists = source_map.file_exists(&default_path); - let secondary_exists = source_map.file_exists(&secondary_path); - - let result = match (default_exists, secondary_exists) { - (true, false) => Ok(ModulePathSuccess { - path: default_path, - directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, - }), - (false, true) => Ok(ModulePathSuccess { - path: secondary_path, - directory_ownership: DirectoryOwnership::Owned { relative: None }, - }), - (false, false) => { - Err(Error::FileNotFoundForModule { mod_name: mod_name.clone(), default_path }) - } - (true, true) => Err(Error::DuplicatePaths { - mod_name: mod_name.clone(), - default_path: default_path_str, - secondary_path: secondary_path_str, - }), - }; - - ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } - } - /// Reads a module from a source file. fn eval_src_mod( &mut self, @@ -308,3 +164,183 @@ impl<'a> Parser<'a> { } } } + +fn submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + outer_attrs: &[Attribute], + directory_ownership: DirectoryOwnership, + dir_path: &Path, +) -> PResult<'a, ModulePathSuccess> { + if let Some(path) = submod_path_from_attr(outer_attrs, dir_path) { + let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + // All `#[path]` files are treated as though they are a `mod.rs` file. + // This means that `mod foo;` declarations inside `#[path]`-included + // files are siblings, + // + // Note that this will produce weirdness when a file named `foo.rs` is + // `#[path]` included and contains a `mod foo;` declaration. + // If you encounter this, it's your own darn fault :P + Some(_) => DirectoryOwnership::Owned { relative: None }, + _ => DirectoryOwnership::UnownedViaMod, + }; + return Ok(ModulePathSuccess { directory_ownership, path }); + } + + let relative = match directory_ownership { + DirectoryOwnership::Owned { relative } => relative, + DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, + }; + let ModulePath { path_exists, name, result } = + default_submod_path(sess, id, relative, dir_path); + match directory_ownership { + DirectoryOwnership::Owned { .. } => Ok(result?), + DirectoryOwnership::UnownedViaBlock => { + let _ = result.map_err(|mut err| err.cancel()); + error_decl_mod_in_block(sess, id.span, path_exists, &name) + } + DirectoryOwnership::UnownedViaMod => { + let _ = result.map_err(|mut err| err.cancel()); + error_cannot_declare_mod_here(sess, id.span, path_exists, &name) + } + } +} + +fn error_decl_mod_in_block<'a, T>( + sess: &'a ParseSess, + id_sp: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; + let mut err = sess.span_diagnostic.struct_span_err(id_sp, msg); + if path_exists { + let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name); + err.span_note(id_sp, &msg); + } + Err(err) +} + +fn error_cannot_declare_mod_here<'a, T>( + sess: &'a ParseSess, + id_sp: Span, + path_exists: bool, + name: &str, +) -> PResult<'a, T> { + let mut err = + sess.span_diagnostic.struct_span_err(id_sp, "cannot declare a new module at this location"); + if !id_sp.is_dummy() { + if let FileName::Real(src_path) = sess.source_map().span_to_filename(id_sp) { + if let Some(stem) = src_path.file_stem() { + let mut dest_path = src_path.clone(); + dest_path.set_file_name(stem); + dest_path.push("mod.rs"); + err.span_note( + id_sp, + &format!( + "maybe move this module `{}` to its own \ + directory via `{}`", + src_path.display(), + dest_path.display() + ), + ); + } + } + } + if path_exists { + err.span_note( + id_sp, + &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name), + ); + } + Err(err) +} + +/// Derive a submodule path from the first found `#[path = "path_string"]`. +/// The provided `dir_path` is joined with the `path_string`. +// Public for rustfmt usage. +pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option { + // Extract path string from first `#[path = "path_string"]` attribute. + let path_string = attr::first_attr_value_str_by_name(attrs, sym::path)?; + let path_string = path_string.as_str(); + + // On windows, the base path might have the form + // `\\?\foo\bar` in which case it does not tolerate + // mixed `/` and `\` separators, so canonicalize + // `/` to `\`. + #[cfg(windows)] + let path_string = path_string.replace("/", "\\"); + + Some(dir_path.join(&*path_string)) +} + +/// Returns a path to a module. +// Public for rustfmt usage. +pub fn default_submod_path<'a>( + sess: &'a ParseSess, + id: ast::Ident, + relative: Option, + dir_path: &Path, +) -> ModulePath<'a> { + // If we're in a foo.rs file instead of a mod.rs file, + // we need to look for submodules in + // `./foo/.rs` and `./foo//mod.rs` rather than + // `./.rs` and `.//mod.rs`. + let relative_prefix_string; + let relative_prefix = if let Some(ident) = relative { + relative_prefix_string = format!("{}{}", ident.name, path::MAIN_SEPARATOR); + &relative_prefix_string + } else { + "" + }; + + let mod_name = id.name.to_string(); + let default_path_str = format!("{}{}.rs", relative_prefix, mod_name); + let secondary_path_str = + format!("{}{}{}mod.rs", relative_prefix, mod_name, path::MAIN_SEPARATOR); + let default_path = dir_path.join(&default_path_str); + let secondary_path = dir_path.join(&secondary_path_str); + let default_exists = sess.source_map().file_exists(&default_path); + let secondary_exists = sess.source_map().file_exists(&secondary_path); + + let result = match (default_exists, secondary_exists) { + (true, false) => Ok(ModulePathSuccess { + path: default_path, + directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, + }), + (false, true) => Ok(ModulePathSuccess { + path: secondary_path, + directory_ownership: DirectoryOwnership::Owned { relative: None }, + }), + (false, false) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + id.span, + E0583, + "file not found for module `{}`", + mod_name, + ); + err.help(&format!( + "to create the module `{}`, create file \"{}\"", + mod_name, + default_path.display(), + )); + Err(err) + } + (true, true) => { + let mut err = struct_span_err!( + sess.span_diagnostic, + id.span, + E0584, + "file for module `{}` found at both {} and {}", + mod_name, + default_path_str, + secondary_path_str, + ); + err.help("delete or rename one of them to remove the ambiguity"); + Err(err) + } + }; + + ModulePath { name: mod_name, path_exists: default_exists || secondary_exists, result } +} From 53a633fb445af045493f832fdce4f9d9ce48fbd4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 09:54:19 +0100 Subject: [PATCH 1220/1250] decouple push_directory from Parser --- src/librustc_parse/parser/module.rs | 41 ++++++++++++++++------------- 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index a30d6da281a..53c0c9154bc 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -58,7 +58,7 @@ impl<'a> Parser<'a> { } } else { let old_directory = self.directory.clone(); - self.push_directory(id, &attrs); + push_directory(id, &attrs, &mut self.directory.ownership, &mut self.directory.path); self.expect(&token::OpenDelim(token::Brace))?; let module = self.parse_mod(&token::CloseDelim(token::Brace))?; @@ -142,26 +142,31 @@ impl<'a> Parser<'a> { } Ok(()) } +} - fn push_directory(&mut self, id: Ident, attrs: &[Attribute]) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - self.directory.path.push(&*path.as_str()); - self.directory.ownership = DirectoryOwnership::Owned { relative: None }; - } else { - // We have to push on the current module name in the case of relative - // paths in order to ensure that any additional module paths from inline - // `mod x { ... }` come after the relative extension. - // - // For example, a `mod z { ... }` inside `x/y.rs` should set the current - // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. - if let DirectoryOwnership::Owned { relative } = &mut self.directory.ownership { - if let Some(ident) = relative.take() { - // remove the relative offset - self.directory.path.push(&*ident.as_str()); - } +fn push_directory( + id: Ident, + attrs: &[Attribute], + dir_ownership: &mut DirectoryOwnership, + dir_path: &mut PathBuf, +) { + if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { + dir_path.push(&*path.as_str()); + *dir_ownership = DirectoryOwnership::Owned { relative: None }; + } else { + // We have to push on the current module name in the case of relative + // paths in order to ensure that any additional module paths from inline + // `mod x { ... }` come after the relative extension. + // + // For example, a `mod z { ... }` inside `x/y.rs` should set the current + // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. + if let DirectoryOwnership::Owned { relative } = dir_ownership { + if let Some(ident) = relative.take() { + // Remove the relative offset. + dir_path.push(&*ident.as_str()); } - self.directory.path.push(&*id.as_str()); } + dir_path.push(&*id.as_str()); } } From 98e71cd5d788c1d8476ccd29974decb5d4b88dbc Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 11:06:30 +0100 Subject: [PATCH 1221/1250] decouple eval_src_mod from Parser --- src/librustc_parse/parser/module.rs | 69 ++++++++++++----------------- 1 file changed, 29 insertions(+), 40 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 53c0c9154bc..245d06333f7 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -52,7 +52,7 @@ impl<'a> Parser<'a> { self.directory.ownership, &self.directory.path, )?; - self.eval_src_mod(path, directory_ownership, id.to_string(), id.span)? + eval_src_mod(self.sess, self.cfg_mods, path, directory_ownership, id)? } else { (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) } @@ -100,48 +100,37 @@ impl<'a> Parser<'a> { Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) } +} - /// Reads a module from a source file. - fn eval_src_mod( - &mut self, - path: PathBuf, - directory_ownership: DirectoryOwnership, - name: String, - id_sp: Span, - ) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = self.sess.included_mod_stack.borrow_mut(); - self.error_on_circular_module(id_sp, &path, &included_mod_stack)?; - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(self.sess, &path, directory_ownership, Some(name), id_sp); - p0.cfg_mods = self.cfg_mods; - let mut module = p0.parse_mod(&token::Eof)?; - module.0.inline = false; - - self.sess.included_mod_stack.borrow_mut().pop(); - Ok(module) - } - - fn error_on_circular_module( - &self, - span: Span, - path: &Path, - included_mod_stack: &[PathBuf], - ) -> PResult<'a, ()> { - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - let len = included_mod_stack.len(); - for p in &included_mod_stack[i..len] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(self.struct_span_err(span, &err[..])); +/// Reads a module from a source file. +fn eval_src_mod<'a>( + sess: &'a ParseSess, + cfg_mods: bool, + path: PathBuf, + dir_ownership: DirectoryOwnership, + id: ast::Ident, +) -> PResult<'a, (Mod, Vec)> { + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + for p in &included_mod_stack[i..] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); } - Ok(()) + err.push_str(&path.to_string_lossy()); + return Err(sess.span_diagnostic.struct_span_err(id.span, &err[..])); } + included_mod_stack.push(path.clone()); + drop(included_mod_stack); + + let mut p0 = + new_sub_parser_from_file(sess, &path, dir_ownership, Some(id.to_string()), id.span); + p0.cfg_mods = cfg_mods; + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + + sess.included_mod_stack.borrow_mut().pop(); + Ok(module) } fn push_directory( From b9e1b2661159a9c63d47ef181c259465b90dca6d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 11:18:26 +0100 Subject: [PATCH 1222/1250] expand: use push_directory --- src/librustc_expand/expand.rs | 14 +++++++------- src/librustc_parse/parser/mod.rs | 2 +- src/librustc_parse/parser/module.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 4d0548f3f86..38b8ab62212 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,6 +18,7 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; +use rustc_parse::parser::module; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_parse::DirectoryOwnership; @@ -1448,13 +1449,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { module.mod_path.push(item.ident); if inline { - if let Some(path) = attr::first_attr_value_str_by_name(&item.attrs, sym::path) { - self.cx.current_expansion.directory_ownership = - DirectoryOwnership::Owned { relative: None }; - module.directory.push(&*path.as_str()); - } else { - module.directory.push(&*item.ident.as_str()); - } + module::push_directory( + item.ident, + &item.attrs, + &mut self.cx.current_expansion.directory_ownership, + &mut module.directory, + ); } else { let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); let mut path = match path { diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 9376c7c1c72..40dc9275b32 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1,7 +1,7 @@ pub mod attr; mod expr; mod item; -mod module; +pub mod module; pub use module::{ModulePath, ModulePathSuccess}; mod pat; mod path; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 245d06333f7..d4cf39e28b0 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -133,7 +133,7 @@ fn eval_src_mod<'a>( Ok(module) } -fn push_directory( +pub fn push_directory( id: Ident, attrs: &[Attribute], dir_ownership: &mut DirectoryOwnership, From 8bab88f2d9d1c81ab8d80d903359900ef106d21e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 12:19:27 +0100 Subject: [PATCH 1223/1250] de-fatalize outline module parsing --- src/librustc_ast/ast.rs | 2 +- src/librustc_parse/parser/module.rs | 37 +++++++++---------- src/test/ui/mod/mod_file_disambig.rs | 1 + src/test/ui/mod/mod_file_disambig.stderr | 11 +++++- src/test/ui/parser/circular_modules_main.rs | 2 +- .../ui/parser/circular_modules_main.stderr | 14 ++++++- src/test/ui/parser/mod_file_not_exist.rs | 1 + src/test/ui/parser/mod_file_not_exist.stderr | 11 +++++- 8 files changed, 52 insertions(+), 27 deletions(-) diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs index 68960ba9fe9..e3077b9897c 100644 --- a/src/librustc_ast/ast.rs +++ b/src/librustc_ast/ast.rs @@ -2153,7 +2153,7 @@ impl FnRetTy { /// Module declaration. /// /// E.g., `mod foo;` or `mod foo { .. }`. -#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] +#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)] pub struct Mod { /// A span from the first token past `{` to the last token until `}`. /// For `mod foo;`, the inner span ranges from the first token diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index d4cf39e28b0..8f99d88b8e4 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -8,7 +8,7 @@ use rustc_ast::attr; use rustc_ast::token::{self, TokenKind}; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::{FileName, Span, DUMMY_SP}; +use rustc_span::source_map::{FileName, Span}; use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; @@ -24,7 +24,7 @@ pub struct ModulePath<'a> { // Public for rustfmt usage. pub struct ModulePathSuccess { pub path: PathBuf, - pub directory_ownership: DirectoryOwnership, + pub ownership: DirectoryOwnership, } impl<'a> Parser<'a> { @@ -45,16 +45,13 @@ impl<'a> Parser<'a> { let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { // This mod is in an external file. Let's go get it! - let ModulePathSuccess { path, directory_ownership } = submod_path( - self.sess, - id, - &attrs, - self.directory.ownership, - &self.directory.path, - )?; - eval_src_mod(self.sess, self.cfg_mods, path, directory_ownership, id)? + let dir = &self.directory; + submod_path(self.sess, id, &attrs, dir.ownership, &dir.path) + .and_then(|r| eval_src_mod(self.sess, self.cfg_mods, r.path, r.ownership, id)) + .map_err(|mut err| err.emit()) + .unwrap_or_default() } else { - (ast::Mod { inner: DUMMY_SP, items: Vec::new(), inline: false }, Vec::new()) + Default::default() } } else { let old_directory = self.directory.clone(); @@ -162,12 +159,12 @@ pub fn push_directory( fn submod_path<'a>( sess: &'a ParseSess, id: ast::Ident, - outer_attrs: &[Attribute], - directory_ownership: DirectoryOwnership, + attrs: &[Attribute], + ownership: DirectoryOwnership, dir_path: &Path, ) -> PResult<'a, ModulePathSuccess> { - if let Some(path) = submod_path_from_attr(outer_attrs, dir_path) { - let directory_ownership = match path.file_name().and_then(|s| s.to_str()) { + if let Some(path) = submod_path_from_attr(attrs, dir_path) { + let ownership = match path.file_name().and_then(|s| s.to_str()) { // All `#[path]` files are treated as though they are a `mod.rs` file. // This means that `mod foo;` declarations inside `#[path]`-included // files are siblings, @@ -178,16 +175,16 @@ fn submod_path<'a>( Some(_) => DirectoryOwnership::Owned { relative: None }, _ => DirectoryOwnership::UnownedViaMod, }; - return Ok(ModulePathSuccess { directory_ownership, path }); + return Ok(ModulePathSuccess { ownership, path }); } - let relative = match directory_ownership { + let relative = match ownership { DirectoryOwnership::Owned { relative } => relative, DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; let ModulePath { path_exists, name, result } = default_submod_path(sess, id, relative, dir_path); - match directory_ownership { + match ownership { DirectoryOwnership::Owned { .. } => Ok(result?), DirectoryOwnership::UnownedViaBlock => { let _ = result.map_err(|mut err| err.cancel()); @@ -300,11 +297,11 @@ pub fn default_submod_path<'a>( let result = match (default_exists, secondary_exists) { (true, false) => Ok(ModulePathSuccess { path: default_path, - directory_ownership: DirectoryOwnership::Owned { relative: Some(id) }, + ownership: DirectoryOwnership::Owned { relative: Some(id) }, }), (false, true) => Ok(ModulePathSuccess { path: secondary_path, - directory_ownership: DirectoryOwnership::Owned { relative: None }, + ownership: DirectoryOwnership::Owned { relative: None }, }), (false, false) => { let mut err = struct_span_err!( diff --git a/src/test/ui/mod/mod_file_disambig.rs b/src/test/ui/mod/mod_file_disambig.rs index ef203ef082b..7b182421d34 100644 --- a/src/test/ui/mod/mod_file_disambig.rs +++ b/src/test/ui/mod/mod_file_disambig.rs @@ -2,4 +2,5 @@ mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` fou fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 2b77d866fb3..230bfa79916 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -6,6 +6,13 @@ LL | mod mod_file_disambig_aux; | = help: delete or rename one of them to remove the ambiguity -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_disambig.rs:4:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0584`. +Some errors have detailed explanations: E0433, E0584. +For more information about an error, try `rustc --explain E0433`. diff --git a/src/test/ui/parser/circular_modules_main.rs b/src/test/ui/parser/circular_modules_main.rs index b85003bf091..1ae36a1f760 100644 --- a/src/test/ui/parser/circular_modules_main.rs +++ b/src/test/ui/parser/circular_modules_main.rs @@ -6,5 +6,5 @@ pub fn hi_str() -> String { } fn main() { - circular_modules_hello::say_hello(); + circular_modules_hello::say_hello(); //~ ERROR cannot find function `say_hello` in module } diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index 33865fb7bca..ca84f2d2854 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -4,5 +4,17 @@ error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules LL | mod circular_modules_hello; | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error[E0425]: cannot find function `say_hello` in module `circular_modules_hello` + --> $DIR/circular_modules_main.rs:9:29 + | +LL | circular_modules_hello::say_hello(); + | ^^^^^^^^^ not found in `circular_modules_hello` + | +help: possible candidate is found in another module, you can import it into scope + | +LL | use circular_modules_hello::say_hello; + | + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs index 71fbc7aea45..aee778d1013 100644 --- a/src/test/ui/parser/mod_file_not_exist.rs +++ b/src/test/ui/parser/mod_file_not_exist.rs @@ -5,4 +5,5 @@ mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index db3ea04ac76..c298c51c4f8 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -6,6 +6,13 @@ LL | mod not_a_real_file; | = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_not_exist.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0583`. +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. From 463995fe2974e2473392ddf7be8699746f6b7dac Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 12:33:15 +0100 Subject: [PATCH 1224/1250] extract parse_external_module --- src/librustc_parse/parser/module.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 8f99d88b8e4..0701b733076 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -44,12 +44,8 @@ impl<'a> Parser<'a> { let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { if in_cfg && self.recurse_into_file_modules { - // This mod is in an external file. Let's go get it! let dir = &self.directory; - submod_path(self.sess, id, &attrs, dir.ownership, &dir.path) - .and_then(|r| eval_src_mod(self.sess, self.cfg_mods, r.path, r.ownership, id)) - .map_err(|mut err| err.emit()) - .unwrap_or_default() + parse_external_module(self.sess, self.cfg_mods, id, dir.ownership, &dir.path, attrs) } else { Default::default() } @@ -99,6 +95,20 @@ impl<'a> Parser<'a> { } } +fn parse_external_module( + sess: &ParseSess, + cfg_mods: bool, + id: ast::Ident, + ownership: DirectoryOwnership, + dir_path: &Path, + attrs: &[Attribute], +) -> (Mod, Vec) { + submod_path(sess, id, &attrs, ownership, dir_path) + .and_then(|r| eval_src_mod(sess, cfg_mods, r.path, r.ownership, id)) + .map_err(|mut err| err.emit()) + .unwrap_or_default() +} + /// Reads a module from a source file. fn eval_src_mod<'a>( sess: &'a ParseSess, From 59bf8a07f93d194abcc880a366bda37563a9402b Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 13:29:37 +0100 Subject: [PATCH 1225/1250] extract error_on_circular_module --- src/librustc_parse/parser/module.rs | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 0701b733076..66faf295b72 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -118,15 +118,7 @@ fn eval_src_mod<'a>( id: ast::Ident, ) -> PResult<'a, (Mod, Vec)> { let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { - let mut err = String::from("circular modules: "); - for p in &included_mod_stack[i..] { - err.push_str(&p.to_string_lossy()); - err.push_str(" -> "); - } - err.push_str(&path.to_string_lossy()); - return Err(sess.span_diagnostic.struct_span_err(id.span, &err[..])); - } + error_on_circular_module(sess, id.span, &path, &included_mod_stack)?; included_mod_stack.push(path.clone()); drop(included_mod_stack); @@ -140,6 +132,24 @@ fn eval_src_mod<'a>( Ok(module) } +fn error_on_circular_module<'a>( + sess: &'a ParseSess, + span: Span, + path: &Path, + included_mod_stack: &[PathBuf], +) -> PResult<'a, ()> { + if let Some(i) = included_mod_stack.iter().position(|p| *p == path) { + let mut err = String::from("circular modules: "); + for p in &included_mod_stack[i..] { + err.push_str(&p.to_string_lossy()); + err.push_str(" -> "); + } + err.push_str(&path.to_string_lossy()); + return Err(sess.span_diagnostic.struct_span_err(span, &err[..])); + } + Ok(()) +} + pub fn push_directory( id: Ident, attrs: &[Attribute], From 83a757a9ca0d0f61bd2325e9a95d591d53e01129 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 13:36:20 +0100 Subject: [PATCH 1226/1250] outline modules: parse -> expand. --- src/librustc_builtin_macros/source_util.rs | 5 +- src/librustc_expand/expand.rs | 77 +++++++++------ src/librustc_expand/mbe/macro_rules.rs | 37 +++----- src/librustc_parse/config.rs | 9 -- src/librustc_parse/lib.rs | 20 ++-- src/librustc_parse/parser/mod.rs | 33 +------ src/librustc_parse/parser/module.rs | 105 ++++++++++----------- src/librustc_parse/parser/stmt.rs | 10 +- 8 files changed, 116 insertions(+), 180 deletions(-) diff --git a/src/librustc_builtin_macros/source_util.rs b/src/librustc_builtin_macros/source_util.rs index 5ad72a7443d..662bbe6a287 100644 --- a/src/librustc_builtin_macros/source_util.rs +++ b/src/librustc_builtin_macros/source_util.rs @@ -5,7 +5,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{self, *}; use rustc_expand::panictry; -use rustc_parse::{self, new_sub_parser_from_file, parser::Parser, DirectoryOwnership}; +use rustc_parse::{self, new_sub_parser_from_file, parser::Parser}; use rustc_session::lint::builtin::INCOMPLETE_INCLUDE; use rustc_span::symbol::Symbol; use rustc_span::{self, Pos, Span}; @@ -108,8 +108,7 @@ pub fn expand_include<'cx>( return DummyResult::any(sp); } }; - let directory_ownership = DirectoryOwnership::Owned { relative: None }; - let p = new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp); + let p = new_sub_parser_from_file(cx.parse_sess(), &file, None, sp); struct ExpandResult<'a> { p: Parser<'a>, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 38b8ab62212..61a34a39d58 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,10 +18,10 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module; +use rustc_parse::parser::module::{parse_external_mod, push_directory}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::DirectoryOwnership; +use rustc_parse::{Directory, DirectoryOwnership}; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; @@ -1428,8 +1428,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { .make_items(); } + let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. + let ident = item.ident; + match item.kind { ast::ItemKind::MacCall(..) => { + item.attrs = attrs; self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::MacCall(mac) => self @@ -1441,45 +1445,56 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { _ => unreachable!(), }) } - ast::ItemKind::Mod(ast::Mod { inner, inline, .. }) - if item.ident != Ident::invalid() => - { - let orig_directory_ownership = self.cx.current_expansion.directory_ownership; + ast::ItemKind::Mod(ref mut old_mod @ ast::Mod { .. }) if ident != Ident::invalid() => { + let sess = self.cx.parse_sess; + let orig_ownership = self.cx.current_expansion.directory_ownership; let mut module = (*self.cx.current_expansion.module).clone(); - module.mod_path.push(item.ident); - - if inline { - module::push_directory( - item.ident, - &item.attrs, - &mut self.cx.current_expansion.directory_ownership, - &mut module.directory, - ); + + let pushed = &mut false; // Record `parse_external_mod` pushing so we can pop. + let dir = Directory { ownership: orig_ownership, path: module.directory }; + let Directory { ownership, path } = if old_mod.inline { + // Inline `mod foo { ... }`, but we still need to push directories. + item.attrs = attrs; + push_directory(ident, &item.attrs, dir) } else { - let path = self.cx.parse_sess.source_map().span_to_unmapped_path(inner); - let mut path = match path { - FileName::Real(path) => path, - other => PathBuf::from(other.to_string()), - }; - let directory_ownership = match path.file_name().unwrap().to_str() { - Some("mod.rs") => DirectoryOwnership::Owned { relative: None }, - Some(_) => DirectoryOwnership::Owned { relative: Some(item.ident) }, - None => DirectoryOwnership::UnownedViaMod, + // We have an outline `mod foo;` so we need to parse the file. + let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed); + *old_mod = new_mod; + item.attrs = attrs; + // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. + item = match self.configure(item) { + Some(node) => node, + None => { + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } + return Default::default(); + } }; - path.pop(); - module.directory = path; - self.cx.current_expansion.directory_ownership = directory_ownership; - } + dir + }; + // Set the module info before we flat map. + self.cx.current_expansion.directory_ownership = ownership; + module.directory = path; + module.mod_path.push(ident); let orig_module = mem::replace(&mut self.cx.current_expansion.module, Rc::new(module)); + let result = noop_flat_map_item(item, self); + + // Restore the module info. self.cx.current_expansion.module = orig_module; - self.cx.current_expansion.directory_ownership = orig_directory_ownership; + self.cx.current_expansion.directory_ownership = orig_ownership; + if *pushed { + sess.included_mod_stack.borrow_mut().pop(); + } result } - - _ => noop_flat_map_item(item, self), + _ => { + item.attrs = attrs; + noop_flat_map_item(item, self) + } } } diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 2268c9b3854..1628d8bfdbc 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -1,4 +1,4 @@ -use crate::base::{DummyResult, ExpansionData, ExtCtxt, MacResult, TTMacroExpander}; +use crate::base::{DummyResult, ExtCtxt, MacResult, TTMacroExpander}; use crate::base::{SyntaxExtension, SyntaxExtensionKind}; use crate::expand::{ensure_complete_parse, parse_ast_fragment, AstFragment, AstFragmentKind}; use crate::mbe; @@ -18,7 +18,6 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder, FatalError}; use rustc_feature::Features; use rustc_parse::parser::Parser; -use rustc_parse::Directory; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::Transparency; @@ -182,6 +181,8 @@ fn generic_extension<'cx>( lhses: &[mbe::TokenTree], rhses: &[mbe::TokenTree], ) -> Box { + let sess = cx.parse_sess; + if cx.trace_macros() { let msg = format!("expanding `{}! {{ {} }}`", name, pprust::tts_to_string(arg.clone())); trace_macros_note(&mut cx.expansions, sp, msg); @@ -209,7 +210,7 @@ fn generic_extension<'cx>( // hacky, but speeds up the `html5ever` benchmark significantly. (Issue // 68836 suggests a more comprehensive but more complex change to deal with // this situation.) - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); + let parser = parser_from_cx(sess, arg.clone()); for (i, lhs) in lhses.iter().enumerate() { // try each arm's matchers @@ -222,14 +223,13 @@ fn generic_extension<'cx>( // This is used so that if a matcher is not `Success(..)`ful, // then the spans which became gated when parsing the unsuccessful matcher // are not recorded. On the first `Success(..)`ful matcher, the spans are merged. - let mut gated_spans_snapshot = - mem::take(&mut *cx.parse_sess.gated_spans.spans.borrow_mut()); + let mut gated_spans_snapshot = mem::take(&mut *sess.gated_spans.spans.borrow_mut()); match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { Success(named_matches) => { // The matcher was `Success(..)`ful. // Merge the gated spans from parsing the matcher with the pre-existing ones. - cx.parse_sess.gated_spans.merge(gated_spans_snapshot); + sess.gated_spans.merge(gated_spans_snapshot); let rhs = match rhses[i] { // ignore delimiters @@ -258,11 +258,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let directory = Directory { - path: cx.current_expansion.module.directory.clone(), - ownership: cx.current_expansion.directory_ownership, - }; - let mut p = Parser::new(cx.parse_sess(), tts, Some(directory), true, false, None); + let mut p = Parser::new(cx.parse_sess(), tts, false, None); p.root_module_name = cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; @@ -289,7 +285,7 @@ fn generic_extension<'cx>( // The matcher was not `Success(..)`ful. // Restore to the state before snapshotting and maybe try again. - mem::swap(&mut gated_spans_snapshot, &mut cx.parse_sess.gated_spans.spans.borrow_mut()); + mem::swap(&mut gated_spans_snapshot, &mut sess.gated_spans.spans.borrow_mut()); } drop(parser); @@ -309,8 +305,7 @@ fn generic_extension<'cx>( mbe::TokenTree::Delimited(_, ref delim) => &delim.tts[..], _ => continue, }; - let parser = parser_from_cx(&cx.current_expansion, &cx.parse_sess, arg.clone()); - match parse_tt(&mut Cow::Borrowed(&parser), lhs_tt) { + match parse_tt(&mut Cow::Borrowed(&parser_from_cx(sess, arg.clone())), lhs_tt) { Success(_) => { if comma_span.is_dummy() { err.note("you might be missing a comma"); @@ -392,7 +387,7 @@ pub fn compile_declarative_macro( ), ]; - let parser = Parser::new(sess, body, None, true, true, rustc_parse::MACRO_ARGUMENTS); + let parser = Parser::new(sess, body, true, rustc_parse::MACRO_ARGUMENTS); let argument_map = match parse_tt(&mut Cow::Borrowed(&parser), &argument_gram) { Success(m) => m, Failure(token, msg) => { @@ -1209,16 +1204,8 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>( - current_expansion: &'cx ExpansionData, - sess: &'cx ParseSess, - tts: TokenStream, -) -> Parser<'cx> { - let directory = Directory { - path: current_expansion.module.directory.clone(), - ownership: current_expansion.directory_ownership, - }; - Parser::new(sess, tts, Some(directory), true, true, rustc_parse::MACRO_ARGUMENTS) +fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> { + Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } /// Generates an appropriate parsing failure message. For EOF, this is "unexpected end...". For diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs index d209da866e1..c611f249420 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_parse/config.rs @@ -538,12 +538,3 @@ impl<'a> MutVisitor for StripUnconfigured<'a> { fn is_cfg(attr: &Attribute) -> bool { attr.check_name(sym::cfg) } - -/// Process the potential `cfg` attributes on a module. -/// Also determine if the module should be included in this configuration. -pub fn process_configure_mod(sess: &ParseSess, cfg_mods: bool, attrs: &mut Vec) -> bool { - // Don't perform gated feature checking. - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - strip_unconfigured.process_cfg_attrs(attrs); - !cfg_mods || strip_unconfigured.in_cfg(&attrs) -} diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 884499ff2dd..bcaae02942e 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -3,6 +3,7 @@ #![feature(bool_to_option)] #![feature(crate_visibility_modifier)] #![feature(bindings_after_at)] +#![feature(try_blocks)] use rustc_ast::ast; use rustc_ast::token::{self, Nonterminal}; @@ -119,10 +120,7 @@ pub fn maybe_new_parser_from_source_str( name: FileName, source: String, ) -> Result, Vec> { - let mut parser = - maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source))?; - parser.recurse_into_file_modules = false; - Ok(parser) + maybe_source_file_to_parser(sess, sess.source_map().new_source_file(name, source)) } /// Creates a new parser, handling errors as appropriate if the file doesn't exist. @@ -146,12 +144,10 @@ pub fn maybe_new_parser_from_file<'a>( pub fn new_sub_parser_from_file<'a>( sess: &'a ParseSess, path: &Path, - directory_ownership: DirectoryOwnership, module_name: Option, sp: Span, ) -> Parser<'a> { let mut p = source_file_to_parser(sess, file_to_source_file(sess, path, Some(sp))); - p.directory.ownership = directory_ownership; p.root_module_name = module_name; p } @@ -257,7 +253,7 @@ pub fn stream_to_parser<'a>( stream: TokenStream, subparser_name: Option<&'static str>, ) -> Parser<'a> { - Parser::new(sess, stream, None, true, false, subparser_name) + Parser::new(sess, stream, false, subparser_name) } /// Given a stream, the `ParseSess` and the base directory, produces a parser. @@ -271,12 +267,8 @@ pub fn stream_to_parser<'a>( /// The main usage of this function is outside of rustc, for those who uses /// librustc_ast as a library. Please do not remove this function while refactoring /// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir( - sess: &ParseSess, - stream: TokenStream, - base_dir: Directory, -) -> Parser<'_> { - Parser::new(sess, stream, Some(base_dir), true, false, None) +pub fn stream_to_parser_with_base_dir(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { + Parser::new(sess, stream, false, None) } /// Runs the given subparser `f` on the tokens of the given `attr`'s item. @@ -286,7 +278,7 @@ pub fn parse_in<'a, T>( name: &'static str, mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>, ) -> PResult<'a, T> { - let mut parser = Parser::new(sess, tts, None, false, false, Some(name)); + let mut parser = Parser::new(sess, tts, false, Some(name)); let result = f(&mut parser)?; if parser.token != token::Eof { parser.unexpected()?; diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index 40dc9275b32..f4862a6c87b 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -13,7 +13,6 @@ mod stmt; use diagnostics::Error; use crate::lexer::UnmatchedBrace; -use crate::{Directory, DirectoryOwnership}; use log::debug; use rustc_ast::ast::DUMMY_NODE_ID; @@ -28,11 +27,9 @@ use rustc_ast::util::comments::{doc_comment_style, strip_doc_comment_decoration} use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, FatalError, PResult}; use rustc_session::parse::ParseSess; -use rustc_span::source_map::respan; +use rustc_span::source_map::{respan, Span, DUMMY_SP}; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{FileName, Span, DUMMY_SP}; -use std::path::PathBuf; use std::{cmp, mem, slice}; bitflags::bitflags! { @@ -93,11 +90,6 @@ pub struct Parser<'a> { /// The previous token. pub prev_token: Token, restrictions: Restrictions, - /// Used to determine the path to externally loaded source files. - pub(super) directory: Directory, - /// `true` to parse sub-modules in other files. - // Public for rustfmt usage. - pub recurse_into_file_modules: bool, /// Name of the root module this parser originated from. If `None`, then the /// name is not known. This does not change while the parser is descending /// into modules, and sub-parsers have new values for this name. @@ -105,9 +97,6 @@ pub struct Parser<'a> { expected_tokens: Vec, token_cursor: TokenCursor, desugar_doc_comments: bool, - /// `true` we should configure out of line modules as we parse. - // Public for rustfmt usage. - pub cfg_mods: bool, /// This field is used to keep track of how many left angle brackets we have seen. This is /// required in order to detect extra leading left angle brackets (`<` characters) and error /// appropriately. @@ -355,8 +344,6 @@ impl<'a> Parser<'a> { pub fn new( sess: &'a ParseSess, tokens: TokenStream, - directory: Option, - recurse_into_file_modules: bool, desugar_doc_comments: bool, subparser_name: Option<&'static str>, ) -> Self { @@ -365,11 +352,6 @@ impl<'a> Parser<'a> { token: Token::dummy(), prev_token: Token::dummy(), restrictions: Restrictions::empty(), - recurse_into_file_modules, - directory: Directory { - path: PathBuf::new(), - ownership: DirectoryOwnership::Owned { relative: None }, - }, root_module_name: None, expected_tokens: Vec::new(), token_cursor: TokenCursor { @@ -377,7 +359,6 @@ impl<'a> Parser<'a> { stack: Vec::new(), }, desugar_doc_comments, - cfg_mods: true, unmatched_angle_bracket_count: 0, max_angle_bracket_count: 0, unclosed_delims: Vec::new(), @@ -389,18 +370,6 @@ impl<'a> Parser<'a> { // Make parser point to the first token. parser.bump(); - if let Some(directory) = directory { - parser.directory = directory; - } else if !parser.token.span.is_dummy() { - if let Some(FileName::Real(path)) = - &sess.source_map().lookup_char_pos(parser.token.span.lo()).file.unmapped_path - { - if let Some(directory_path) = path.parent() { - parser.directory.path = directory_path.to_path_buf(); - } - } - } - parser } diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 66faf295b72..695afafdd82 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,7 +1,7 @@ use super::item::ItemInfo; use super::Parser; -use crate::{new_sub_parser_from_file, DirectoryOwnership}; +use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; use rustc_ast::attr; @@ -39,25 +39,12 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let in_cfg = crate::config::process_configure_mod(self.sess, self.cfg_mods, attrs); - let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { - if in_cfg && self.recurse_into_file_modules { - let dir = &self.directory; - parse_external_module(self.sess, self.cfg_mods, id, dir.ownership, &dir.path, attrs) - } else { - Default::default() - } + Default::default() } else { - let old_directory = self.directory.clone(); - push_directory(id, &attrs, &mut self.directory.ownership, &mut self.directory.path); - self.expect(&token::OpenDelim(token::Brace))?; - let module = self.parse_mod(&token::CloseDelim(token::Brace))?; - - self.directory = old_directory; - module + self.parse_mod(&token::CloseDelim(token::Brace))? }; attrs.append(&mut inner_attrs); Ok((id, ItemKind::Mod(module))) @@ -95,41 +82,45 @@ impl<'a> Parser<'a> { } } -fn parse_external_module( +pub fn parse_external_mod( sess: &ParseSess, - cfg_mods: bool, - id: ast::Ident, - ownership: DirectoryOwnership, - dir_path: &Path, - attrs: &[Attribute], -) -> (Mod, Vec) { - submod_path(sess, id, &attrs, ownership, dir_path) - .and_then(|r| eval_src_mod(sess, cfg_mods, r.path, r.ownership, id)) - .map_err(|mut err| err.emit()) - .unwrap_or_default() -} - -/// Reads a module from a source file. -fn eval_src_mod<'a>( - sess: &'a ParseSess, - cfg_mods: bool, - path: PathBuf, - dir_ownership: DirectoryOwnership, id: ast::Ident, -) -> PResult<'a, (Mod, Vec)> { - let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - error_on_circular_module(sess, id.span, &path, &included_mod_stack)?; - included_mod_stack.push(path.clone()); - drop(included_mod_stack); - - let mut p0 = - new_sub_parser_from_file(sess, &path, dir_ownership, Some(id.to_string()), id.span); - p0.cfg_mods = cfg_mods; - let mut module = p0.parse_mod(&token::Eof)?; - module.0.inline = false; + Directory { mut ownership, path }: Directory, + attrs: &mut Vec, + pop_mod_stack: &mut bool, +) -> (Mod, Directory) { + // We bail on the first error, but that error does not cause a fatal error... (1) + let result: PResult<'_, _> = try { + // Extract the file path and the new ownership. + let mp = submod_path(sess, id, &attrs, ownership, &path)?; + ownership = mp.ownership; + + // Ensure file paths are acyclic. + let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); + error_on_circular_module(sess, id.span, &mp.path, &included_mod_stack)?; + included_mod_stack.push(mp.path.clone()); + *pop_mod_stack = true; // We have pushed, so notify caller. + drop(included_mod_stack); + + // Actually parse the external file as amodule. + let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), id.span); + let mut module = p0.parse_mod(&token::Eof)?; + module.0.inline = false; + module + }; + // (1) ...instead, we return a dummy module. + let (module, mut new_attrs) = result.map_err(|mut err| err.emit()).unwrap_or_default(); + attrs.append(&mut new_attrs); + + // Extract the directory path for submodules of `module`. + let path = sess.source_map().span_to_unmapped_path(module.inner); + let mut path = match path { + FileName::Real(path) => path, + other => PathBuf::from(other.to_string()), + }; + path.pop(); - sess.included_mod_stack.borrow_mut().pop(); - Ok(module) + (module, Directory { ownership, path }) } fn error_on_circular_module<'a>( @@ -153,12 +144,11 @@ fn error_on_circular_module<'a>( pub fn push_directory( id: Ident, attrs: &[Attribute], - dir_ownership: &mut DirectoryOwnership, - dir_path: &mut PathBuf, -) { - if let Some(path) = attr::first_attr_value_str_by_name(attrs, sym::path) { - dir_path.push(&*path.as_str()); - *dir_ownership = DirectoryOwnership::Owned { relative: None }; + Directory { mut ownership, mut path }: Directory, +) -> Directory { + if let Some(filename) = attr::first_attr_value_str_by_name(attrs, sym::path) { + path.push(&*filename.as_str()); + ownership = DirectoryOwnership::Owned { relative: None }; } else { // We have to push on the current module name in the case of relative // paths in order to ensure that any additional module paths from inline @@ -166,14 +156,15 @@ pub fn push_directory( // // For example, a `mod z { ... }` inside `x/y.rs` should set the current // directory path to `/x/y/z`, not `/x/z` with a relative offset of `y`. - if let DirectoryOwnership::Owned { relative } = dir_ownership { + if let DirectoryOwnership::Owned { relative } = &mut ownership { if let Some(ident) = relative.take() { // Remove the relative offset. - dir_path.push(&*ident.as_str()); + path.push(&*ident.as_str()); } } - dir_path.push(&*id.as_str()); + path.push(&*id.as_str()); } + Directory { ownership, path } } fn submod_path<'a>( diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 4359823be08..d40597d8fcb 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -5,7 +5,6 @@ use super::pat::GateOr; use super::path::PathStyle; use super::{BlockMode, Parser, Restrictions, SemiColonMode}; use crate::maybe_whole; -use crate::DirectoryOwnership; use rustc_ast::ast; use rustc_ast::ast::{AttrStyle, AttrVec, Attribute, MacCall, MacStmtStyle}; @@ -54,7 +53,7 @@ impl<'a> Parser<'a> { // that starts like a path (1 token), but it fact not a path. // Also, we avoid stealing syntax from `parse_item_`. self.parse_stmt_path_start(lo, attrs)? - } else if let Some(item) = self.parse_stmt_item(attrs.clone())? { + } else if let Some(item) = self.parse_item_common(attrs.clone(), false, true, |_| true)? { // FIXME: Bad copy of attrs self.mk_stmt(lo.to(item.span), StmtKind::Item(P(item))) } else if self.eat(&token::Semi) { @@ -72,13 +71,6 @@ impl<'a> Parser<'a> { Ok(Some(stmt)) } - fn parse_stmt_item(&mut self, attrs: Vec) -> PResult<'a, Option> { - let old = mem::replace(&mut self.directory.ownership, DirectoryOwnership::UnownedViaBlock); - let item = self.parse_item_common(attrs, false, true, |_| true)?; - self.directory.ownership = old; - Ok(item) - } - fn parse_stmt_path_start(&mut self, lo: Span, attrs: Vec) -> PResult<'a, Stmt> { let path = self.parse_path(PathStyle::Expr)?; From f1ca9969bfb1a69e98dab6ff0413e099532f57f2 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 21:50:01 +0100 Subject: [PATCH 1227/1250] parse: module parsing -> item.rs --- src/librustc_parse/parser/item.rs | 69 ++++++++++++++++++++++++++--- src/librustc_parse/parser/module.rs | 62 +------------------------- 2 files changed, 66 insertions(+), 65 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index e927bcd07e2..d0da8e6c7c1 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -4,14 +4,18 @@ use super::{FollowedByType, Parser, PathStyle}; use crate::maybe_whole; -use rustc_ast::ast::{self, Async, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; -use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind}; -use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, MacArgs, MacCall, MacDelimiter, Param}; -use rustc_ast::ast::{Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind}; +use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; +use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod}; +use rustc_ast::ast::{ + Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind, +}; +use rustc_ast::ast::{ + BindingMode, Block, FnDecl, FnSig, MacArgs, MacCall, MacDelimiter, Param, SelfKind, +}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, SelfKind, Visibility, VisibilityKind}; use rustc_ast::ptr::P; -use rustc_ast::token; +use rustc_ast::token::{self, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast_pretty::pprust; use rustc_errors::{struct_span_err, Applicability, PResult, StashKey}; @@ -23,6 +27,61 @@ use log::debug; use std::convert::TryFrom; use std::mem; +impl<'a> Parser<'a> { + /// Parses a source module as a crate. This is the main entry point for the parser. + pub fn parse_crate_mod(&mut self) -> PResult<'a, ast::Crate> { + let lo = self.token.span; + let (module, attrs) = self.parse_mod(&token::Eof)?; + let span = lo.to(self.token.span); + let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. + Ok(ast::Crate { attrs, module, span, proc_macros }) + } + + /// Parses a `mod { ... }` or `mod ;` item. + pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + let id = self.parse_ident()?; + let (module, mut inner_attrs) = if self.eat(&token::Semi) { + Default::default() + } else { + self.expect(&token::OpenDelim(token::Brace))?; + self.parse_mod(&token::CloseDelim(token::Brace))? + }; + attrs.append(&mut inner_attrs); + Ok((id, ItemKind::Mod(module))) + } + + /// Parses the contents of a module (inner attributes followed by module items). + pub fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { + let lo = self.token.span; + let attrs = self.parse_inner_attributes()?; + let module = self.parse_mod_items(term, lo)?; + Ok((module, attrs)) + } + + /// Given a termination token, parses all of the items in a module. + fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { + let mut items = vec![]; + while let Some(item) = self.parse_item()? { + items.push(item); + self.maybe_consume_incorrect_semicolon(&items); + } + + if !self.eat(term) { + let token_str = super::token_descr(&self.token); + if !self.maybe_consume_incorrect_semicolon(&items) { + let msg = &format!("expected item, found {}", token_str); + let mut err = self.struct_span_err(self.token.span, msg); + err.span_label(self.token.span, "expected item"); + return Err(err); + } + } + + let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; + + Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) + } +} + pub(super) type ItemInfo = (Ident, ItemKind); impl<'a> Parser<'a> { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 695afafdd82..2c752bd9f0a 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,11 +1,8 @@ -use super::item::ItemInfo; -use super::Parser; - use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; -use rustc_ast::ast::{self, Attribute, Crate, Ident, ItemKind, Mod}; +use rustc_ast::ast::{self, Attribute, Ident, Mod}; use rustc_ast::attr; -use rustc_ast::token::{self, TokenKind}; +use rustc_ast::token; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; @@ -27,61 +24,6 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } -impl<'a> Parser<'a> { - /// Parses a source module as a crate. This is the main entry point for the parser. - pub fn parse_crate_mod(&mut self) -> PResult<'a, Crate> { - let lo = self.token.span; - let (module, attrs) = self.parse_mod(&token::Eof)?; - let span = lo.to(self.token.span); - let proc_macros = Vec::new(); // Filled in by `proc_macro_harness::inject()`. - Ok(ast::Crate { attrs, module, span, proc_macros }) - } - - /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { - let id = self.parse_ident()?; - let (module, mut inner_attrs) = if self.eat(&token::Semi) { - Default::default() - } else { - self.expect(&token::OpenDelim(token::Brace))?; - self.parse_mod(&token::CloseDelim(token::Brace))? - }; - attrs.append(&mut inner_attrs); - Ok((id, ItemKind::Mod(module))) - } - - /// Parses the contents of a module (inner attributes followed by module items). - fn parse_mod(&mut self, term: &TokenKind) -> PResult<'a, (Mod, Vec)> { - let lo = self.token.span; - let attrs = self.parse_inner_attributes()?; - let module = self.parse_mod_items(term, lo)?; - Ok((module, attrs)) - } - - /// Given a termination token, parses all of the items in a module. - fn parse_mod_items(&mut self, term: &TokenKind, inner_lo: Span) -> PResult<'a, Mod> { - let mut items = vec![]; - while let Some(item) = self.parse_item()? { - items.push(item); - self.maybe_consume_incorrect_semicolon(&items); - } - - if !self.eat(term) { - let token_str = super::token_descr(&self.token); - if !self.maybe_consume_incorrect_semicolon(&items) { - let msg = &format!("expected item, found {}", token_str); - let mut err = self.struct_span_err(self.token.span, msg); - err.span_label(self.token.span, "expected item"); - return Err(err); - } - } - - let hi = if self.token.span.is_dummy() { inner_lo } else { self.prev_token.span }; - - Ok(Mod { inner: inner_lo.to(hi), items, inline: true }) - } -} - pub fn parse_external_mod( sess: &ParseSess, id: ast::Ident, From ddcc8ec89de7c2637a012eb14b1b07c8b9426d1e Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:10:37 +0100 Subject: [PATCH 1228/1250] move Directory -> parser::module --- src/librustc_expand/base.rs | 3 ++- src/librustc_expand/expand.rs | 5 +++-- src/librustc_parse/lib.rs | 18 +----------------- src/librustc_parse/parser/module.rs | 21 ++++++++++++++++++--- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index f5f2a5ed43f..315a1c950d8 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -10,7 +10,8 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_parse::{self, parser, DirectoryOwnership, MACRO_ARGUMENTS}; +use rustc_parse::parser::module::DirectoryOwnership; +use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind}; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 61a34a39d58..46f10ca3614 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -18,10 +18,11 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module::{parse_external_mod, push_directory}; +use rustc_parse::parser::module::{ + parse_external_mod, push_directory, Directory, DirectoryOwnership, +}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; -use rustc_parse::{Directory, DirectoryOwnership}; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::{feature_err, ParseSess}; diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index bcaae02942e..70aa8c0074a 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -14,7 +14,7 @@ use rustc_errors::{Diagnostic, FatalError, Level, PResult}; use rustc_session::parse::ParseSess; use rustc_span::{FileName, SourceFile, Span}; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::str; use log::info; @@ -29,22 +29,6 @@ pub mod validate_attr; #[macro_use] pub mod config; -#[derive(Clone)] -pub struct Directory { - pub path: PathBuf, - pub ownership: DirectoryOwnership, -} - -#[derive(Copy, Clone)] -pub enum DirectoryOwnership { - Owned { - // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. - relative: Option, - }, - UnownedViaBlock, - UnownedViaMod, -} - // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that // uses a HOF to parse anything, and includes file and diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 2c752bd9f0a..e45a26bd441 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -1,8 +1,7 @@ -use crate::{new_sub_parser_from_file, Directory, DirectoryOwnership}; +use crate::new_sub_parser_from_file; use rustc_ast::ast::{self, Attribute, Ident, Mod}; -use rustc_ast::attr; -use rustc_ast::token; +use rustc_ast::{attr, token}; use rustc_errors::{struct_span_err, PResult}; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; @@ -10,6 +9,22 @@ use rustc_span::symbol::sym; use std::path::{self, Path, PathBuf}; +#[derive(Clone)] +pub struct Directory { + pub path: PathBuf, + pub ownership: DirectoryOwnership, +} + +#[derive(Copy, Clone)] +pub enum DirectoryOwnership { + Owned { + // None if `mod.rs`, `Some("foo")` if we're in `foo.rs`. + relative: Option, + }, + UnownedViaBlock, + UnownedViaMod, +} + /// Information about the path to a module. // Public for rustfmt usage. pub struct ModulePath<'a> { From 3796faefb1d22f496514126d3d2b5a87b948ae47 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:21:37 +0100 Subject: [PATCH 1229/1250] {rustc_parse::parser -> rustc_expand}::module --- src/librustc_expand/base.rs | 2 +- src/librustc_expand/expand.rs | 4 +--- src/librustc_expand/lib.rs | 2 ++ src/{librustc_parse/parser => librustc_expand}/module.rs | 7 +++---- src/librustc_parse/parser/mod.rs | 2 -- 5 files changed, 7 insertions(+), 10 deletions(-) rename src/{librustc_parse/parser => librustc_expand}/module.rs (99%) diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 315a1c950d8..1e9d59ca4bf 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -1,4 +1,5 @@ use crate::expand::{self, AstFragment, Invocation}; +use crate::module::DirectoryOwnership; use rustc_ast::ast::{self, Attribute, Name, NodeId, PatKind}; use rustc_ast::mut_visit::{self, MutVisitor}; @@ -10,7 +11,6 @@ use rustc_attr::{self as attr, Deprecation, HasAttrs, Stability}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{self, Lrc}; use rustc_errors::{DiagnosticBuilder, DiagnosticId}; -use rustc_parse::parser::module::DirectoryOwnership; use rustc_parse::{self, parser, MACRO_ARGUMENTS}; use rustc_session::parse::ParseSess; use rustc_span::edition::Edition; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 46f10ca3614..8e83e13fa8a 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -2,6 +2,7 @@ use crate::base::*; use crate::config::StripUnconfigured; use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext}; use crate::mbe::macro_rules::annotate_err_with_kind; +use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; use crate::placeholders::{placeholder, PlaceholderExpander}; use crate::proc_macro::collect_derives; @@ -18,9 +19,6 @@ use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; use rustc_parse::configure; -use rustc_parse::parser::module::{ - parse_external_mod, push_directory, Directory, DirectoryOwnership, -}; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index f119c956ced..98d644eb77a 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -4,6 +4,7 @@ #![feature(proc_macro_diagnostic)] #![feature(proc_macro_internals)] #![feature(proc_macro_span)] +#![feature(try_blocks)] extern crate proc_macro as pm; @@ -34,6 +35,7 @@ crate use rustc_span::hygiene; pub mod base; pub mod build; pub mod expand; +pub mod module; pub use rustc_parse::config; pub mod proc_macro; diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_expand/module.rs similarity index 99% rename from src/librustc_parse/parser/module.rs rename to src/librustc_expand/module.rs index e45a26bd441..1d4c767b84f 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_expand/module.rs @@ -1,8 +1,7 @@ -use crate::new_sub_parser_from_file; - use rustc_ast::ast::{self, Attribute, Ident, Mod}; use rustc_ast::{attr, token}; use rustc_errors::{struct_span_err, PResult}; +use rustc_parse::new_sub_parser_from_file; use rustc_session::parse::ParseSess; use rustc_span::source_map::{FileName, Span}; use rustc_span::symbol::sym; @@ -39,7 +38,7 @@ pub struct ModulePathSuccess { pub ownership: DirectoryOwnership, } -pub fn parse_external_mod( +crate fn parse_external_mod( sess: &ParseSess, id: ast::Ident, Directory { mut ownership, path }: Directory, @@ -98,7 +97,7 @@ fn error_on_circular_module<'a>( Ok(()) } -pub fn push_directory( +crate fn push_directory( id: Ident, attrs: &[Attribute], Directory { mut ownership, mut path }: Directory, diff --git a/src/librustc_parse/parser/mod.rs b/src/librustc_parse/parser/mod.rs index f4862a6c87b..bb6793d08aa 100644 --- a/src/librustc_parse/parser/mod.rs +++ b/src/librustc_parse/parser/mod.rs @@ -1,8 +1,6 @@ pub mod attr; mod expr; mod item; -pub mod module; -pub use module::{ModulePath, ModulePathSuccess}; mod pat; mod path; mod ty; From 31ee8e0a4396898929702db7743988b6f9916fe1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:32:25 +0100 Subject: [PATCH 1230/1250] {rustc_parse -> rustc_expand}::config --- src/{librustc_parse => librustc_expand}/config.rs | 14 +++----------- src/librustc_expand/expand.rs | 2 +- src/librustc_expand/lib.rs | 4 +++- src/librustc_parse/lib.rs | 2 -- src/librustc_parse/validate_attr.rs | 2 +- 5 files changed, 8 insertions(+), 16 deletions(-) rename src/{librustc_parse => librustc_expand}/config.rs (97%) diff --git a/src/librustc_parse/config.rs b/src/librustc_expand/config.rs similarity index 97% rename from src/librustc_parse/config.rs rename to src/librustc_expand/config.rs index c611f249420..72c09f35dfa 100644 --- a/src/librustc_parse/config.rs +++ b/src/librustc_expand/config.rs @@ -1,14 +1,5 @@ -//! Process the potential `cfg` attributes on a module. -//! Also determine if the module should be included in this configuration. -//! -//! This module properly belongs in rustc_expand, but for now it's tied into -//! parsing, so we leave it here to avoid complicated out-of-line dependencies. -//! -//! A principled solution to this wrong location would be to implement [#64197]. -//! -//! [#64197]: https://github.com/rust-lang/rust/issues/64197 - -use crate::{parse_in, validate_attr}; +//! Conditional compilation stripping. + use rustc_ast::ast::{self, AttrItem, Attribute, MetaItem}; use rustc_ast::attr::HasAttrs; use rustc_ast::mut_visit::*; @@ -21,6 +12,7 @@ use rustc_feature::{Feature, Features, State as FeatureState}; use rustc_feature::{ ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES, }; +use rustc_parse::{parse_in, validate_attr}; use rustc_session::parse::{feature_err, ParseSess}; use rustc_span::edition::{Edition, ALL_EDITIONS}; use rustc_span::symbol::{sym, Symbol}; diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 8e83e13fa8a..db6a64b3b35 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1,5 +1,6 @@ use crate::base::*; use crate::config::StripUnconfigured; +use crate::configure; use crate::hygiene::{ExpnData, ExpnId, ExpnKind, SyntaxContext}; use crate::mbe::macro_rules::annotate_err_with_kind; use crate::module::{parse_external_mod, push_directory, Directory, DirectoryOwnership}; @@ -18,7 +19,6 @@ use rustc_ast_pretty::pprust; use rustc_attr::{self as attr, is_builtin_attr, HasAttrs}; use rustc_errors::{Applicability, FatalError, PResult}; use rustc_feature::Features; -use rustc_parse::configure; use rustc_parse::parser::Parser; use rustc_parse::validate_attr; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; diff --git a/src/librustc_expand/lib.rs b/src/librustc_expand/lib.rs index 98d644eb77a..0320a275e5d 100644 --- a/src/librustc_expand/lib.rs +++ b/src/librustc_expand/lib.rs @@ -1,3 +1,4 @@ +#![feature(bool_to_option)] #![feature(cow_is_borrowed)] #![feature(crate_visibility_modifier)] #![feature(decl_macro)] @@ -34,9 +35,10 @@ pub use mbe::macro_rules::compile_declarative_macro; crate use rustc_span::hygiene; pub mod base; pub mod build; +#[macro_use] +pub mod config; pub mod expand; pub mod module; -pub use rustc_parse::config; pub mod proc_macro; crate mod mbe; diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 70aa8c0074a..a23f74a8894 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -26,8 +26,6 @@ pub mod parser; use parser::{emit_unclosed_delims, make_unclosed_delims_error, Parser}; pub mod lexer; pub mod validate_attr; -#[macro_use] -pub mod config; // A bunch of utility functions of the form `parse__from_` // where includes crate, expr, item, stmt, tts, and one that diff --git a/src/librustc_parse/validate_attr.rs b/src/librustc_parse/validate_attr.rs index 029aa5ed2ba..2512878ec65 100644 --- a/src/librustc_parse/validate_attr.rs +++ b/src/librustc_parse/validate_attr.rs @@ -57,7 +57,7 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta }) } -crate fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { +pub fn check_meta_bad_delim(sess: &ParseSess, span: DelimSpan, delim: MacDelimiter, msg: &str) { if let ast::MacDelimiter::Parenthesis = delim { return; } From a6cb04ff2303bcebf15583097ffb05e865eea7f4 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Sun, 8 Mar 2020 22:48:24 +0100 Subject: [PATCH 1231/1250] add test for stripped nested outline module --- .../ui/parser/stripped-nested-outline-mod-pass.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 src/test/ui/parser/stripped-nested-outline-mod-pass.rs diff --git a/src/test/ui/parser/stripped-nested-outline-mod-pass.rs b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs new file mode 100644 index 00000000000..1b4669a439f --- /dev/null +++ b/src/test/ui/parser/stripped-nested-outline-mod-pass.rs @@ -0,0 +1,13 @@ +// Expansion drives parsing, so conditional compilation will strip +// out outline modules and we will never attempt parsing them. + +// check-pass + +fn main() {} + +#[cfg(FALSE)] +mod foo { + mod bar { + mod baz; // This was an error before. + } +} From 7d0e5bbb67f5c1d30b8c23bbfdaa6ed3cc281786 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 9 Mar 2020 10:35:35 +0100 Subject: [PATCH 1232/1250] parser/expand: minor cleanup --- src/librustc_expand/mbe/macro_rules.rs | 4 ++-- src/librustc_parse/lib.rs | 15 --------------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/librustc_expand/mbe/macro_rules.rs b/src/librustc_expand/mbe/macro_rules.rs index 1628d8bfdbc..3de2169f114 100644 --- a/src/librustc_expand/mbe/macro_rules.rs +++ b/src/librustc_expand/mbe/macro_rules.rs @@ -258,7 +258,7 @@ fn generic_extension<'cx>( trace_macros_note(&mut cx.expansions, sp, msg); } - let mut p = Parser::new(cx.parse_sess(), tts, false, None); + let mut p = Parser::new(sess, tts, false, None); p.root_module_name = cx.current_expansion.module.mod_path.last().map(|id| id.to_string()); p.last_type_ascription = cx.current_expansion.prior_type_ascription; @@ -1204,7 +1204,7 @@ fn quoted_tt_to_string(tt: &mbe::TokenTree) -> String { } } -fn parser_from_cx<'cx>(sess: &'cx ParseSess, tts: TokenStream) -> Parser<'cx> { +fn parser_from_cx(sess: &ParseSess, tts: TokenStream) -> Parser<'_> { Parser::new(sess, tts, true, rustc_parse::MACRO_ARGUMENTS) } diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index a23f74a8894..c31cc1b4c9f 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -238,21 +238,6 @@ pub fn stream_to_parser<'a>( Parser::new(sess, stream, false, subparser_name) } -/// Given a stream, the `ParseSess` and the base directory, produces a parser. -/// -/// Use this function when you are creating a parser from the token stream -/// and also care about the current working directory of the parser (e.g., -/// you are trying to resolve modules defined inside a macro invocation). -/// -/// # Note -/// -/// The main usage of this function is outside of rustc, for those who uses -/// librustc_ast as a library. Please do not remove this function while refactoring -/// just because it is not used in rustc codebase! -pub fn stream_to_parser_with_base_dir(sess: &ParseSess, stream: TokenStream) -> Parser<'_> { - Parser::new(sess, stream, false, None) -} - /// Runs the given subparser `f` on the tokens of the given `attr`'s item. pub fn parse_in<'a, T>( sess: &'a ParseSess, From fe713420911b6f0d7816ba5254f364557cfc8284 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 9 Mar 2020 11:16:00 +0100 Subject: [PATCH 1233/1250] tweak outline module parsing spans --- src/librustc_expand/expand.rs | 9 ++--- src/librustc_expand/module.rs | 40 ++++++++++--------- src/librustc_parse/parser/item.rs | 2 +- .../directory_ownership/macro-expanded-mod.rs | 4 +- .../macro-expanded-mod.stderr | 9 ++++- .../non-inline-mod-restriction.stderr | 4 +- src/test/ui/error-codes/E0583.stderr | 4 +- .../invalid-module-declaration.stderr | 4 +- .../missing_non_modrs_mod.stderr | 4 +- .../missing_non_modrs_mod_inline.stderr | 4 +- src/test/ui/mod/mod_file_disambig.stderr | 4 +- .../ui/parser/circular_modules_main.stderr | 4 +- src/test/ui/parser/issue-5806.stderr | 4 +- src/test/ui/parser/mod_file_not_exist.stderr | 4 +- .../ui/parser/mod_file_with_path_attr.stderr | 4 +- 15 files changed, 55 insertions(+), 49 deletions(-) diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index db6a64b3b35..834febceb1e 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1429,6 +1429,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { let mut attrs = mem::take(&mut item.attrs); // We do this to please borrowck. let ident = item.ident; + let span = item.span; match item.kind { ast::ItemKind::MacCall(..) => { @@ -1436,10 +1437,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.check_attributes(&item.attrs); item.and_then(|item| match item.kind { ItemKind::MacCall(mac) => self - .collect( - AstFragmentKind::Items, - InvocationKind::Bang { mac, span: item.span }, - ) + .collect(AstFragmentKind::Items, InvocationKind::Bang { mac, span }) .make_items(), _ => unreachable!(), }) @@ -1457,7 +1455,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { push_directory(ident, &item.attrs, dir) } else { // We have an outline `mod foo;` so we need to parse the file. - let (new_mod, dir) = parse_external_mod(sess, ident, dir, &mut attrs, pushed); + let (new_mod, dir) = + parse_external_mod(sess, ident, span, dir, &mut attrs, pushed); *old_mod = new_mod; item.attrs = attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. diff --git a/src/librustc_expand/module.rs b/src/librustc_expand/module.rs index 1d4c767b84f..2d5e4d4e889 100644 --- a/src/librustc_expand/module.rs +++ b/src/librustc_expand/module.rs @@ -41,6 +41,7 @@ pub struct ModulePathSuccess { crate fn parse_external_mod( sess: &ParseSess, id: ast::Ident, + span: Span, // The span to blame on errors. Directory { mut ownership, path }: Directory, attrs: &mut Vec, pop_mod_stack: &mut bool, @@ -48,18 +49,18 @@ crate fn parse_external_mod( // We bail on the first error, but that error does not cause a fatal error... (1) let result: PResult<'_, _> = try { // Extract the file path and the new ownership. - let mp = submod_path(sess, id, &attrs, ownership, &path)?; + let mp = submod_path(sess, id, span, &attrs, ownership, &path)?; ownership = mp.ownership; // Ensure file paths are acyclic. let mut included_mod_stack = sess.included_mod_stack.borrow_mut(); - error_on_circular_module(sess, id.span, &mp.path, &included_mod_stack)?; + error_on_circular_module(sess, span, &mp.path, &included_mod_stack)?; included_mod_stack.push(mp.path.clone()); *pop_mod_stack = true; // We have pushed, so notify caller. drop(included_mod_stack); // Actually parse the external file as amodule. - let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), id.span); + let mut p0 = new_sub_parser_from_file(sess, &mp.path, Some(id.to_string()), span); let mut module = p0.parse_mod(&token::Eof)?; module.0.inline = false; module @@ -126,6 +127,7 @@ crate fn push_directory( fn submod_path<'a>( sess: &'a ParseSess, id: ast::Ident, + span: Span, attrs: &[Attribute], ownership: DirectoryOwnership, dir_path: &Path, @@ -150,54 +152,53 @@ fn submod_path<'a>( DirectoryOwnership::UnownedViaBlock | DirectoryOwnership::UnownedViaMod => None, }; let ModulePath { path_exists, name, result } = - default_submod_path(sess, id, relative, dir_path); + default_submod_path(sess, id, span, relative, dir_path); match ownership { DirectoryOwnership::Owned { .. } => Ok(result?), DirectoryOwnership::UnownedViaBlock => { let _ = result.map_err(|mut err| err.cancel()); - error_decl_mod_in_block(sess, id.span, path_exists, &name) + error_decl_mod_in_block(sess, span, path_exists, &name) } DirectoryOwnership::UnownedViaMod => { let _ = result.map_err(|mut err| err.cancel()); - error_cannot_declare_mod_here(sess, id.span, path_exists, &name) + error_cannot_declare_mod_here(sess, span, path_exists, &name) } } } fn error_decl_mod_in_block<'a, T>( sess: &'a ParseSess, - id_sp: Span, + span: Span, path_exists: bool, name: &str, ) -> PResult<'a, T> { let msg = "Cannot declare a non-inline module inside a block unless it has a path attribute"; - let mut err = sess.span_diagnostic.struct_span_err(id_sp, msg); + let mut err = sess.span_diagnostic.struct_span_err(span, msg); if path_exists { let msg = format!("Maybe `use` the module `{}` instead of redeclaring it", name); - err.span_note(id_sp, &msg); + err.span_note(span, &msg); } Err(err) } fn error_cannot_declare_mod_here<'a, T>( sess: &'a ParseSess, - id_sp: Span, + span: Span, path_exists: bool, name: &str, ) -> PResult<'a, T> { let mut err = - sess.span_diagnostic.struct_span_err(id_sp, "cannot declare a new module at this location"); - if !id_sp.is_dummy() { - if let FileName::Real(src_path) = sess.source_map().span_to_filename(id_sp) { + sess.span_diagnostic.struct_span_err(span, "cannot declare a new module at this location"); + if !span.is_dummy() { + if let FileName::Real(src_path) = sess.source_map().span_to_filename(span) { if let Some(stem) = src_path.file_stem() { let mut dest_path = src_path.clone(); dest_path.set_file_name(stem); dest_path.push("mod.rs"); err.span_note( - id_sp, + span, &format!( - "maybe move this module `{}` to its own \ - directory via `{}`", + "maybe move this module `{}` to its own directory via `{}`", src_path.display(), dest_path.display() ), @@ -207,7 +208,7 @@ fn error_cannot_declare_mod_here<'a, T>( } if path_exists { err.span_note( - id_sp, + span, &format!("... or maybe `use` the module `{}` instead of possibly redeclaring it", name), ); } @@ -237,6 +238,7 @@ pub fn submod_path_from_attr(attrs: &[Attribute], dir_path: &Path) -> Option( sess: &'a ParseSess, id: ast::Ident, + span: Span, relative: Option, dir_path: &Path, ) -> ModulePath<'a> { @@ -273,7 +275,7 @@ pub fn default_submod_path<'a>( (false, false) => { let mut err = struct_span_err!( sess.span_diagnostic, - id.span, + span, E0583, "file not found for module `{}`", mod_name, @@ -288,7 +290,7 @@ pub fn default_submod_path<'a>( (true, true) => { let mut err = struct_span_err!( sess.span_diagnostic, - id.span, + span, E0584, "file for module `{}` found at both {} and {}", mod_name, diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index d0da8e6c7c1..873b7e93c6f 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -38,7 +38,7 @@ impl<'a> Parser<'a> { } /// Parses a `mod { ... }` or `mod ;` item. - pub(super) fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { + fn parse_item_mod(&mut self, attrs: &mut Vec) -> PResult<'a, ItemInfo> { let id = self.parse_ident()?; let (module, mut inner_attrs) = if self.eat(&token::Semi) { Default::default() diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.rs b/src/test/ui/directory_ownership/macro-expanded-mod.rs index 1066a2ba712..9cb159603a8 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.rs +++ b/src/test/ui/directory_ownership/macro-expanded-mod.rs @@ -2,7 +2,7 @@ macro_rules! mod_decl { ($i:ident) => { - mod $i; + mod $i; //~ ERROR Cannot declare a non-inline module inside a block }; } @@ -11,5 +11,5 @@ mod macro_expanded_mod_helper { } fn main() { - mod_decl!(foo); //~ ERROR Cannot declare a non-inline module inside a block + mod_decl!(foo); } diff --git a/src/test/ui/directory_ownership/macro-expanded-mod.stderr b/src/test/ui/directory_ownership/macro-expanded-mod.stderr index d9d8a8ffed7..f90419247c9 100644 --- a/src/test/ui/directory_ownership/macro-expanded-mod.stderr +++ b/src/test/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,8 +1,13 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/macro-expanded-mod.rs:14:15 + --> $DIR/macro-expanded-mod.rs:5:9 | +LL | mod $i; + | ^^^^^^^ +... LL | mod_decl!(foo); - | ^^^ + | --------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr index 46acc7e66d8..d034942ca5d 100644 --- a/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr +++ b/src/test/ui/directory_ownership/non-inline-mod-restriction.stderr @@ -1,8 +1,8 @@ error: Cannot declare a non-inline module inside a block unless it has a path attribute - --> $DIR/non-inline-mod-restriction.rs:4:9 + --> $DIR/non-inline-mod-restriction.rs:4:5 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/error-codes/E0583.stderr b/src/test/ui/error-codes/E0583.stderr index 5d47b633e78..dbe70035595 100644 --- a/src/test/ui/error-codes/E0583.stderr +++ b/src/test/ui/error-codes/E0583.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `module_that_doesnt_exist` - --> $DIR/E0583.rs:1:5 + --> $DIR/E0583.rs:1:1 | LL | mod module_that_doesnt_exist; - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: to create the module `module_that_doesnt_exist`, create file "$DIR/module_that_doesnt_exist.rs" diff --git a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr index 5d2cdaef1a7..52296042eb4 100644 --- a/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr +++ b/src/test/ui/invalid-module-declaration/invalid-module-declaration.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `baz` - --> $DIR/auxiliary/foo/bar.rs:1:9 + --> $DIR/auxiliary/foo/bar.rs:1:1 | LL | pub mod baz; - | ^^^ + | ^^^^^^^^^^^^ | = help: to create the module `baz`, create file "$DIR/auxiliary/foo/bar/baz.rs" diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr index e8d997e6de0..91b3fe15c4b 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo.rs:4:5 + --> $DIR/foo.rs:4:1 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | = help: to create the module `missing`, create file "$DIR/foo/missing.rs" diff --git a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr index b2b0f8b466a..f519de46c76 100644 --- a/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr +++ b/src/test/ui/missing_non_modrs_mod/missing_non_modrs_mod_inline.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `missing` - --> $DIR/foo_inline.rs:4:9 + --> $DIR/foo_inline.rs:4:5 | LL | mod missing; - | ^^^^^^^ + | ^^^^^^^^^^^^ | = help: to create the module `missing`, create file "$DIR/foo_inline/inline/missing.rs" diff --git a/src/test/ui/mod/mod_file_disambig.stderr b/src/test/ui/mod/mod_file_disambig.stderr index 230bfa79916..490633a3fb0 100644 --- a/src/test/ui/mod/mod_file_disambig.stderr +++ b/src/test/ui/mod/mod_file_disambig.stderr @@ -1,8 +1,8 @@ error[E0584]: file for module `mod_file_disambig_aux` found at both mod_file_disambig_aux.rs and mod_file_disambig_aux/mod.rs - --> $DIR/mod_file_disambig.rs:1:5 + --> $DIR/mod_file_disambig.rs:1:1 | LL | mod mod_file_disambig_aux; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: delete or rename one of them to remove the ambiguity diff --git a/src/test/ui/parser/circular_modules_main.stderr b/src/test/ui/parser/circular_modules_main.stderr index ca84f2d2854..90f81c64835 100644 --- a/src/test/ui/parser/circular_modules_main.stderr +++ b/src/test/ui/parser/circular_modules_main.stderr @@ -1,8 +1,8 @@ error: circular modules: $DIR/circular_modules_hello.rs -> $DIR/circular_modules_main.rs -> $DIR/circular_modules_hello.rs - --> $DIR/circular_modules_main.rs:2:5 + --> $DIR/circular_modules_main.rs:2:1 | LL | mod circular_modules_hello; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0425]: cannot find function `say_hello` in module `circular_modules_hello` --> $DIR/circular_modules_main.rs:9:29 diff --git a/src/test/ui/parser/issue-5806.stderr b/src/test/ui/parser/issue-5806.stderr index 6cf902ca86e..bdb5c91ff91 100644 --- a/src/test/ui/parser/issue-5806.stderr +++ b/src/test/ui/parser/issue-5806.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/../parser: $ACCESS_DENIED_MSG (os error $ACCESS_DENIED_CODE) - --> $DIR/issue-5806.rs:5:5 + --> $DIR/issue-5806.rs:5:1 | LL | mod foo; - | ^^^ + | ^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/parser/mod_file_not_exist.stderr b/src/test/ui/parser/mod_file_not_exist.stderr index c298c51c4f8..087ae9fe3e0 100644 --- a/src/test/ui/parser/mod_file_not_exist.stderr +++ b/src/test/ui/parser/mod_file_not_exist.stderr @@ -1,8 +1,8 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist.rs:3:5 + --> $DIR/mod_file_not_exist.rs:3:1 | LL | mod not_a_real_file; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" diff --git a/src/test/ui/parser/mod_file_with_path_attr.stderr b/src/test/ui/parser/mod_file_with_path_attr.stderr index 004b5d7963a..cd1add73d58 100644 --- a/src/test/ui/parser/mod_file_with_path_attr.stderr +++ b/src/test/ui/parser/mod_file_with_path_attr.stderr @@ -1,8 +1,8 @@ error: couldn't read $DIR/not_a_real_file.rs: $FILE_NOT_FOUND_MSG (os error 2) - --> $DIR/mod_file_with_path_attr.rs:4:5 + --> $DIR/mod_file_with_path_attr.rs:4:1 | LL | mod m; - | ^ + | ^^^^^^ error: aborting due to previous error From 41a0b3ec53237ae844a741cffe727ee302b53a67 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 10 Mar 2020 07:21:40 +0100 Subject: [PATCH 1234/1250] use pretty-compare-only in a test --- src/test/pretty/issue-12590-a.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/pretty/issue-12590-a.rs b/src/test/pretty/issue-12590-a.rs index 1a9e85c42d8..ca1fef83cff 100644 --- a/src/test/pretty/issue-12590-a.rs +++ b/src/test/pretty/issue-12590-a.rs @@ -1,4 +1,5 @@ // pp-exact +// pretty-compare-only // The next line should not be expanded From 5ee4f6f660f9e7516e0a188068c173b0d83347e8 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 16 Mar 2020 00:43:37 +0100 Subject: [PATCH 1235/1250] fix pre-expansion linting infra --- src/libpanic_unwind/emcc.rs | 2 -- src/libpanic_unwind/gcc.rs | 2 -- src/libpanic_unwind/seh.rs | 1 - .../proc_macro_harness.rs | 2 +- .../standard_library_imports.rs | 2 +- src/librustc_builtin_macros/test_harness.rs | 2 +- src/librustc_expand/base.rs | 6 ++++- src/librustc_expand/expand.rs | 15 ++++++++++-- src/librustc_interface/passes.rs | 23 +++++++++++-------- src/librustc_lint/early.rs | 18 ++++----------- .../change_symbol_export_status.rs | 6 ++--- .../auxiliary/linkage-visibility.rs | 12 ++++------ .../lint/lint-pre-expansion-extern-module.rs | 7 ++++++ .../lint-pre-expansion-extern-module.stderr | 10 ++++++++ .../lint_pre_expansion_extern_module_aux.rs | 3 +++ 15 files changed, 67 insertions(+), 44 deletions(-) create mode 100644 src/test/ui/lint/lint-pre-expansion-extern-module.rs create mode 100644 src/test/ui/lint/lint-pre-expansion-extern-module.stderr create mode 100644 src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs diff --git a/src/libpanic_unwind/emcc.rs b/src/libpanic_unwind/emcc.rs index c7144fe16cd..a0bdb1481c6 100644 --- a/src/libpanic_unwind/emcc.rs +++ b/src/libpanic_unwind/emcc.rs @@ -6,8 +6,6 @@ //! Emscripten's runtime always implements those APIs and does not //! implement libunwind. -#![allow(private_no_mangle_fns)] - use alloc::boxed::Box; use core::any::Any; use core::mem; diff --git a/src/libpanic_unwind/gcc.rs b/src/libpanic_unwind/gcc.rs index 9c032b30341..1622442a5eb 100644 --- a/src/libpanic_unwind/gcc.rs +++ b/src/libpanic_unwind/gcc.rs @@ -36,8 +36,6 @@ //! Once stack has been unwound down to the handler frame level, unwinding stops //! and the last personality routine transfers control to the catch block. -#![allow(private_no_mangle_fns)] - use alloc::boxed::Box; use core::any::Any; diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index c294fe26327..10b765a5b41 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -45,7 +45,6 @@ //! [llvm]: http://llvm.org/docs/ExceptionHandling.html#background-on-windows-exceptions #![allow(nonstandard_style)] -#![allow(private_no_mangle_fns)] use alloc::boxed::Box; use core::any::Any; diff --git a/src/librustc_builtin_macros/proc_macro_harness.rs b/src/librustc_builtin_macros/proc_macro_harness.rs index 179b0133426..71622a3b7e6 100644 --- a/src/librustc_builtin_macros/proc_macro_harness.rs +++ b/src/librustc_builtin_macros/proc_macro_harness.rs @@ -59,7 +59,7 @@ pub fn inject( handler: &rustc_errors::Handler, ) -> ast::Crate { let ecfg = ExpansionConfig::default("proc_macro".to_string()); - let mut cx = ExtCtxt::new(sess, ecfg, resolver); + let mut cx = ExtCtxt::new(sess, ecfg, resolver, None); let mut collect = CollectProcMacros { macros: Vec::new(), diff --git a/src/librustc_builtin_macros/standard_library_imports.rs b/src/librustc_builtin_macros/standard_library_imports.rs index 30403f6dc41..f48fd6df9c9 100644 --- a/src/librustc_builtin_macros/standard_library_imports.rs +++ b/src/librustc_builtin_macros/standard_library_imports.rs @@ -39,7 +39,7 @@ pub fn inject( let call_site = DUMMY_SP.with_call_site_ctxt(expn_id); let ecfg = ExpansionConfig::default("std_lib_injection".to_string()); - let cx = ExtCtxt::new(sess, ecfg, resolver); + let cx = ExtCtxt::new(sess, ecfg, resolver, None); // .rev() to preserve ordering above in combination with insert(0, ...) for &name in names.iter().rev() { diff --git a/src/librustc_builtin_macros/test_harness.rs b/src/librustc_builtin_macros/test_harness.rs index 15997a27fad..b87767f4a41 100644 --- a/src/librustc_builtin_macros/test_harness.rs +++ b/src/librustc_builtin_macros/test_harness.rs @@ -202,7 +202,7 @@ fn generate_test_harness( let mut econfig = ExpansionConfig::default("test".to_string()); econfig.features = Some(features); - let ext_cx = ExtCtxt::new(sess, econfig, resolver); + let ext_cx = ExtCtxt::new(sess, econfig, resolver, None); let expn_id = ext_cx.resolver.expansion_for_ast_pass( DUMMY_SP, diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs index 1e9d59ca4bf..74c304c96b9 100644 --- a/src/librustc_expand/base.rs +++ b/src/librustc_expand/base.rs @@ -926,6 +926,8 @@ pub struct ExtCtxt<'a> { pub resolver: &'a mut dyn Resolver, pub current_expansion: ExpansionData, pub expansions: FxHashMap>, + /// Called directly after having parsed an external `mod foo;` in expansion. + pub(super) extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, } impl<'a> ExtCtxt<'a> { @@ -933,12 +935,14 @@ impl<'a> ExtCtxt<'a> { parse_sess: &'a ParseSess, ecfg: expand::ExpansionConfig<'a>, resolver: &'a mut dyn Resolver, + extern_mod_loaded: Option<&'a dyn Fn(&ast::Crate)>, ) -> ExtCtxt<'a> { ExtCtxt { parse_sess, ecfg, - root_path: PathBuf::new(), resolver, + extern_mod_loaded, + root_path: PathBuf::new(), current_expansion: ExpansionData { id: ExpnId::root(), depth: 0, diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs index 834febceb1e..b6cc192cc33 100644 --- a/src/librustc_expand/expand.rs +++ b/src/librustc_expand/expand.rs @@ -1457,8 +1457,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { // We have an outline `mod foo;` so we need to parse the file. let (new_mod, dir) = parse_external_mod(sess, ident, span, dir, &mut attrs, pushed); - *old_mod = new_mod; - item.attrs = attrs; + + let krate = ast::Crate { + span: new_mod.inner, + module: new_mod, + attrs, + proc_macros: vec![], + }; + if let Some(extern_mod_loaded) = self.cx.extern_mod_loaded { + extern_mod_loaded(&krate); + } + + *old_mod = krate.module; + item.attrs = krate.attrs; // File can have inline attributes, e.g., `#![cfg(...)]` & co. => Reconfigure. item = match self.configure(item) { Some(node) => node, diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs index 4fe7a06e560..93f0beaa48b 100644 --- a/src/librustc_interface/passes.rs +++ b/src/librustc_interface/passes.rs @@ -210,14 +210,7 @@ pub fn register_plugins<'a>( Ok((krate, Lrc::new(lint_store))) } -fn configure_and_expand_inner<'a>( - sess: &'a Session, - lint_store: &'a LintStore, - mut krate: ast::Crate, - crate_name: &str, - resolver_arenas: &'a ResolverArenas<'a>, - metadata_loader: &'a MetadataLoaderDyn, -) -> Result<(ast::Crate, Resolver<'a>)> { +fn pre_expansion_lint(sess: &Session, lint_store: &LintStore, krate: &ast::Crate) { sess.time("pre_AST_expansion_lint_checks", || { rustc_lint::check_ast_crate( sess, @@ -228,6 +221,17 @@ fn configure_and_expand_inner<'a>( rustc_lint::BuiltinCombinedPreExpansionLintPass::new(), ); }); +} + +fn configure_and_expand_inner<'a>( + sess: &'a Session, + lint_store: &'a LintStore, + mut krate: ast::Crate, + crate_name: &str, + resolver_arenas: &'a ResolverArenas<'a>, + metadata_loader: &'a MetadataLoaderDyn, +) -> Result<(ast::Crate, Resolver<'a>)> { + pre_expansion_lint(sess, lint_store, &krate); let mut resolver = Resolver::new(sess, &krate, crate_name, metadata_loader, &resolver_arenas); rustc_builtin_macros::register_builtin_macros(&mut resolver, sess.edition()); @@ -291,7 +295,8 @@ fn configure_and_expand_inner<'a>( ..rustc_expand::expand::ExpansionConfig::default(crate_name.to_string()) }; - let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver); + let extern_mod_loaded = |k: &ast::Crate| pre_expansion_lint(sess, lint_store, k); + let mut ecx = ExtCtxt::new(&sess.parse_sess, cfg, &mut resolver, Some(&extern_mod_loaded)); // Expand macros now! let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate)); diff --git a/src/librustc_lint/early.rs b/src/librustc_lint/early.rs index a5da960d888..34da29c9747 100644 --- a/src/librustc_lint/early.rs +++ b/src/librustc_lint/early.rs @@ -18,7 +18,7 @@ use crate::context::{EarlyContext, LintContext, LintStore}; use crate::passes::{EarlyLintPass, EarlyLintPassObject}; use rustc_ast::ast; use rustc_ast::visit as ast_visit; -use rustc_session::lint::{LintBuffer, LintPass}; +use rustc_session::lint::{BufferedEarlyLint, LintBuffer, LintPass}; use rustc_session::Session; use rustc_span::Span; @@ -37,13 +37,7 @@ struct EarlyContextAndPass<'a, T: EarlyLintPass> { impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> { fn check_id(&mut self, id: ast::NodeId) { for early_lint in self.context.buffered.take(id) { - let rustc_session::lint::BufferedEarlyLint { - span, - msg, - node_id: _, - lint_id, - diagnostic, - } = early_lint; + let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint; self.context.lookup_with_diagnostics( lint_id.lint, Some(span), @@ -326,11 +320,9 @@ pub fn check_ast_crate( lint_buffer: Option, builtin_lints: T, ) { - let mut passes: Vec<_> = if pre_expansion { - lint_store.pre_expansion_passes.iter().map(|p| (p)()).collect() - } else { - lint_store.early_passes.iter().map(|p| (p)()).collect() - }; + let passes = + if pre_expansion { &lint_store.pre_expansion_passes } else { &lint_store.early_passes }; + let mut passes: Vec<_> = passes.iter().map(|p| (p)()).collect(); let mut buffered = lint_buffer.unwrap_or_default(); if !sess.opts.debugging_opts.no_interleave_lints { diff --git a/src/test/incremental/change_symbol_export_status.rs b/src/test/incremental/change_symbol_export_status.rs index f3de46d99dd..9b3b381d621 100644 --- a/src/test/incremental/change_symbol_export_status.rs +++ b/src/test/incremental/change_symbol_export_status.rs @@ -2,10 +2,8 @@ // compile-flags: -Zquery-dep-graph #![feature(rustc_attrs)] -#![allow(private_no_mangle_fns)] - -#![rustc_partition_codegened(module="change_symbol_export_status-mod1", cfg="rpass2")] -#![rustc_partition_reused(module="change_symbol_export_status-mod2", cfg="rpass2")] +#![rustc_partition_codegened(module = "change_symbol_export_status-mod1", cfg = "rpass2")] +#![rustc_partition_reused(module = "change_symbol_export_status-mod2", cfg = "rpass2")] // This test case makes sure that a change in symbol visibility is detected by // our dependency tracking. We do this by changing a module's visibility to diff --git a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs index 8917693d45e..837ed1f002f 100644 --- a/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs +++ b/src/test/ui-fulldeps/auxiliary/linkage-visibility.rs @@ -2,16 +2,14 @@ #![feature(rustc_private)] -// We're testing linkage visibility; the compiler warns us, but we want to -// do the runtime check that these functions aren't exported. -#![allow(private_no_mangle_fns)] - extern crate rustc_metadata; use rustc_metadata::dynamic_lib::DynamicLibrary; #[no_mangle] -pub fn foo() { bar(); } +pub fn foo() { + bar(); +} pub fn foo2() { fn bar2() { @@ -21,11 +19,11 @@ pub fn foo2() { } #[no_mangle] -fn bar() { } +fn bar() {} #[allow(dead_code)] #[no_mangle] -fn baz() { } +fn baz() {} pub fn test() { let lib = DynamicLibrary::open(None).unwrap(); diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.rs b/src/test/ui/lint/lint-pre-expansion-extern-module.rs new file mode 100644 index 00000000000..30e2ed8b7a6 --- /dev/null +++ b/src/test/ui/lint/lint-pre-expansion-extern-module.rs @@ -0,0 +1,7 @@ +// check-pass +// compile-flags: -W rust-2018-compatibility +// error-pattern: `try` is a keyword in the 2018 edition + +fn main() {} + +mod lint_pre_expansion_extern_module_aux; diff --git a/src/test/ui/lint/lint-pre-expansion-extern-module.stderr b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr new file mode 100644 index 00000000000..c683a3fa670 --- /dev/null +++ b/src/test/ui/lint/lint-pre-expansion-extern-module.stderr @@ -0,0 +1,10 @@ +warning: `try` is a keyword in the 2018 edition + --> $DIR/lint_pre_expansion_extern_module_aux.rs:3:8 + | +LL | pub fn try() {} + | ^^^ help: you can use a raw identifier to stay compatible: `r#try` + | + = note: `-W keyword-idents` implied by `-W rust-2018-compatibility` + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in the 2018 edition! + = note: for more information, see issue #49716 + diff --git a/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs new file mode 100644 index 00000000000..71dec40ea44 --- /dev/null +++ b/src/test/ui/lint/lint_pre_expansion_extern_module_aux.rs @@ -0,0 +1,3 @@ +// ignore-test: not a test + +pub fn try() {} From e301291cb6523b415e0a64ea61cb4728b9ca2c0a Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Mon, 16 Mar 2020 00:56:27 +0100 Subject: [PATCH 1236/1250] fix rebase fallout --- src/librustc_parse/parser/item.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs index 873b7e93c6f..9d70f606f3e 100644 --- a/src/librustc_parse/parser/item.rs +++ b/src/librustc_parse/parser/item.rs @@ -6,14 +6,11 @@ use crate::maybe_whole; use rustc_ast::ast::{self, AttrStyle, AttrVec, Attribute, Ident, DUMMY_NODE_ID}; use rustc_ast::ast::{AssocItem, AssocItemKind, ForeignItemKind, Item, ItemKind, Mod}; -use rustc_ast::ast::{ - Async, Const, Defaultness, IsAuto, PathSegment, Unsafe, UseTree, UseTreeKind, -}; -use rustc_ast::ast::{ - BindingMode, Block, FnDecl, FnSig, MacArgs, MacCall, MacDelimiter, Param, SelfKind, -}; +use rustc_ast::ast::{Async, Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind}; +use rustc_ast::ast::{BindingMode, Block, FnDecl, FnSig, Param, SelfKind}; use rustc_ast::ast::{EnumDef, Generics, StructField, TraitRef, Ty, TyKind, Variant, VariantData}; -use rustc_ast::ast::{FnHeader, ForeignItem, Mutability, SelfKind, Visibility, VisibilityKind}; +use rustc_ast::ast::{FnHeader, ForeignItem, PathSegment, Visibility, VisibilityKind}; +use rustc_ast::ast::{MacArgs, MacCall, MacDelimiter}; use rustc_ast::ptr::P; use rustc_ast::token::{self, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; From 8caf688844e1c4ba3f3d554488efca7d0994b2b1 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 17 Mar 2020 04:39:22 +0100 Subject: [PATCH 1237/1250] --bless windows test --- src/test/ui/parser/mod_file_not_exist.rs | 2 +- src/test/ui/parser/mod_file_not_exist_windows.rs | 1 + .../ui/parser/mod_file_not_exist_windows.stderr | 15 +++++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/test/ui/parser/mod_file_not_exist.rs b/src/test/ui/parser/mod_file_not_exist.rs index aee778d1013..f4a27b52ec5 100644 --- a/src/test/ui/parser/mod_file_not_exist.rs +++ b/src/test/ui/parser/mod_file_not_exist.rs @@ -1,7 +1,7 @@ // ignore-windows mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` -//~^ HELP to create the module `not_a_real_file`, create file " +//~^ HELP to create the module `not_a_real_file`, create file fn main() { assert_eq!(mod_file_aux::bar(), 10); diff --git a/src/test/ui/parser/mod_file_not_exist_windows.rs b/src/test/ui/parser/mod_file_not_exist_windows.rs index 97cadab675f..4b7d7a02bbe 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.rs +++ b/src/test/ui/parser/mod_file_not_exist_windows.rs @@ -5,4 +5,5 @@ mod not_a_real_file; //~ ERROR file not found for module `not_a_real_file` fn main() { assert_eq!(mod_file_aux::bar(), 10); + //~^ ERROR failed to resolve: use of undeclared type or module `mod_file_aux` } diff --git a/src/test/ui/parser/mod_file_not_exist_windows.stderr b/src/test/ui/parser/mod_file_not_exist_windows.stderr index a58db80f73d..d67205cfdf1 100644 --- a/src/test/ui/parser/mod_file_not_exist_windows.stderr +++ b/src/test/ui/parser/mod_file_not_exist_windows.stderr @@ -1,11 +1,18 @@ error[E0583]: file not found for module `not_a_real_file` - --> $DIR/mod_file_not_exist_windows.rs:3:5 + --> $DIR/mod_file_not_exist_windows.rs:3:1 | LL | mod not_a_real_file; - | ^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^ | = help: to create the module `not_a_real_file`, create file "$DIR/not_a_real_file.rs" -error: aborting due to previous error +error[E0433]: failed to resolve: use of undeclared type or module `mod_file_aux` + --> $DIR/mod_file_not_exist_windows.rs:7:16 + | +LL | assert_eq!(mod_file_aux::bar(), 10); + | ^^^^^^^^^^^^ use of undeclared type or module `mod_file_aux` + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0583`. +Some errors have detailed explanations: E0433, E0583. +For more information about an error, try `rustc --explain E0433`. From 287c4eb0947c5b2df63633fc71005f2bab541673 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 18 Mar 2020 08:15:29 -0700 Subject: [PATCH 1238/1250] Tidy: fix running rustfmt twice --- src/bootstrap/format.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index a4acb14ee4b..1616ae15d31 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -37,6 +37,9 @@ struct RustfmtConfig { } pub fn format(build: &Build, check: bool) { + if build.config.dry_run { + return; + } let mut builder = ignore::types::TypesBuilder::new(); builder.add_defaults(); builder.select("rust"); From 779e5922eeae915cac3470f6f4b33f78fc740d80 Mon Sep 17 00:00:00 2001 From: Pietro Albini Date: Wed, 18 Mar 2020 18:57:37 +0100 Subject: [PATCH 1239/1250] ci: use python from the correct path Apparently the old path we were using for Python 2 on Windows was not documented, and eventually got removed. This switches our CI to use the correct path. --- src/ci/scripts/install-msys2-packages.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ci/scripts/install-msys2-packages.sh b/src/ci/scripts/install-msys2-packages.sh index 843a2bf2d5e..22b9854ad5e 100755 --- a/src/ci/scripts/install-msys2-packages.sh +++ b/src/ci/scripts/install-msys2-packages.sh @@ -13,6 +13,7 @@ if isWindows; then # one way or another. The msys interpreters seem to have weird path conversions # baked in which break LLVM's build system one way or another, so let's use the # native version which keeps everything as native as possible. - cp C:/Python27amd64/python.exe C:/Python27amd64/python2.7.exe - ciCommandAddPath "C:\\Python27amd64" + python_home="C:/hostedtoolcache/windows/Python/2.7.17/x64" + cp "${python_home}/python.exe" "${python_home}/python2.7.exe" + ciCommandAddPath "C:\\hostedtoolcache\\windows\\Python\\2.7.17\\x64" fi From 5e2856122a42a9e148d9d583561f7b07037bd3bc Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Fri, 7 Feb 2020 14:02:24 -0500 Subject: [PATCH 1240/1250] Properly handle Spans that reference imported SourceFiles Previously, metadata encoding used DUMMY_SP to represent any spans that referenced an 'imported' SourceFile - e.g. a SourceFile from an upstream dependency. These leads to sub-optimal error messages in certain cases (see the included test). This PR changes how we encode and decode spans in crate metadata. We encode spans in one of two ways: * 'Local' spans, which reference non-imported SourceFiles, are encoded exactly as before. * 'Foreign' spans, which reference imported SourceFiles, are encoded with the CrateNum of their 'originating' crate. Additionally, their 'lo' and 'high' values are rebased on top of the 'originating' crate, which allows them to be used with the SourceMap data encoded for that crate. The `ExternalSource` enum is renamed to `ExternalSourceKind`. There is now a struct called `ExternalSource`, which holds an `ExternalSourceKind` along with the original line number information for the file. This is used during `Span` serialization to rebase spans onto their 'owning' crate. --- src/librustc/hir/map/collector.rs | 4 +- src/librustc/ich/impls_syntax.rs | 8 +- src/librustc_metadata/rmeta/decoder.rs | 91 +++++++++++++++++-- src/librustc_metadata/rmeta/encoder.rs | 61 ++++++++++--- src/librustc_metadata/rmeta/mod.rs | 5 +- src/librustc_span/lib.rs | 61 ++++++++----- src/librustc_span/source_map.rs | 12 ++- .../ui/span/auxiliary/transitive_dep_three.rs | 9 ++ .../ui/span/auxiliary/transitive_dep_two.rs | 3 + src/test/ui/span/transitive-dep-span.rs | 13 +++ src/test/ui/span/transitive-dep-span.stderr | 19 ++++ 11 files changed, 234 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/span/auxiliary/transitive_dep_three.rs create mode 100644 src/test/ui/span/auxiliary/transitive_dep_two.rs create mode 100644 src/test/ui/span/transitive-dep-span.rs create mode 100644 src/test/ui/span/transitive-dep-span.stderr diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index e8233c0446d..8b276d0a762 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_INDEX; -use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{DefIndex, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; @@ -175,7 +175,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { .source_map .files() .iter() - .filter(|source_file| CrateNum::from_u32(source_file.crate_of_origin) == LOCAL_CRATE) + .filter(|source_file| source_file.cnum == LOCAL_CRATE) .map(|source_file| source_file.name_hash) .collect(); diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index daff8a0f182..c5a4b53b10d 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -5,7 +5,6 @@ use crate::ich::StableHashingContext; use rustc_ast::ast; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX}; use rustc_span::SourceFile; use smallvec::SmallVec; @@ -59,7 +58,7 @@ impl<'a> HashStable> for SourceFile { name_hash, name_was_remapped, unmapped_path: _, - crate_of_origin, + cnum, // Do not hash the source as it is not encoded src: _, src_hash, @@ -75,9 +74,6 @@ impl<'a> HashStable> for SourceFile { (name_hash as u64).hash_stable(hcx, hasher); name_was_remapped.hash_stable(hcx, hasher); - DefId { krate: CrateNum::from_u32(crate_of_origin), index: CRATE_DEF_INDEX } - .hash_stable(hcx, hasher); - src_hash.hash_stable(hcx, hasher); // We only hash the relative position within this source_file @@ -101,6 +97,8 @@ impl<'a> HashStable> for SourceFile { for &char_pos in normalized_pos.iter() { stable_normalized_pos(char_pos, start_pos).hash_stable(hcx, hasher); } + + cnum.hash_stable(hcx, hasher); } } diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index cf0f8816058..9cad086b4e8 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -386,7 +386,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { return Ok(DUMMY_SP); } - debug_assert_eq!(tag, TAG_VALID_SPAN); + debug_assert!(tag == TAG_VALID_SPAN_LOCAL || tag == TAG_VALID_SPAN_FOREIGN); let lo = BytePos::decode(self)?; let len = BytePos::decode(self)?; @@ -398,7 +398,68 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { bug!("Cannot decode Span without Session.") }; - let imported_source_files = self.cdata().imported_source_files(&sess.source_map()); + // There are two possibilities here: + // 1. This is a 'local span', which is located inside a `SourceFile` + // that came from this crate. In this case, we use the source map data + // encoded in this crate. This branch should be taken nearly all of the time. + // 2. This is a 'foreign span', which is located inside a `SourceFile` + // that came from a *different* crate (some crate upstream of the one + // whose metadata we're looking at). For example, consider this dependency graph: + // + // A -> B -> C + // + // Suppose that we're currently compiling crate A, and start deserializing + // metadata from crate B. When we deserialize a Span from crate B's metadata, + // there are two posibilites: + // + // 1. The span references a file from crate B. This makes it a 'local' span, + // which means that we can use crate B's serialized source map information. + // 2. The span references a file from crate C. This makes it a 'foreign' span, + // which means we need to use Crate *C* (not crate B) to determine the source + // map information. We only record source map information for a file in the + // crate that 'owns' it, so deserializing a Span may require us to look at + // a transitive dependency. + // + // When we encode a foreign span, we adjust its 'lo' and 'high' values + // to be based on the *foreign* crate (e.g. crate C), not the crate + // we are writing metadata for (e.g. crate B). This allows us to + // treat the 'local' and 'foreign' cases almost identically during deserialization: + // we can call `imported_source_files` for the proper crate, and binary search + // through the returned slice using our span. + let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL { + self.cdata().imported_source_files(sess.source_map()) + } else { + // FIXME: We don't decode dependencies of proc-macros. + // Remove this once #69976 is merged + if self.cdata().root.is_proc_macro_crate() { + debug!( + "SpecializedDecoder::specialized_decode: skipping span for proc-macro crate {:?}", + self.cdata().cnum + ); + // Decode `CrateNum` as u32 - using `CrateNum::decode` will ICE + // since we don't have `cnum_map` populated. + // This advances the decoder position so that we can continue + // to read metadata. + let _ = u32::decode(self)?; + return Ok(DUMMY_SP); + } + // tag is TAG_VALID_SPAN_FOREIGN, checked by `debug_assert` above + let cnum = CrateNum::decode(self)?; + debug!( + "SpecializedDecoder::specialized_decode: loading source files from cnum {:?}", + cnum + ); + + // Decoding 'foreign' spans should be rare enough that it's + // not worth it to maintain a per-CrateNum cache for `last_source_file_index`. + // We just set it to 0, to ensure that we don't try to access something out + // of bounds for our initial 'guess' + self.last_source_file_index = 0; + + let foreign_data = self.cdata().cstore.get_crate_data(cnum); + foreign_data.imported_source_files(sess.source_map()) + }; + let source_file = { // Optimize for the case that most spans within a translated item // originate from the same source_file. @@ -412,16 +473,32 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { .binary_search_by_key(&lo, |source_file| source_file.original_start_pos) .unwrap_or_else(|index| index - 1); - self.last_source_file_index = index; + // Don't try to cache the index for foreign spans, + // as this would require a map from CrateNums to indices + if tag == TAG_VALID_SPAN_LOCAL { + self.last_source_file_index = index; + } &imported_source_files[index] } }; // Make sure our binary search above is correct. - debug_assert!(lo >= source_file.original_start_pos && lo <= source_file.original_end_pos); + debug_assert!( + lo >= source_file.original_start_pos && lo <= source_file.original_end_pos, + "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + lo, + source_file.original_start_pos, + source_file.original_end_pos + ); // Make sure we correctly filtered out invalid spans during encoding - debug_assert!(hi >= source_file.original_start_pos && hi <= source_file.original_end_pos); + debug_assert!( + hi >= source_file.original_start_pos && hi <= source_file.original_end_pos, + "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}", + hi, + source_file.original_start_pos, + source_file.original_end_pos + ); let lo = (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos; @@ -1425,14 +1502,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { let local_version = local_source_map.new_imported_source_file( name, name_was_remapped, - self.cnum.as_u32(), src_hash, name_hash, source_length, + self.cnum, lines, multibyte_chars, non_narrow_chars, normalized_pos, + start_pos, + end_pos, ); debug!( "CrateMetaData::imported_source_files alloc \ diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 90179520a62..98528018d9e 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1,6 +1,7 @@ use crate::rmeta::table::FixedSizeEncoding; use crate::rmeta::*; +use log::{debug, trace}; use rustc::hir::map::definitions::DefPathTable; use rustc::hir::map::Map; use rustc::middle::cstore::{EncodedMetadata, ForeignModule, LinkagePreference, NativeLibrary}; @@ -29,9 +30,7 @@ use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder}; use rustc_session::config::{self, CrateType}; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{self, FileName, SourceFile, Span}; - -use log::{debug, trace}; +use rustc_span::{self, ExternalSource, FileName, SourceFile, Span}; use std::hash::Hash; use std::num::NonZeroUsize; use std::path::Path; @@ -165,20 +164,56 @@ impl<'tcx> SpecializedEncoder for EncodeContext<'tcx> { return TAG_INVALID_SPAN.encode(self); } - // HACK(eddyb) there's no way to indicate which crate a Span is coming - // from right now, so decoding would fail to find the SourceFile if - // it's not local to the crate the Span is found in. - if self.source_file_cache.is_imported() { - return TAG_INVALID_SPAN.encode(self); - } + // There are two possible cases here: + // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the + // crate we are writing metadata for. When the metadata for *this* crate gets + // deserialized, the deserializer will need to know which crate it originally came + // from. We use `TAG_VALID_SPAN_FOREIGN` to indicate that a `CrateNum` should + // be deserialized after the rest of the span data, which tells the deserializer + // which crate contains the source map information. + // 2. This span comes from our own crate. No special hamdling is needed - we just + // write `TAG_VALID_SPAN_LOCAL` to let the deserializer know that it should use + // our own source map information. + let (tag, lo, hi) = if self.source_file_cache.is_imported() { + // To simplify deserialization, we 'rebase' this span onto the crate it originally came from + // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values + // are relative to the source map information for the 'foreign' crate whose CrateNum + // we write into the metadata. This allows `imported_source_files` to binary + // search through the 'foreign' crate's source map information, using the + // deserialized 'lo' and 'hi' values directly. + // + // All of this logic ensures that the final result of deserialization is a 'normal' + // Span that can be used without any additional trouble. + let external_start_pos = { + // Introduce a new scope so that we drop the 'lock()' temporary + match &*self.source_file_cache.external_src.lock() { + ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos, + src => panic!("Unexpected external source {:?}", src), + } + }; + let lo = (span.lo - self.source_file_cache.start_pos) + external_start_pos; + let hi = (span.hi - self.source_file_cache.start_pos) + external_start_pos; - TAG_VALID_SPAN.encode(self)?; - span.lo.encode(self)?; + (TAG_VALID_SPAN_FOREIGN, lo, hi) + } else { + (TAG_VALID_SPAN_LOCAL, span.lo, span.hi) + }; + + tag.encode(self)?; + lo.encode(self)?; // Encode length which is usually less than span.hi and profits more // from the variable-length integer encoding that we use. - let len = span.hi - span.lo; - len.encode(self) + let len = hi - lo; + len.encode(self)?; + + if tag == TAG_VALID_SPAN_FOREIGN { + // This needs to be two lines to avoid holding the `self.source_file_cache` + // while calling `cnum.encode(self)` + let cnum = self.source_file_cache.cnum; + cnum.encode(self)?; + } + Ok(()) // Don't encode the expansion context. } diff --git a/src/librustc_metadata/rmeta/mod.rs b/src/librustc_metadata/rmeta/mod.rs index defa306b6d6..05d834e5dee 100644 --- a/src/librustc_metadata/rmeta/mod.rs +++ b/src/librustc_metadata/rmeta/mod.rs @@ -405,5 +405,6 @@ struct GeneratorData<'tcx> { } // Tags used for encoding Spans: -const TAG_VALID_SPAN: u8 = 0; -const TAG_INVALID_SPAN: u8 = 1; +const TAG_VALID_SPAN_LOCAL: u8 = 0; +const TAG_VALID_SPAN_FOREIGN: u8 = 1; +const TAG_INVALID_SPAN: u8 = 2; diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index 1f6d10f4e8f..dbc180114f1 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -27,7 +27,7 @@ pub mod hygiene; use hygiene::Transparency; pub use hygiene::{DesugaringKind, ExpnData, ExpnId, ExpnKind, MacroKind, SyntaxContext}; pub mod def_id; -use def_id::DefId; +use def_id::{CrateNum, DefId, LOCAL_CRATE}; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; @@ -839,30 +839,42 @@ pub struct NormalizedPos { pub diff: u32, } -/// The state of the lazy external source loading mechanism of a `SourceFile`. -#[derive(PartialEq, Eq, Clone)] +#[derive(PartialEq, Eq, Clone, Debug)] pub enum ExternalSource { + /// No external source has to be loaded, since the `SourceFile` represents a local crate. + Unneeded, + Foreign { + kind: ExternalSourceKind, + /// This SourceFile's byte-offset within the source_map of its original crate + original_start_pos: BytePos, + /// The end of this SourceFile within the source_map of its original crate + original_end_pos: BytePos, + }, +} + +/// The state of the lazy external source loading mechanism of a `SourceFile`. +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum ExternalSourceKind { /// The external source has been loaded already. Present(String), /// No attempt has been made to load the external source. AbsentOk, /// A failed attempt has been made to load the external source. AbsentErr, - /// No external source has to be loaded, since the `SourceFile` represents a local crate. Unneeded, } impl ExternalSource { pub fn is_absent(&self) -> bool { - match *self { - ExternalSource::Present(_) => false, + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(_), .. } => false, _ => true, } } pub fn get_source(&self) -> Option<&str> { - match *self { - ExternalSource::Present(ref src) => Some(src), + match self { + ExternalSource::Foreign { kind: ExternalSourceKind::Present(ref src), .. } => Some(src), _ => None, } } @@ -883,8 +895,6 @@ pub struct SourceFile { /// The unmapped path of the file that the source came from. /// Set to `None` if the `SourceFile` was imported from an external crate. pub unmapped_path: Option, - /// Indicates which crate this `SourceFile` was imported from. - pub crate_of_origin: u32, /// The complete source code. pub src: Option>, /// The source code's hash. @@ -906,6 +916,8 @@ pub struct SourceFile { pub normalized_pos: Vec, /// A hash of the filename, used for speeding up hashing in incremental compilation. pub name_hash: u128, + /// Indicates which crate this `SourceFile` was imported from. + pub cnum: CrateNum, } impl Encodable for SourceFile { @@ -972,7 +984,8 @@ impl Encodable for SourceFile { s.emit_struct_field("multibyte_chars", 6, |s| self.multibyte_chars.encode(s))?; s.emit_struct_field("non_narrow_chars", 7, |s| self.non_narrow_chars.encode(s))?; s.emit_struct_field("name_hash", 8, |s| self.name_hash.encode(s))?; - s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s)) + s.emit_struct_field("normalized_pos", 9, |s| self.normalized_pos.encode(s))?; + s.emit_struct_field("cnum", 10, |s| self.cnum.encode(s)) }) } } @@ -1022,24 +1035,24 @@ impl Decodable for SourceFile { let name_hash: u128 = d.read_struct_field("name_hash", 8, |d| Decodable::decode(d))?; let normalized_pos: Vec = d.read_struct_field("normalized_pos", 9, |d| Decodable::decode(d))?; + let cnum: CrateNum = d.read_struct_field("cnum", 10, |d| Decodable::decode(d))?; Ok(SourceFile { name, name_was_remapped, unmapped_path: None, - // `crate_of_origin` has to be set by the importer. - // This value matches up with `rustc_hir::def_id::INVALID_CRATE`. - // That constant is not available here, unfortunately. - crate_of_origin: std::u32::MAX - 1, start_pos, end_pos, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + // Unused - the metadata decoder will construct + // a new SourceFile, filling in `external_src` properly + external_src: Lock::new(ExternalSource::Unneeded), lines, multibyte_chars, non_narrow_chars, normalized_pos, name_hash, + cnum, }) }) } @@ -1081,7 +1094,6 @@ impl SourceFile { name, name_was_remapped, unmapped_path: Some(unmapped_path), - crate_of_origin: 0, src: Some(Lrc::new(src)), src_hash, external_src: Lock::new(ExternalSource::Unneeded), @@ -1092,6 +1104,7 @@ impl SourceFile { non_narrow_chars, normalized_pos, name_hash, + cnum: LOCAL_CRATE, } } @@ -1109,21 +1122,27 @@ impl SourceFile { where F: FnOnce() -> Option, { - if *self.external_src.borrow() == ExternalSource::AbsentOk { + if matches!( + *self.external_src.borrow(), + ExternalSource::Foreign { kind: ExternalSourceKind::AbsentOk, .. } + ) { let src = get_src(); let mut external_src = self.external_src.borrow_mut(); // Check that no-one else have provided the source while we were getting it - if *external_src == ExternalSource::AbsentOk { + if let ExternalSource::Foreign { + kind: src_kind @ ExternalSourceKind::AbsentOk, .. + } = &mut *external_src + { if let Some(src) = src { let mut hasher: StableHasher = StableHasher::new(); hasher.write(src.as_bytes()); if hasher.finish::() == self.src_hash { - *external_src = ExternalSource::Present(src); + *src_kind = ExternalSourceKind::Present(src); return true; } } else { - *external_src = ExternalSource::AbsentErr; + *src_kind = ExternalSourceKind::AbsentErr; } false diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index 353f7b3f52b..7dd9e2f6316 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -296,14 +296,16 @@ impl SourceMap { &self, filename: FileName, name_was_remapped: bool, - crate_of_origin: u32, src_hash: u128, name_hash: u128, source_len: usize, + cnum: CrateNum, mut file_local_lines: Vec, mut file_local_multibyte_chars: Vec, mut file_local_non_narrow_chars: Vec, mut file_local_normalized_pos: Vec, + original_start_pos: BytePos, + original_end_pos: BytePos, ) -> Lrc { let start_pos = self .allocate_address_space(source_len) @@ -332,10 +334,13 @@ impl SourceMap { name: filename, name_was_remapped, unmapped_path: None, - crate_of_origin, src: None, src_hash, - external_src: Lock::new(ExternalSource::AbsentOk), + external_src: Lock::new(ExternalSource::Foreign { + kind: ExternalSourceKind::AbsentOk, + original_start_pos, + original_end_pos, + }), start_pos, end_pos, lines: file_local_lines, @@ -343,6 +348,7 @@ impl SourceMap { non_narrow_chars: file_local_non_narrow_chars, normalized_pos: file_local_normalized_pos, name_hash, + cnum, }); let mut files = self.files.borrow_mut(); diff --git a/src/test/ui/span/auxiliary/transitive_dep_three.rs b/src/test/ui/span/auxiliary/transitive_dep_three.rs new file mode 100644 index 00000000000..99b51625ac3 --- /dev/null +++ b/src/test/ui/span/auxiliary/transitive_dep_three.rs @@ -0,0 +1,9 @@ +#[macro_export] +macro_rules! define_parse_error { + () => { + #[macro_export] + macro_rules! parse_error { + () => { parse error } + } + } +} diff --git a/src/test/ui/span/auxiliary/transitive_dep_two.rs b/src/test/ui/span/auxiliary/transitive_dep_two.rs new file mode 100644 index 00000000000..5110c42765b --- /dev/null +++ b/src/test/ui/span/auxiliary/transitive_dep_two.rs @@ -0,0 +1,3 @@ +extern crate transitive_dep_three; + +transitive_dep_three::define_parse_error!(); diff --git a/src/test/ui/span/transitive-dep-span.rs b/src/test/ui/span/transitive-dep-span.rs new file mode 100644 index 00000000000..b445d389c56 --- /dev/null +++ b/src/test/ui/span/transitive-dep-span.rs @@ -0,0 +1,13 @@ +// Tests that we properly serialize/deserialize spans from transitive dependencies +// (e.g. imported SourceFiles) +// +// The order of these next lines is important, since we need +// transitive_dep_two.rs to be able to reference transitive_dep_three.rs +// +// aux-build: transitive_dep_three.rs +// aux-build: transitive_dep_two.rs +// compile-flags: -Z macro-backtrace + +extern crate transitive_dep_two; + +transitive_dep_two::parse_error!(); //~ ERROR expected one of diff --git a/src/test/ui/span/transitive-dep-span.stderr b/src/test/ui/span/transitive-dep-span.stderr new file mode 100644 index 00000000000..68d8911a435 --- /dev/null +++ b/src/test/ui/span/transitive-dep-span.stderr @@ -0,0 +1,19 @@ +error: expected one of `!` or `::`, found `error` + --> $DIR/auxiliary/transitive_dep_three.rs:6:27 + | +LL | / macro_rules! parse_error { +LL | | () => { parse error } + | | ^^^^^ expected one of `!` or `::` +LL | | } + | |_________- in this expansion of `transitive_dep_two::parse_error!` + | + ::: $DIR/transitive-dep-span.rs:13:1 + | +LL | transitive_dep_two::parse_error!(); + | ----------------------------------- + | | + | in this macro invocation + | in this macro invocation + +error: aborting due to previous error + From 898ff8d7238ed2f1986c2c83a5a436273b95c0dd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 19 Mar 2020 09:08:13 +0100 Subject: [PATCH 1241/1250] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index a7891c05f7f..0ff05c4cfe5 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit a7891c05f7fdb329f68c991abbb39dafc1f6b4a5 +Subproject commit 0ff05c4cfe534321b194bf3bedf028df92ef519c From e11dd4750301e55f6e0af1726001c7a7589a9cf9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 31 Oct 2019 15:32:07 +0200 Subject: [PATCH 1242/1250] rustc: use LocalDefId instead of DefIndex for query keys. --- src/librustc/dep_graph/dep_node.rs | 10 +++++----- src/librustc/query/mod.rs | 10 +++++----- src/librustc/ty/context.rs | 17 ++++++++++------- src/librustc/ty/query/keys.rs | 10 +++++----- src/librustc/ty/query/mod.rs | 4 ++-- .../borrow_check/universal_regions.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 17 +++-------------- 7 files changed, 31 insertions(+), 39 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index e3df9d5d04b..bee85c014e7 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -63,7 +63,7 @@ use crate::ty::subst::SubstsRef; use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::HirId; use rustc_span::symbol::Symbol; use std::fmt; @@ -413,19 +413,19 @@ impl<'tcx> DepNodeParams<'tcx> for DefId { } } -impl<'tcx> DepNodeParams<'tcx> for DefIndex { +impl<'tcx> DepNodeParams<'tcx> for LocalDefId { const CAN_RECONSTRUCT_QUERY_KEY: bool = true; fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { - tcx.hir().definitions().def_path_hash(*self).0 + self.to_def_id().to_fingerprint(tcx) } fn to_debug_str(&self, tcx: TyCtxt<'tcx>) -> String { - tcx.def_path_str(DefId::local(*self)) + self.to_def_id().to_debug_str(tcx) } fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.index) + dep_node.extract_def_id(tcx).map(|id| id.to_local()) } } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index ff3a82e5363..f47d22fdffb 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -11,7 +11,7 @@ use crate::ty::query::queries; use crate::ty::query::QueryDescription; use crate::ty::subst::SubstsRef; use crate::ty::{self, ParamEnvAnd, Ty, TyCtxt}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::symbol::Symbol; use std::borrow::Cow; @@ -791,7 +791,7 @@ rustc_queries! { query specializes(_: (DefId, DefId)) -> bool { desc { "computing whether impls specialize one another" } } - query in_scope_traits_map(_: DefIndex) + query in_scope_traits_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { eval_always desc { "traits in scope at a block" } @@ -948,15 +948,15 @@ rustc_queries! { query resolve_lifetimes(_: CrateNum) -> &'tcx ResolveLifetimes { desc { "resolving lifetimes" } } - query named_region_map(_: DefIndex) -> + query named_region_map(_: LocalDefId) -> Option<&'tcx FxHashMap> { desc { "looking up a named region" } } - query is_late_bound_map(_: DefIndex) -> + query is_late_bound_map(_: LocalDefId) -> Option<&'tcx FxHashSet> { desc { "testing if a region is late bound" } } - query object_lifetime_defaults_map(_: DefIndex) + query object_lifetime_defaults_map(_: LocalDefId) -> Option<&'tcx FxHashMap>> { desc { "looking up lifetime defaults for a region" } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d7a259cc870..25c442a8207 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -55,7 +55,7 @@ use rustc_data_structures::stable_hasher::{ use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::{HirId, Node, TraitCandidate}; use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet}; use rustc_index::vec::{Idx, IndexVec}; @@ -958,7 +958,7 @@ pub struct GlobalCtxt<'tcx> { /// Map indicating what traits are in scope for places where this /// is relevant; generated by resolve. - trait_map: FxHashMap>>, + trait_map: FxHashMap>>, /// Export map produced by name resolution. export_map: FxHashMap>>, @@ -1153,7 +1153,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { let hir_id = definitions.node_to_hir_id(k); - let map = trait_map.entry(hir_id.owner).or_default(); + let map = trait_map.entry(hir_id.owner_local_def_id()).or_default(); let v = v .into_iter() .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id))) @@ -2631,19 +2631,22 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec> { - self.in_scope_traits_map(id.owner).and_then(|map| map.get(&id.local_id)) + self.in_scope_traits_map(id.owner_local_def_id()).and_then(|map| map.get(&id.local_id)) } pub fn named_region(self, id: HirId) -> Option { - self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) + self.named_region_map(id.owner_local_def_id()) + .and_then(|map| map.get(&id.local_id).cloned()) } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner).map(|set| set.contains(&id.local_id)).unwrap_or(false) + self.is_late_bound_map(id.owner_local_def_id()) + .map(|set| set.contains(&id.local_id)) + .unwrap_or(false) } pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { - self.object_lifetime_defaults_map(id.owner) + self.object_lifetime_defaults_map(id.owner_local_def_id()) .and_then(|map| map.get(&id.local_id).map(|v| &**v)) } } diff --git a/src/librustc/ty/query/keys.rs b/src/librustc/ty/query/keys.rs index 09fb307a1ce..6073d3a545f 100644 --- a/src/librustc/ty/query/keys.rs +++ b/src/librustc/ty/query/keys.rs @@ -7,7 +7,7 @@ use crate::ty::fast_reject::SimplifiedType; use crate::ty::query::caches::DefaultCacheSelector; use crate::ty::subst::SubstsRef; use crate::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -84,14 +84,14 @@ impl Key for CrateNum { } } -impl Key for DefIndex { +impl Key for LocalDefId { type CacheSelector = DefaultCacheSelector; fn query_crate(&self) -> CrateNum { - LOCAL_CRATE + self.to_def_id().query_crate() } - fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { - DUMMY_SP + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.to_def_id().default_span(tcx) } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index e3859ed12a2..7ac8358c78a 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -44,7 +44,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId}; use rustc_hir::{Crate, HirIdSet, ItemLocalId, TraitCandidate}; use rustc_index::vec::IndexVec; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; @@ -147,7 +147,7 @@ rustc_query_append! { [define_queries!][<'tcx>] } /// /// When you implement a new query, it will likely have a corresponding new /// `DepKind`, and you'll have to support it here in `force_from_dep_node()`. As -/// a rule of thumb, if your query takes a `DefId` or `DefIndex` as sole parameter, +/// a rule of thumb, if your query takes a `DefId` or `LocalDefId` as sole parameter, /// then `force_from_dep_node()` should not fail for it. Otherwise, you can just /// add it to the "We don't have enough information to reconstruct..." group in /// the match below. diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 67b00e9ffdd..4cc2a2d45a6 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -774,7 +774,7 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.index) { + if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.to_local()) { for late_bound in late_bounds.iter() { let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound }; let name = tcx.hir().name(hir_id); diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 47d04964842..5e8b08167a4 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -17,7 +17,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::{GenericArg, GenericParam, LifetimeName, Node, ParamName, QPath}; use rustc_hir::{GenericParamKind, HirIdMap, HirIdSet, LifetimeParamKind}; @@ -280,25 +280,14 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { *providers = ty::query::Providers { resolve_lifetimes, - named_region_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id) - }, - - is_late_bound_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) - tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id) - }, - + named_region_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).defs.get(&id), + is_late_bound_map: |tcx, id| tcx.resolve_lifetimes(LOCAL_CRATE).late_bound.get(&id), object_lifetime_defaults_map: |tcx, id| { - let id = LocalDefId::from_def_id(DefId::local(id)); // (*) tcx.resolve_lifetimes(LOCAL_CRATE).object_lifetime_defaults.get(&id) }, ..*providers }; - - // (*) FIXME the query should be defined to take a LocalDefId } /// Computes the `ResolveLifetimes` map that contains data for the From e1762fdad12cd2577da0f3b0794c875648adde59 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 31 Oct 2019 16:27:44 +0200 Subject: [PATCH 1243/1250] rustc_typeck: remove dead impl for `DefIndex`. --- src/librustc_typeck/check/writeback.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 9d574ee50a4..4ca735d3909 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -9,7 +9,7 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdSet, DefIndex}; +use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; @@ -597,13 +597,6 @@ impl Locatable for Span { } } -impl Locatable for DefIndex { - fn to_span(&self, tcx: TyCtxt<'_>) -> Span { - let hir_id = tcx.hir().def_index_to_hir_id(*self); - tcx.hir().span(hir_id) - } -} - impl Locatable for hir::HirId { fn to_span(&self, tcx: TyCtxt<'_>) -> Span { tcx.hir().span(*self) From 55ed19fe1bba25251f110c0bf2bc6e42d50f3129 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 31 Oct 2019 20:48:13 +0200 Subject: [PATCH 1244/1250] rustc: make LocalDefId's index field public like DefId's is. --- src/librustc/hir/map/mod.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc_hir/hir_id.rs | 2 +- src/librustc_span/def_id.rs | 8 +++++--- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index ba1665fb530..636044069e4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -263,7 +263,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - self.tcx.definitions.def_index_to_hir_id(def_id.to_def_id().index) + self.tcx.definitions.def_index_to_hir_id(def_id.local_def_index) } pub fn def_kind(&self, hir_id: HirId) -> Option { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 25c442a8207..9f5197f3db6 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -735,7 +735,7 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { let var_owner_def_id = DefId { krate: local_id_root.krate, index: var_path.hir_id.owner }; let closure_def_id = - DefId { krate: local_id_root.krate, index: closure_expr_id.to_def_id().index }; + DefId { krate: local_id_root.krate, index: closure_expr_id.local_def_index }; ( hcx.def_path_hash(var_owner_def_id), var_path.hir_id.local_id, diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs index a11638a3bb2..c96807b528b 100644 --- a/src/librustc_hir/hir_id.rs +++ b/src/librustc_hir/hir_id.rs @@ -24,7 +24,7 @@ impl HirId { } pub fn owner_local_def_id(self) -> LocalDefId { - LocalDefId::from_def_id(DefId::local(self.owner)) + LocalDefId { local_def_index: self.owner } } } diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index af8d5ce09b5..413e747e033 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -211,18 +211,20 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); /// and a DefId from a different crate would signify a bug somewhere. This /// is when LocalDefId comes in handy. #[derive(Clone, Copy, PartialEq, Eq, Hash)] -pub struct LocalDefId(DefIndex); +pub struct LocalDefId { + pub local_def_index: DefIndex, +} impl LocalDefId { #[inline] pub fn from_def_id(def_id: DefId) -> LocalDefId { assert!(def_id.is_local()); - LocalDefId(def_id.index) + LocalDefId { local_def_index: def_id.index } } #[inline] pub fn to_def_id(self) -> DefId { - DefId { krate: LOCAL_CRATE, index: self.0 } + DefId { krate: LOCAL_CRATE, index: self.local_def_index } } } From 0c692797d702cb1ee3e5b19110c60baf54bc4e0e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Nov 2019 14:48:52 +0200 Subject: [PATCH 1245/1250] rustc: rename DefId::to_local to expect_local and use it instead of LocalDefId::from_def_id. --- src/librustc/dep_graph/dep_node.rs | 2 +- src/librustc/ty/query/on_disk_cache.rs | 2 +- src/librustc_metadata/rmeta/decoder.rs | 2 +- src/librustc_mir/borrow_check/universal_regions.rs | 2 +- src/librustc_mir/const_eval/fn_queries.rs | 4 ++-- src/librustc_mir_build/hair/cx/expr.rs | 5 ++--- src/librustc_span/def_id.rs | 11 +++-------- src/librustc_typeck/check/upvar.rs | 4 ++-- src/librustc_typeck/expr_use_visitor.rs | 2 +- src/librustc_typeck/mem_categorization.rs | 2 +- 10 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index bee85c014e7..dffbb373846 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -425,7 +425,7 @@ impl<'tcx> DepNodeParams<'tcx> for LocalDefId { } fn recover(tcx: TyCtxt<'tcx>, dep_node: &DepNode) -> Option { - dep_node.extract_def_id(tcx).map(|id| id.to_local()) + dep_node.extract_def_id(tcx).map(|id| id.expect_local()) } } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index 62c2bd801ee..e7e4d01ea51 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -657,7 +657,7 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - Ok(LocalDefId::from_def_id(DefId::decode(self)?)) + Ok(DefId::decode(self)?.expect_local()) } } diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs index 9cad086b4e8..2bf74fe272e 100644 --- a/src/librustc_metadata/rmeta/decoder.rs +++ b/src/librustc_metadata/rmeta/decoder.rs @@ -364,7 +364,7 @@ impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] fn specialized_decode(&mut self) -> Result { - self.specialized_decode().map(|i| LocalDefId::from_def_id(i)) + Ok(DefId::decode(self)?.expect_local()) } } diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 4cc2a2d45a6..06c01071644 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -774,7 +774,7 @@ fn for_each_late_bound_region_defined_on<'tcx>( fn_def_id: DefId, mut f: impl FnMut(ty::Region<'tcx>), ) { - if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.to_local()) { + if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { for late_bound in late_bounds.iter() { let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound }; let name = tcx.hir().name(hir_id); diff --git a/src/librustc_mir/const_eval/fn_queries.rs b/src/librustc_mir/const_eval/fn_queries.rs index 27efcd50841..470e4e7ed25 100644 --- a/src/librustc_mir/const_eval/fn_queries.rs +++ b/src/librustc_mir/const_eval/fn_queries.rs @@ -85,7 +85,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, hir_id: hir::HirId) -> bool { let parent_id = tcx.hir().get_parent_did(hir_id); if !parent_id.is_top_level_module() { - is_const_impl_raw(tcx, LocalDefId::from_def_id(parent_id)) + is_const_impl_raw(tcx, parent_id.expect_local()) } else { false } @@ -171,7 +171,7 @@ fn const_fn_is_allowed_fn_ptr(tcx: TyCtxt<'_>, def_id: DefId) -> bool { pub fn provide(providers: &mut Providers<'_>) { *providers = Providers { is_const_fn_raw, - is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, LocalDefId::from_def_id(def_id)), + is_const_impl_raw: |tcx, def_id| is_const_impl_raw(tcx, def_id.expect_local()), is_promotable_const_fn, const_fn_is_allowed_fn_ptr, ..*providers diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs index 9f04bc1dc76..02b596863ab 100644 --- a/src/librustc_mir_build/hair/cx/expr.rs +++ b/src/librustc_mir_build/hair/cx/expr.rs @@ -10,7 +10,6 @@ use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::{self, AdtKind, Ty}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::def_id::LocalDefId; use rustc_index::vec::Idx; use rustc_span::Span; @@ -812,7 +811,7 @@ fn convert_var<'tcx>( let closure_def_id = cx.body_owner; let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; let var_ty = cx.tables().node_type(var_hir_id); @@ -987,7 +986,7 @@ fn capture_upvar<'tcx>( ) -> ExprRef<'tcx> { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).to_local(), + closure_expr_id: cx.tcx.hir().local_def_id(closure_expr.hir_id).expect_local(), }; let upvar_capture = cx.tables().upvar_capture(upvar_id); let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 413e747e033..1aaec66722a 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -164,8 +164,9 @@ impl DefId { } #[inline] - pub fn to_local(self) -> LocalDefId { - LocalDefId::from_def_id(self) + pub fn expect_local(self) -> LocalDefId { + assert!(self.is_local()); + LocalDefId { local_def_index: self.index } } pub fn is_top_level_module(self) -> bool { @@ -216,12 +217,6 @@ pub struct LocalDefId { } impl LocalDefId { - #[inline] - pub fn from_def_id(def_id: DefId) -> LocalDefId { - assert!(def_id.is_local()); - LocalDefId { local_def_index: def_id.index } - } - #[inline] pub fn to_def_id(self) -> DefId { DefId { krate: LOCAL_CRATE, index: self.local_def_index } diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs index 44b960ad22b..1b5f151870c 100644 --- a/src/librustc_typeck/check/upvar.rs +++ b/src/librustc_typeck/check/upvar.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (&var_hir_id, _) in upvars.iter() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; debug!("seed upvar_id {:?}", upvar_id); // Adding the upvar Id to the list of Upvars, which will be added @@ -228,7 +228,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let upvar_ty = self.node_ty(var_hir_id); let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_hir_id }, - closure_expr_id: LocalDefId::from_def_id(closure_def_id), + closure_expr_id: closure_def_id.expect_local(), }; let capture = self.tables.borrow().upvar_capture(upvar_id); diff --git a/src/librustc_typeck/expr_use_visitor.rs b/src/librustc_typeck/expr_use_visitor.rs index 6666b169994..a45d8ce6823 100644 --- a/src/librustc_typeck/expr_use_visitor.rs +++ b/src/librustc_typeck/expr_use_visitor.rs @@ -519,7 +519,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { for &var_id in upvars.keys() { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, - closure_expr_id: closure_def_id.to_local(), + closure_expr_id: closure_def_id.expect_local(), }; let upvar_capture = self.mc.tables.upvar_capture(upvar_id); let captured_place = return_if_err!(self.cat_captured_var( diff --git a/src/librustc_typeck/mem_categorization.rs b/src/librustc_typeck/mem_categorization.rs index 4350b3dda97..7d8bf71cf97 100644 --- a/src/librustc_typeck/mem_categorization.rs +++ b/src/librustc_typeck/mem_categorization.rs @@ -470,7 +470,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { let upvar_id = ty::UpvarId { var_path: ty::UpvarPath { hir_id: var_id }, - closure_expr_id: closure_expr_def_id.to_local(), + closure_expr_id: closure_expr_def_id.expect_local(), }; let var_ty = self.node_ty(var_id)?; From 42b2adfab0e77c4662021badcf765a445681a12e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Nov 2019 20:48:08 +0200 Subject: [PATCH 1246/1250] rustc: introduce DefId::as_local(self) -> Option and use it. --- src/librustc/hir/map/hir_id_validator.rs | 16 +++++++++++----- src/librustc/hir/map/mod.rs | 12 +++++------- src/librustc/ich/hcx.rs | 4 ++-- src/librustc/ty/context.rs | 12 ++++++++---- src/librustc_mir/borrow_check/nll.rs | 2 +- src/librustc_passes/entry.rs | 2 +- src/librustc_span/def_id.rs | 8 ++++++-- src/librustc_typeck/check/mod.rs | 5 ++--- 8 files changed, 36 insertions(+), 25 deletions(-) diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index 796f4895472..cc3e11d9af9 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -3,7 +3,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefIndex, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId}; @@ -113,14 +113,18 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { missing_items.push(format!( "[local_id: {}, owner: {}]", local_id, - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate() + self.hir_map + .def_path(LocalDefId { local_def_index: owner_def_index }) + .to_string_no_crate() )); } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map.def_path(DefId::local(owner_def_index)).to_string_no_crate(), + self.hir_map + .def_path(LocalDefId { local_def_index: owner_def_index }) + .to_string_no_crate(), max, missing_items, self.hir_ids_seen @@ -159,8 +163,10 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(DefId::local(hir_id.owner)).to_string_no_crate(), - self.hir_map.def_path(DefId::local(owner)).to_string_no_crate() + self.hir_map.def_path(hir_id.owner_local_def_id()).to_string_no_crate(), + self.hir_map + .def_path(LocalDefId { local_def_index: owner }) + .to_string_no_crate() ) }); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 636044069e4..dbe23edd8a4 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -188,18 +188,16 @@ impl<'hir> Map<'hir> { &self.tcx.definitions } - pub fn def_key(&self, def_id: DefId) -> DefKey { - assert!(def_id.is_local()); - self.tcx.definitions.def_key(def_id.index) + pub fn def_key(&self, def_id: LocalDefId) -> DefKey { + self.tcx.definitions.def_key(def_id.local_def_index) } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { - self.opt_local_def_id(id).map(|def_id| self.def_path(def_id)) + self.opt_local_def_id(id).map(|def_id| self.def_path(def_id.expect_local())) } - pub fn def_path(&self, def_id: DefId) -> DefPath { - assert!(def_id.is_local()); - self.tcx.definitions.def_path(def_id.index) + pub fn def_path(&self, def_id: LocalDefId) -> DefPath { + self.tcx.definitions.def_path(def_id.local_def_index) } #[inline] diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 8fd86b3232d..09654478791 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -123,8 +123,8 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { - if def_id.is_local() { - self.definitions.def_path_hash(def_id.index) + if let Some(def_id) = def_id.as_local() { + self.definitions.def_path_hash(def_id.local_def_index) } else { self.cstore.def_path_hash(def_id) } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 9f5197f3db6..78e7d1f3bd8 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1261,7 +1261,7 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn def_key(self, id: DefId) -> hir_map::DefKey { - if id.is_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) } + if let Some(id) = id.as_local() { self.hir().def_key(id) } else { self.cstore.def_key(id) } } /// Converts a `DefId` into its fully expanded `DefPath` (every @@ -1270,7 +1270,11 @@ impl<'tcx> TyCtxt<'tcx> { /// Note that if `id` is not local to this crate, the result will /// be a non-local `DefPath`. pub fn def_path(self, id: DefId) -> hir_map::DefPath { - if id.is_local() { self.hir().def_path(id) } else { self.cstore.def_path(id) } + if let Some(id) = id.as_local() { + self.hir().def_path(id) + } else { + self.cstore.def_path(id) + } } /// Returns whether or not the crate with CrateNum 'cnum' @@ -1281,8 +1285,8 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { - if def_id.is_local() { - self.definitions.def_path_hash(def_id.index) + if let Some(def_id) = def_id.as_local() { + self.definitions.def_path_hash(def_id.local_def_index) } else { self.cstore.def_path_hash(def_id) } diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index ba1b322524e..077ed49ed2c 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -272,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Dump facts if requested. let polonius_output = all_facts.and_then(|all_facts| { if infcx.tcx.sess.opts.debugging_opts.nll_facts { - let def_path = infcx.tcx.hir().def_path(def_id); + let def_path = infcx.tcx.def_path(def_id); let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate()); all_facts.write_to_dir(dir_path, location_table).unwrap(); diff --git a/src/librustc_passes/entry.rs b/src/librustc_passes/entry.rs index 598d6bb3c48..7e0d0bfe9ab 100644 --- a/src/librustc_passes/entry.rs +++ b/src/librustc_passes/entry.rs @@ -34,7 +34,7 @@ struct EntryContext<'a, 'tcx> { impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { fn visit_item(&mut self, item: &'tcx Item<'tcx>) { let def_id = self.map.local_def_id(item.hir_id); - let def_key = self.map.def_key(def_id); + let def_key = self.map.def_key(def_id.expect_local()); let at_root = def_key.parent == Some(CRATE_DEF_INDEX); find_item(item, self, at_root); } diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index 1aaec66722a..f8570b98162 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -163,10 +163,14 @@ impl DefId { self.krate == LOCAL_CRATE } + #[inline] + pub fn as_local(self) -> Option { + if self.is_local() { Some(LocalDefId { local_def_index: self.index }) } else { None } + } + #[inline] pub fn expect_local(self) -> LocalDefId { - assert!(self.is_local()); - LocalDefId { local_def_index: self.index } + self.as_local().unwrap_or_else(|| panic!("DefId::expect_local: `{:?}` isn't local", self)) } pub fn is_top_level_module(self) -> bool { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bfb0d25dea2..e6d492110fb 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -638,9 +638,8 @@ pub struct InheritedBuilder<'tcx> { impl Inherited<'_, 'tcx> { pub fn build(tcx: TyCtxt<'tcx>, def_id: DefId) -> InheritedBuilder<'tcx> { - let hir_id_root = if def_id.is_local() { - let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - DefId::local(hir_id.owner) + let hir_id_root = if let Some(def_id) = def_id.as_local() { + tcx.hir().local_def_id_to_hir_id(def_id).owner_def_id() } else { def_id }; From 6130b9959c418f48ccc12beab71a5c0e84659b4b Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Nov 2019 21:29:40 +0200 Subject: [PATCH 1247/1250] rustc: use LocalDefId instead of DefIndex in hir::lowering. --- src/librustc_ast_lowering/item.rs | 23 ++++--- src/librustc_ast_lowering/lib.rs | 106 ++++++++++++++++-------------- 2 files changed, 72 insertions(+), 57 deletions(-) diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs index aab6aa7c35b..94ae2a0973a 100644 --- a/src/librustc_ast_lowering/item.rs +++ b/src/librustc_ast_lowering/item.rs @@ -11,7 +11,7 @@ use rustc_ast::visit::{self, AssocCtxt, Visitor}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::LocalDefId; use rustc_span::source_map::{respan, DesugaringKind}; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -269,7 +269,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::Const(ty, body_id) } ItemKind::Fn(_, FnSig { ref decl, header }, ref generics, ref body) => { - let fn_def_id = self.resolver.definitions().local_def_id(id); + let fn_def_id = self.resolver.definitions().local_def_id(id).expect_local(); self.with_new_scopes(|this| { this.current_item = Some(ident.span); @@ -287,7 +287,12 @@ impl<'hir> LoweringContext<'_, 'hir> { AnonymousLifetimeMode::PassThrough, |this, idty| { let ret_id = asyncness.opt_return_id(); - this.lower_fn_decl(&decl, Some((fn_def_id, idty)), true, ret_id) + this.lower_fn_decl( + &decl, + Some((fn_def_id.to_def_id(), idty)), + true, + ret_id, + ) }, ); let sig = hir::FnSig { decl, header: this.lower_fn_header(header) }; @@ -351,7 +356,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self_ty: ref ty, items: ref impl_items, } => { - let def_id = self.resolver.definitions().local_def_id(id); + let def_id = self.resolver.definitions().local_def_id(id).expect_local(); // Lower the "impl header" first. This ordering is important // for in-band lifetimes! Consider `'a` here: @@ -648,7 +653,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_foreign_item(&mut self, i: &ForeignItem) -> hir::ForeignItem<'hir> { - let def_id = self.resolver.definitions().local_def_id(i.id); + let def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); hir::ForeignItem { hir_id: self.lower_node_id(i.id), ident: i.ident, @@ -749,7 +754,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_item(&mut self, i: &AssocItem) -> hir::TraitItem<'hir> { - let trait_item_def_id = self.resolver.definitions().local_def_id(i.id); + let trait_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); let (generics, kind) = match i.kind { AssocItemKind::Const(_, ref ty, ref default) => { @@ -814,7 +819,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_impl_item(&mut self, i: &AssocItem) -> hir::ImplItem<'hir> { - let impl_item_def_id = self.resolver.definitions().local_def_id(i.id); + let impl_item_def_id = self.resolver.definitions().local_def_id(i.id).expect_local(); let (generics, kind) = match &i.kind { AssocItemKind::Const(_, ty, expr) => { @@ -1211,7 +1216,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, sig: &FnSig, - fn_def_id: DefId, + fn_def_id: LocalDefId, impl_trait_return_allow: bool, is_async: Option, ) -> (hir::Generics<'hir>, hir::FnSig<'hir>) { @@ -1223,7 +1228,7 @@ impl<'hir> LoweringContext<'_, 'hir> { |this, idty| { this.lower_fn_decl( &sig.decl, - Some((fn_def_id, idty)), + Some((fn_def_id.to_def_id(), idty)), impl_trait_return_allow, is_async, ) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 43a6b7ac04c..3056612ee29 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -53,7 +53,7 @@ use rustc_data_structures::sync::Lrc; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, PartialRes, PerNS, Res}; -use rustc_hir::def_id::{DefId, DefIdMap, DefIndex, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::{ConstArg, GenericArg, ParamName}; use rustc_index::vec::IndexVec; @@ -160,7 +160,7 @@ struct LoweringContext<'a, 'hir: 'a> { type_def_lifetime_params: DefIdMap, - current_hir_id_owner: Vec<(DefIndex, u32)>, + current_hir_id_owner: Vec<(LocalDefId, u32)>, item_local_id_counters: NodeMap, node_id_to_hir_id: IndexVec, @@ -290,7 +290,7 @@ pub fn lower_crate<'a, 'hir>( anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough, type_def_lifetime_params: Default::default(), current_module: hir::CRATE_HIR_ID, - current_hir_id_owner: vec![(CRATE_DEF_INDEX, 0)], + current_hir_id_owner: vec![(LocalDefId { local_def_index: CRATE_DEF_INDEX }, 0)], item_local_id_counters: Default::default(), node_id_to_hir_id: IndexVec::new(), generator_kind: None, @@ -407,12 +407,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } impl MiscCollector<'_, '_, '_> { - fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: DefIndex) { + fn allocate_use_tree_hir_id_counters(&mut self, tree: &UseTree, owner: LocalDefId) { match tree.kind { UseTreeKind::Simple(_, id1, id2) => { for &id in &[id1, id2] { self.lctx.resolver.definitions().create_def_with_parent( - owner, + owner.local_def_index, id, DefPathData::Misc, ExpnId::root(), @@ -425,7 +425,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { UseTreeKind::Nested(ref trees) => { for &(ref use_tree, id) in trees { let hir_id = self.lctx.allocate_hir_id_counter(id); - self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); + self.allocate_use_tree_hir_id_counters( + use_tree, + hir_id.owner_local_def_id(), + ); } } } @@ -463,7 +466,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { | ItemKind::Enum(_, ref generics) | ItemKind::TyAlias(_, ref generics, ..) | ItemKind::Trait(_, _, ref generics, ..) => { - let def_id = self.lctx.resolver.definitions().local_def_id(item.id); + let def_id = + self.lctx.resolver.definitions().local_def_id(item.id).expect_local(); let count = generics .params .iter() @@ -472,10 +476,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { _ => false, }) .count(); - self.lctx.type_def_lifetime_params.insert(def_id, count); + self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count); } ItemKind::Use(ref use_tree) => { - self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); + self.allocate_use_tree_hir_id_counters( + use_tree, + hir_id.owner_local_def_id(), + ); } _ => {} } @@ -598,12 +605,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .item_local_id_counters .insert(owner, HIR_ID_COUNTER_LOCKED) .unwrap_or_else(|| panic!("no `item_local_id_counters` entry for {:?}", owner)); - let def_index = self.resolver.definitions().opt_def_index(owner).unwrap(); - self.current_hir_id_owner.push((def_index, counter)); + let def_id = self.resolver.definitions().local_def_id(owner).expect_local(); + self.current_hir_id_owner.push((def_id, counter)); let ret = f(self); - let (new_def_index, new_counter) = self.current_hir_id_owner.pop().unwrap(); + let (new_def_id, new_counter) = self.current_hir_id_owner.pop().unwrap(); - debug_assert!(def_index == new_def_index); + debug_assert!(def_id == new_def_id); debug_assert!(new_counter >= counter); let prev = self.item_local_id_counters.insert(owner, new_counter).unwrap(); @@ -619,11 +626,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { self.lower_node_id_generic(ast_node_id, |this| { - let &mut (def_index, ref mut local_id_counter) = + let &mut (def_id, ref mut local_id_counter) = this.current_hir_id_owner.last_mut().unwrap(); let local_id = *local_id_counter; *local_id_counter += 1; - hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) } + hir::HirId { + owner: def_id.local_def_index, + local_id: hir::ItemLocalId::from_u32(local_id), + } }) } @@ -724,7 +734,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// parameter while `f` is running (and restored afterwards). fn collect_in_band_defs( &mut self, - parent_id: DefId, + parent_def_id: LocalDefId, anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self) -> (Vec>, T), ) -> (Vec>, T) { @@ -744,7 +754,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let params = lifetimes_to_define .into_iter() - .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_id.index)) + .map(|(span, hir_name)| self.lifetime_to_generic_param(span, hir_name, parent_def_id)) .chain(in_band_ty_params.into_iter()) .collect(); @@ -756,7 +766,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { &mut self, span: Span, hir_name: ParamName, - parent_index: DefIndex, + parent_def_id: LocalDefId, ) -> hir::GenericParam<'hir> { let node_id = self.resolver.next_node_id(); @@ -771,7 +781,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band lifetime def. self.resolver.definitions().create_def_with_parent( - parent_index, + parent_def_id.local_def_index, node_id, DefPathData::LifetimeNs(str_name), ExpnId::root(), @@ -860,13 +870,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn add_in_band_defs( &mut self, generics: &Generics, - parent_id: DefId, + parent_def_id: LocalDefId, anonymous_lifetime_mode: AnonymousLifetimeMode, f: impl FnOnce(&mut Self, &mut Vec>) -> T, ) -> (hir::Generics<'hir>, T) { let (in_band_defs, (mut lowered_generics, res)) = self.with_in_scope_lifetime_defs(&generics.params, |this| { - this.collect_in_band_defs(parent_id, anonymous_lifetime_mode, |this| { + this.collect_in_band_defs(parent_def_id, anonymous_lifetime_mode, |this| { let mut params = Vec::new(); // Note: it is necessary to lower generics *before* calling `f`. // When lowering `async fn`, there's a final step when lowering @@ -1048,9 +1058,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // constructing the HIR for `impl bounds...` and then lowering that. let impl_trait_node_id = self.resolver.next_node_id(); - let parent_def_index = self.current_hir_id_owner.last().unwrap().0; + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; self.resolver.definitions().create_def_with_parent( - parent_def_index, + parent_def_id.local_def_index, impl_trait_node_id, DefPathData::ImplTrait, ExpnId::root(), @@ -1111,12 +1121,12 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Construct a AnonConst where the expr is the "ty"'s path. - let parent_def_index = self.current_hir_id_owner.last().unwrap().0; + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; let node_id = self.resolver.next_node_id(); // Add a definition for the in-band const def. self.resolver.definitions().create_def_with_parent( - parent_def_index, + parent_def_id.local_def_index, node_id, DefPathData::AnonConst, ExpnId::root(), @@ -1278,8 +1288,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } ImplTraitContext::Universal(in_band_ty_params) => { // Add a definition for the in-band `Param`. - let def_index = - self.resolver.definitions().opt_def_index(def_node_id).unwrap(); + let def_id = + self.resolver.definitions().local_def_id(def_node_id).expect_local(); let hir_bounds = self.lower_param_bounds( bounds, @@ -1304,7 +1314,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None, self.arena.alloc(hir::Path { span, - res: Res::Def(DefKind::TyParam, DefId::local(def_index)), + res: Res::Def(DefKind::TyParam, def_id.to_def_id()), segments: arena_vec![self; hir::PathSegment::from_ident(ident)], }), )) @@ -1367,18 +1377,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // frequently opened issues show. let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::OpaqueTy, span, None); - let opaque_ty_def_index = - self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap(); + let opaque_ty_def_id = + self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local(); self.allocate_hir_id_counter(opaque_ty_node_id); let hir_bounds = self.with_hir_id_owner(opaque_ty_node_id, lower_bounds); - let (lifetimes, lifetime_defs) = self.lifetimes_from_impl_trait_bounds( - opaque_ty_node_id, - opaque_ty_def_index, - &hir_bounds, - ); + let (lifetimes, lifetime_defs) = + self.lifetimes_from_impl_trait_bounds(opaque_ty_node_id, opaque_ty_def_id, &hir_bounds); debug!("lower_opaque_impl_trait: lifetimes={:#?}", lifetimes,); @@ -1396,7 +1403,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin, }; - trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_index); + trace!("lower_opaque_impl_trait: {:#?}", opaque_ty_def_id); let opaque_ty_id = lctx.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span); @@ -1437,14 +1444,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { fn lifetimes_from_impl_trait_bounds( &mut self, opaque_ty_id: NodeId, - parent_index: DefIndex, + parent_def_id: LocalDefId, bounds: hir::GenericBounds<'hir>, ) -> (&'hir [hir::GenericArg<'hir>], &'hir [hir::GenericParam<'hir>]) { debug!( "lifetimes_from_impl_trait_bounds(opaque_ty_id={:?}, \ - parent_index={:?}, \ + parent_def_id={:?}, \ bounds={:#?})", - opaque_ty_id, parent_index, bounds, + opaque_ty_id, parent_def_id, bounds, ); // This visitor walks over `impl Trait` bounds and creates defs for all lifetimes that @@ -1452,7 +1459,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // E.g., `'a`, `'b`, but not `'c` in `impl for<'c> SomeTrait<'a, 'b, 'c>`. struct ImplTraitLifetimeCollector<'r, 'a, 'hir> { context: &'r mut LoweringContext<'a, 'hir>, - parent: DefIndex, + parent: LocalDefId, opaque_ty_id: NodeId, collect_elided_lifetimes: bool, currently_bound_lifetimes: Vec, @@ -1557,7 +1564,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_id = self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id); self.context.resolver.definitions().create_def_with_parent( - self.parent, + self.parent.local_def_index, def_node_id, DefPathData::LifetimeNs(name.ident().name), ExpnId::root(), @@ -1590,7 +1597,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut lifetime_collector = ImplTraitLifetimeCollector { context: self, - parent: parent_index, + parent: parent_def_id, opaque_ty_id, collect_elided_lifetimes: true, currently_bound_lifetimes: Vec::new(), @@ -1620,12 +1627,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { visitor.visit_ty(ty); } } - let parent_def_id = DefId::local(self.current_hir_id_owner.last().unwrap().0); + let parent_def_id = self.current_hir_id_owner.last().unwrap().0; let ty = l.ty.as_ref().map(|t| { self.lower_ty( t, if self.sess.features_untracked().impl_trait_in_bindings { - ImplTraitContext::OpaqueTy(Some(parent_def_id), hir::OpaqueTyOrigin::Misc) + ImplTraitContext::OpaqueTy( + Some(parent_def_id.to_def_id()), + hir::OpaqueTyOrigin::Misc, + ) } else { ImplTraitContext::Disallowed(ImplTraitPosition::Binding) }, @@ -1797,8 +1807,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let opaque_ty_span = self.mark_span_with_reason(DesugaringKind::Async, span, None); - let opaque_ty_def_index = - self.resolver.definitions().opt_def_index(opaque_ty_node_id).unwrap(); + let opaque_ty_def_id = + self.resolver.definitions().local_def_id(opaque_ty_node_id).expect_local(); self.allocate_hir_id_counter(opaque_ty_node_id); @@ -1886,7 +1896,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let generic_params = this.arena.alloc_from_iter(lifetime_params.iter().map(|(span, hir_name)| { - this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_index) + this.lifetime_to_generic_param(*span, *hir_name, opaque_ty_def_id) })); let opaque_ty_item = hir::OpaqueTy { @@ -1900,7 +1910,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { origin: hir::OpaqueTyOrigin::AsyncFn, }; - trace!("exist ty from async fn def index: {:#?}", opaque_ty_def_index); + trace!("exist ty from async fn def id: {:#?}", opaque_ty_def_id); let opaque_ty_id = this.generate_opaque_type(opaque_ty_node_id, opaque_ty_item, span, opaque_ty_span); From f3ec0698865d70571f5308f912c63dbc5ad2a9ed Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 18 Mar 2020 20:27:59 +0200 Subject: [PATCH 1248/1250] rustc: use LocalDefId instead of DefIndex in HirId. --- src/librustc/dep_graph/dep_node.rs | 2 +- src/librustc/dep_graph/graph.rs | 2 +- src/librustc/hir/map/collector.rs | 31 ++++++------ src/librustc/hir/map/hir_id_validator.rs | 35 ++++++-------- src/librustc/hir/map/mod.rs | 14 ++---- src/librustc/hir/mod.rs | 16 +++---- src/librustc/ich/impls_hir.rs | 4 +- src/librustc/middle/region.rs | 3 +- src/librustc/query/mod.rs | 20 ++++---- src/librustc/ty/context.rs | 23 +++++---- src/librustc/ty/mod.rs | 6 ++- src/librustc/ty/query/on_disk_cache.rs | 35 -------------- src/librustc_ast_lowering/lib.rs | 34 ++++++-------- src/librustc_hir/hir_id.rs | 47 ++++--------------- src/librustc_hir/stable_hash_impls.rs | 2 +- src/librustc_lint/internal.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/rmeta/encoder.rs | 2 +- .../borrow_check/universal_regions.rs | 2 +- .../hair/pattern/check_match.rs | 2 +- src/librustc_passes/liveness.rs | 4 +- src/librustc_passes/reachable.rs | 2 +- src/librustc_privacy/lib.rs | 2 +- src/librustc_resolve/late/lifetimes.rs | 6 +-- src/librustc_span/def_id.rs | 13 ++++- .../traits/error_reporting/suggestions.rs | 2 +- .../traits/object_safety.rs | 2 +- src/librustc_typeck/check/expr.rs | 2 +- src/librustc_typeck/check/method/suggest.rs | 4 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/writeback.rs | 14 +++--- .../passes/collect_intra_doc_links.rs | 2 +- 32 files changed, 139 insertions(+), 202 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index dffbb373846..b32fa2cda80 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -477,7 +477,7 @@ impl<'tcx> DepNodeParams<'tcx> for HirId { fn to_fingerprint(&self, tcx: TyCtxt<'_>) -> Fingerprint { let HirId { owner, local_id } = *self; - let def_path_hash = tcx.def_path_hash(DefId::local(owner)); + let def_path_hash = tcx.def_path_hash(owner.to_def_id()); let local_id = Fingerprint::from_smaller_hash(local_id.as_u32().into()); def_path_hash.0.combine(local_id) diff --git a/src/librustc/dep_graph/graph.rs b/src/librustc/dep_graph/graph.rs index 97114b9e313..f60d20b8cb7 100644 --- a/src/librustc/dep_graph/graph.rs +++ b/src/librustc/dep_graph/graph.rs @@ -902,7 +902,7 @@ impl DepGraph { fn def_id_corresponds_to_hir_dep_node(tcx: TyCtxt<'_>, def_id: DefId) -> bool { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); - def_id.index == hir_id.owner + def_id.index == hir_id.owner.local_def_index } /// A "work product" is an intermediate result that we save into the diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 8b276d0a762..286de7703ab 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::svh::Svh; use rustc_hir as hir; use rustc_hir::def_id::CRATE_DEF_INDEX; -use rustc_hir::def_id::{DefIndex, LOCAL_CRATE}; +use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::*; use rustc_index::vec::{Idx, IndexVec}; @@ -30,12 +30,12 @@ pub(super) struct NodeCollector<'a, 'hir> { /// Source map source_map: &'a SourceMap, - map: IndexVec>, + map: IndexVec>, /// The parent of this node parent_node: hir::HirId, - current_dep_node_owner: DefIndex, + current_dep_node_owner: LocalDefId, definitions: &'a definitions::Definitions, @@ -126,7 +126,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { krate, source_map: sess.source_map(), parent_node: hir::CRATE_HIR_ID, - current_dep_node_owner: CRATE_DEF_INDEX, + current_dep_node_owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, definitions, hcx, hir_body_nodes, @@ -148,7 +148,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { crate_disambiguator: CrateDisambiguator, cstore: &dyn CrateStore, commandline_args_hash: u64, - ) -> (IndexVec>, Svh) { + ) -> (IndexVec>, Svh) { // Insert bodies into the map for (id, body) in self.krate.bodies.iter() { let bodies = &mut self.map[id.hir_id.owner].with_bodies.as_mut().unwrap().bodies; @@ -261,9 +261,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", self.source_map.span_to_string(span), node_str, - self.definitions.def_path(self.current_dep_node_owner).to_string_no_crate(), + self.definitions + .def_path(self.current_dep_node_owner.local_def_index) + .to_string_no_crate(), self.current_dep_node_owner, - self.definitions.def_path(hir_id.owner).to_string_no_crate(), + self.definitions.def_path(hir_id.owner.local_def_index).to_string_no_crate(), hir_id.owner, forgot_str, ) @@ -285,13 +287,13 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { F: FnOnce(&mut Self, Fingerprint), >( &mut self, - dep_node_owner: DefIndex, + dep_node_owner: LocalDefId, item_like: &T, f: F, ) { let prev_owner = self.current_dep_node_owner; - let def_path_hash = self.definitions.def_path_hash(dep_node_owner); + let def_path_hash = self.definitions.def_path_hash(dep_node_owner.local_def_index); let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); @@ -340,7 +342,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item<'hir>) { debug!("visit_item: {:?}", i); debug_assert_eq!( - i.hir_id.owner, + i.hir_id.owner.local_def_index, self.definitions.opt_def_index(self.definitions.hir_to_node_id(i.hir_id)).unwrap() ); self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| { @@ -372,7 +374,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!( - ti.hir_id.owner, + ti.hir_id.owner.local_def_index, self.definitions.opt_def_index(self.definitions.hir_to_node_id(ti.hir_id)).unwrap() ); self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| { @@ -386,7 +388,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!( - ii.hir_id.owner, + ii.hir_id.owner.local_def_index, self.definitions.opt_def_index(self.definitions.hir_to_node_id(ii.hir_id)).unwrap() ); self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| { @@ -506,10 +508,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { } fn visit_macro_def(&mut self, macro_def: &'hir MacroDef<'hir>) { - let node_id = self.definitions.hir_to_node_id(macro_def.hir_id); - let def_index = self.definitions.opt_def_index(node_id).unwrap(); - - self.with_dep_node_owner(def_index, macro_def, |this, hash| { + self.with_dep_node_owner(macro_def.hir_id.owner, macro_def, |this, hash| { this.insert_with_hash( macro_def.span, macro_def.hir_id, diff --git a/src/librustc/hir/map/hir_id_validator.rs b/src/librustc/hir/map/hir_id_validator.rs index cc3e11d9af9..e3386a2a910 100644 --- a/src/librustc/hir/map/hir_id_validator.rs +++ b/src/librustc/hir/map/hir_id_validator.rs @@ -3,7 +3,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator}; use rustc_hir as hir; -use rustc_hir::def_id::{DefIndex, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{LocalDefId, CRATE_DEF_INDEX}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::{HirId, ItemLocalId}; @@ -32,7 +32,7 @@ pub fn check_crate(tcx: TyCtxt<'_>) { struct HirIdValidator<'a, 'hir> { hir_map: Map<'hir>, - owner_def_index: Option, + owner: Option, hir_ids_seen: FxHashSet, errors: &'a Lock>, } @@ -46,7 +46,7 @@ impl<'a, 'hir> OuterVisitor<'a, 'hir> { fn new_inner_visitor(&self, hir_map: Map<'hir>) -> HirIdValidator<'a, 'hir> { HirIdValidator { hir_map, - owner_def_index: None, + owner: None, hir_ids_seen: Default::default(), errors: self.errors, } @@ -78,12 +78,12 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { } fn check)>(&mut self, hir_id: HirId, walk: F) { - assert!(self.owner_def_index.is_none()); - let owner_def_index = self.hir_map.local_def_id(hir_id).index; - self.owner_def_index = Some(owner_def_index); + assert!(self.owner.is_none()); + let owner = self.hir_map.local_def_id(hir_id).expect_local(); + self.owner = Some(owner); walk(self); - if owner_def_index == CRATE_DEF_INDEX { + if owner.local_def_index == CRATE_DEF_INDEX { return; } @@ -105,31 +105,26 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> { let mut missing_items = Vec::with_capacity(missing.len()); for local_id in missing { - let hir_id = - HirId { owner: owner_def_index, local_id: ItemLocalId::from_u32(local_id) }; + let hir_id = HirId { owner, local_id: ItemLocalId::from_u32(local_id) }; trace!("missing hir id {:#?}", hir_id); missing_items.push(format!( "[local_id: {}, owner: {}]", local_id, - self.hir_map - .def_path(LocalDefId { local_def_index: owner_def_index }) - .to_string_no_crate() + self.hir_map.def_path(owner).to_string_no_crate() )); } self.error(|| { format!( "ItemLocalIds not assigned densely in {}. \ Max ItemLocalId = {}, missing IDs = {:?}; seens IDs = {:?}", - self.hir_map - .def_path(LocalDefId { local_def_index: owner_def_index }) - .to_string_no_crate(), + self.hir_map.def_path(owner).to_string_no_crate(), max, missing_items, self.hir_ids_seen .iter() - .map(|&local_id| HirId { owner: owner_def_index, local_id }) + .map(|&local_id| HirId { owner, local_id }) .map(|h| format!("({:?} {})", h, self.hir_map.node_to_string(h))) .collect::>() ) @@ -146,7 +141,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { } fn visit_id(&mut self, hir_id: HirId) { - let owner = self.owner_def_index.expect("no owner_def_index"); + let owner = self.owner.expect("no owner"); if hir_id == hir::DUMMY_HIR_ID { self.error(|| { @@ -163,10 +158,8 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> { format!( "HirIdValidator: The recorded owner of {} is {} instead of {}", self.hir_map.node_to_string(hir_id), - self.hir_map.def_path(hir_id.owner_local_def_id()).to_string_no_crate(), - self.hir_map - .def_path(LocalDefId { local_def_index: owner }) - .to_string_no_crate() + self.hir_map.def_path(hir_id.owner).to_string_no_crate(), + self.hir_map.def_path(owner).to_string_no_crate() ) }); } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index dbe23edd8a4..47114feb5e7 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -138,7 +138,7 @@ pub struct IndexedHir<'hir> { /// The SVH of the local crate. pub crate_hash: Svh, - pub(super) map: IndexVec>, + pub(super) map: IndexVec>, } #[derive(Copy, Clone)] @@ -345,10 +345,10 @@ impl<'hir> Map<'hir> { fn get_entry(&self, id: HirId) -> Entry<'hir> { if id.local_id == ItemLocalId::from_u32(0) { - let owner = self.tcx.hir_owner(id.owner_def_id()); + let owner = self.tcx.hir_owner(id.owner); Entry { parent: owner.parent, node: owner.node } } else { - let owner = self.tcx.hir_owner_items(id.owner_def_id()); + let owner = self.tcx.hir_owner_items(id.owner); let item = owner.items[id.local_id].as_ref().unwrap(); Entry { parent: HirId { owner: id.owner, local_id: item.parent }, node: item.node } } @@ -376,11 +376,7 @@ impl<'hir> Map<'hir> { } pub fn body(&self, id: BodyId) -> &'hir Body<'hir> { - self.tcx - .hir_owner_items(DefId::local(id.hir_id.owner)) - .bodies - .get(&id.hir_id.local_id) - .unwrap() + self.tcx.hir_owner_items(id.hir_id.owner).bodies.get(&id.hir_id.local_id).unwrap() } pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> { @@ -494,7 +490,7 @@ impl<'hir> Map<'hir> { where V: ItemLikeVisitor<'hir>, { - let module = self.tcx.hir_module_items(module); + let module = self.tcx.hir_module_items(module.expect_local()); for id in &module.items { visitor.visit_item(self.expect_item(*id)); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 3b69fc8d8f2..0042b6a3bd4 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -11,7 +11,7 @@ use crate::ty::TyCtxt; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE}; use rustc_hir::Body; use rustc_hir::HirId; use rustc_hir::ItemLocalId; @@ -60,27 +60,27 @@ impl<'tcx> TyCtxt<'tcx> { map::Map { tcx: self } } - pub fn parent_module(self, id: HirId) -> DefId { - self.parent_module_from_def_id(DefId::local(id.owner)) + pub fn parent_module(self, id: HirId) -> LocalDefId { + self.parent_module_from_def_id(id.owner) } } pub fn provide(providers: &mut Providers<'_>) { providers.parent_module_from_def_id = |tcx, id| { let hir = tcx.hir(); - hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap())) + hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id.to_def_id()).unwrap())) + .expect_local() }; providers.hir_crate = |tcx, _| tcx.untracked_crate; providers.index_hir = map::index_hir; providers.hir_module_items = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); let hir = tcx.hir(); - let module = hir.as_local_hir_id(id).unwrap(); + let module = hir.as_local_hir_id(id.to_def_id()).unwrap(); &tcx.untracked_crate.modules[&module] }; - providers.hir_owner = |tcx, id| tcx.index_hir(id.krate).map[id.index].signature.unwrap(); + providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature.unwrap(); providers.hir_owner_items = |tcx, id| { - tcx.index_hir(id.krate).map[id.index].with_bodies.as_ref().map(|items| &**items).unwrap() + tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|items| &**items).unwrap() }; map::provide(providers); } diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 06bfd782b59..205eadf227c 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -21,7 +21,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { NodeIdHashingMode::HashDefPath => { let hir::HirId { owner, local_id } = hir_id; - hcx.local_def_path_hash(owner).hash_stable(hcx, hasher); + hcx.local_def_path_hash(owner.local_def_index).hash_stable(hcx, hasher); local_id.hash_stable(hcx, hasher); } } @@ -231,7 +231,7 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { let import_keys = import_ids .iter() - .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id)) + .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner.local_def_index), hir_id.local_id)) .collect(); (hcx.def_path_hash(*def_id), import_keys) } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 758ba4a1ab0..2735c4afca2 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -9,7 +9,6 @@ use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::{self, DefIdTree, TyCtxt}; use rustc_hir as hir; -use rustc_hir::def_id::DefId; use rustc_hir::Node; use rustc_data_structures::fx::FxHashMap; @@ -594,7 +593,7 @@ impl<'tcx> ScopeTree { region scope tree for {:?} / {:?}", param_owner, self.root_parent.map(|id| tcx.hir().local_def_id(id)), - self.root_body.map(|hir_id| DefId::local(hir_id.owner)) + self.root_body.map(|hir_id| hir_id.owner) ), ); } diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index f47d22fdffb..de35c6d87e6 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -66,24 +66,27 @@ rustc_queries! { // The items in a module. // This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`. // Avoid calling this query directly. - query hir_module_items(key: DefId) -> &'tcx hir::ModuleItems { + query hir_module_items(key: LocalDefId) -> &'tcx hir::ModuleItems { eval_always + desc { |tcx| "HIR module items in `{}`", tcx.def_path_str(key.to_def_id()) } } - // An HIR item with a `DefId` that can own other HIR items which do not themselves have - // a `DefId`. + // An HIR item with a `LocalDefId` that can own other HIR items which do + // not themselves have a `LocalDefId`. // This can be conveniently accessed by methods on `tcx.hir()`. // Avoid calling this query directly. - query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> { + query hir_owner(key: LocalDefId) -> &'tcx HirOwner<'tcx> { eval_always + desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } - // The HIR items which do not themselves have a `DefId` and are owned by another HIR item - // with a `DefId`. + // The HIR items which do not themselves have a `LocalDefId` and are + // owned by another HIR item with a `LocalDefId`. // This can be conveniently accessed by methods on `tcx.hir()`. // Avoid calling this query directly. - query hir_owner_items(key: DefId) -> &'tcx HirOwnerItems<'tcx> { + query hir_owner_items(key: LocalDefId) -> &'tcx HirOwnerItems<'tcx> { eval_always + desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } /// Records the type of every item. @@ -135,8 +138,9 @@ rustc_queries! { desc { "computing the lint levels for items in this crate" } } - query parent_module_from_def_id(_: DefId) -> DefId { + query parent_module_from_def_id(key: LocalDefId) -> LocalDefId { eval_always + desc { |tcx| "parent module of `{}`", tcx.def_path_str(key.to_def_id()) } } } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 78e7d1f3bd8..71265b2476f 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -205,13 +205,13 @@ fn validate_hir_id_for_typeck_tables( mut_access: bool, ) { if let Some(local_id_root) = local_id_root { - if hir_id.owner != local_id_root.index { + if hir_id.owner.to_def_id() != local_id_root { ty::tls::with(|tcx| { bug!( "node {} with HirId::owner {:?} cannot be placed in \ TypeckTables with local_id_root {:?}", tcx.hir().node_to_string(hir_id), - DefId::local(hir_id.owner), + hir_id.owner, local_id_root ) }); @@ -732,8 +732,10 @@ impl<'a, 'tcx> HashStable> for TypeckTables<'tcx> { let local_id_root = local_id_root.expect("trying to hash invalid TypeckTables"); - let var_owner_def_id = - DefId { krate: local_id_root.krate, index: var_path.hir_id.owner }; + let var_owner_def_id = DefId { + krate: local_id_root.krate, + index: var_path.hir_id.owner.local_def_index, + }; let closure_def_id = DefId { krate: local_id_root.krate, index: closure_expr_id.local_def_index }; ( @@ -1153,7 +1155,7 @@ impl<'tcx> TyCtxt<'tcx> { let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default(); for (k, v) in resolutions.trait_map { let hir_id = definitions.node_to_hir_id(k); - let map = trait_map.entry(hir_id.owner_local_def_id()).or_default(); + let map = trait_map.entry(hir_id.owner).or_default(); let v = v .into_iter() .map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id))) @@ -2635,22 +2637,19 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx StableVec> { - self.in_scope_traits_map(id.owner_local_def_id()).and_then(|map| map.get(&id.local_id)) + self.in_scope_traits_map(id.owner).and_then(|map| map.get(&id.local_id)) } pub fn named_region(self, id: HirId) -> Option { - self.named_region_map(id.owner_local_def_id()) - .and_then(|map| map.get(&id.local_id).cloned()) + self.named_region_map(id.owner).and_then(|map| map.get(&id.local_id).cloned()) } pub fn is_late_bound(self, id: HirId) -> bool { - self.is_late_bound_map(id.owner_local_def_id()) - .map(|set| set.contains(&id.local_id)) - .unwrap_or(false) + self.is_late_bound_map(id.owner).map(|set| set.contains(&id.local_id)).unwrap_or(false) } pub fn object_lifetime_defaults(self, id: HirId) -> Option<&'tcx [ObjectLifetimeDefault]> { - self.object_lifetime_defaults_map(id.owner_local_def_id()) + self.object_lifetime_defaults_map(id.owner) .and_then(|map| map.get(&id.local_id).map(|v| &**v)) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 74d677298d3..ac680fc7568 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -384,7 +384,9 @@ impl Visibility { Res::Err => Visibility::Public, def => Visibility::Restricted(def.def_id()), }, - hir::VisibilityKind::Inherited => Visibility::Restricted(tcx.parent_module(id)), + hir::VisibilityKind::Inherited => { + Visibility::Restricted(tcx.parent_module(id).to_def_id()) + } } } @@ -3117,7 +3119,7 @@ impl<'tcx> TyCtxt<'tcx> { Some(actual_expansion) => { self.hir().definitions().parent_module_of_macro_def(actual_expansion) } - None => self.parent_module(block), + None => self.parent_module(block).to_def_id(), }; (ident, scope) } diff --git a/src/librustc/ty/query/on_disk_cache.rs b/src/librustc/ty/query/on_disk_cache.rs index e7e4d01ea51..781abea75d9 100644 --- a/src/librustc/ty/query/on_disk_cache.rs +++ b/src/librustc/ty/query/on_disk_cache.rs @@ -11,7 +11,6 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::{HashMapExt, Lock, Lrc, Once}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::Diagnostic; -use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; use rustc_serialize::{ @@ -661,25 +660,6 @@ impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { } } -impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result { - // Load the `DefPathHash` which is what we encoded the `DefIndex` as. - let def_path_hash = DefPathHash::decode(self)?; - - // Use the `DefPathHash` to map to the current `DefId`. - let def_id = self.tcx().def_path_hash_to_def_id.as_ref().unwrap()[&def_path_hash]; - - debug_assert!(def_id.is_local()); - - // The `ItemLocalId` needs no remapping. - let local_id = hir::ItemLocalId::decode(self)?; - - // Reconstruct the `HirId` and look up the corresponding `NodeId` in the - // context of the current session. - Ok(hir::HirId { owner: def_id.index, local_id }) - } -} - impl<'a, 'tcx> SpecializedDecoder for CacheDecoder<'a, 'tcx> { fn specialized_decode(&mut self) -> Result { Fingerprint::decode_opaque(&mut self.opaque) @@ -873,21 +853,6 @@ where } } -impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> -where - E: 'a + TyEncoder, -{ - #[inline] - fn specialized_encode(&mut self, id: &hir::HirId) -> Result<(), Self::Error> { - let hir::HirId { owner, local_id } = *id; - - let def_path_hash = self.tcx.hir().definitions().def_path_hash(owner); - - def_path_hash.encode(self)?; - local_id.encode(self) - } -} - impl<'a, 'tcx, E> SpecializedEncoder for CacheEncoder<'a, 'tcx, E> where E: 'a + TyEncoder, diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 3056612ee29..7e9563833b3 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -425,10 +425,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { UseTreeKind::Nested(ref trees) => { for &(ref use_tree, id) in trees { let hir_id = self.lctx.allocate_hir_id_counter(id); - self.allocate_use_tree_hir_id_counters( - use_tree, - hir_id.owner_local_def_id(), - ); + self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); } } } @@ -479,10 +476,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.lctx.type_def_lifetime_params.insert(def_id.to_def_id(), count); } ItemKind::Use(ref use_tree) => { - self.allocate_use_tree_hir_id_counters( - use_tree, - hir_id.owner_local_def_id(), - ); + self.allocate_use_tree_hir_id_counters(use_tree, hir_id.owner); } _ => {} } @@ -626,14 +620,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { /// properly. Calling the method twice with the same `NodeId` is fine though. fn lower_node_id(&mut self, ast_node_id: NodeId) -> hir::HirId { self.lower_node_id_generic(ast_node_id, |this| { - let &mut (def_id, ref mut local_id_counter) = + let &mut (owner, ref mut local_id_counter) = this.current_hir_id_owner.last_mut().unwrap(); let local_id = *local_id_counter; *local_id_counter += 1; - hir::HirId { - owner: def_id.local_def_index, - local_id: hir::ItemLocalId::from_u32(local_id), - } + hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } }) } @@ -651,12 +642,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert!(local_id != HIR_ID_COUNTER_LOCKED); *local_id_counter += 1; - let def_index = this.resolver.definitions().opt_def_index(owner).expect( - "you forgot to call `create_def_with_parent` or are lowering node-IDs \ - that do not belong to the current owner", - ); - - hir::HirId { owner: def_index, local_id: hir::ItemLocalId::from_u32(local_id) } + let owner = this + .resolver + .definitions() + .opt_local_def_id(owner) + .expect( + "you forgot to call `create_def_with_parent` or are lowering node-IDs \ + that do not belong to the current owner", + ) + .expect_local(); + + hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } }) } diff --git a/src/librustc_hir/hir_id.rs b/src/librustc_hir/hir_id.rs index c96807b528b..1c7987e965f 100644 --- a/src/librustc_hir/hir_id.rs +++ b/src/librustc_hir/hir_id.rs @@ -1,9 +1,8 @@ -use crate::def_id::{DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; -use rustc_serialize::{self, Decodable, Decoder, Encodable, Encoder}; +use crate::def_id::{LocalDefId, CRATE_DEF_INDEX}; use std::fmt; /// Uniquely identifies a node in the HIR of the current crate. It is -/// composed of the `owner`, which is the `DefIndex` of the directly enclosing +/// composed of the `owner`, which is the `LocalDefId` of the directly enclosing /// `hir::Item`, `hir::TraitItem`, or `hir::ImplItem` (i.e., the closest "item-like"), /// and the `local_id` which is unique within the given owner. /// @@ -12,41 +11,12 @@ use std::fmt; /// the `local_id` part of the `HirId` changing, which is a very useful property in /// incremental compilation where we have to persist things through changes to /// the code base. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct HirId { - pub owner: DefIndex, + pub owner: LocalDefId, pub local_id: ItemLocalId, } -impl HirId { - pub fn owner_def_id(self) -> DefId { - DefId::local(self.owner) - } - - pub fn owner_local_def_id(self) -> LocalDefId { - LocalDefId { local_def_index: self.owner } - } -} - -impl rustc_serialize::UseSpecializedEncodable for HirId { - fn default_encode(&self, s: &mut S) -> Result<(), S::Error> { - let HirId { owner, local_id } = *self; - - owner.encode(s)?; - local_id.encode(s)?; - Ok(()) - } -} - -impl rustc_serialize::UseSpecializedDecodable for HirId { - fn default_decode(d: &mut D) -> Result { - let owner = DefIndex::decode(d)?; - let local_id = ItemLocalId::decode(d)?; - - Ok(HirId { owner, local_id }) - } -} - impl fmt::Display for HirId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self) @@ -70,9 +40,12 @@ rustc_index::newtype_index! { rustc_data_structures::impl_stable_hash_via_hash!(ItemLocalId); /// The `HirId` corresponding to `CRATE_NODE_ID` and `CRATE_DEF_INDEX`. -pub const CRATE_HIR_ID: HirId = - HirId { owner: CRATE_DEF_INDEX, local_id: ItemLocalId::from_u32(0) }; +pub const CRATE_HIR_ID: HirId = HirId { + owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, + local_id: ItemLocalId::from_u32(0), +}; -pub const DUMMY_HIR_ID: HirId = HirId { owner: CRATE_DEF_INDEX, local_id: DUMMY_ITEM_LOCAL_ID }; +pub const DUMMY_HIR_ID: HirId = + HirId { owner: LocalDefId { local_def_index: CRATE_DEF_INDEX }, local_id: DUMMY_ITEM_LOCAL_ID }; pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX; diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index 7ca2bfded3c..bdfdd76d1f9 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -29,7 +29,7 @@ impl ToStableHashKey for HirId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner); + let def_path_hash = hcx.local_def_path_hash(self.owner.local_def_index); (def_path_hash, self.local_id) } } diff --git a/src/librustc_lint/internal.rs b/src/librustc_lint/internal.rs index db109aef6eb..d8c685f2b22 100644 --- a/src/librustc_lint/internal.rs +++ b/src/librustc_lint/internal.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyTyKind { } } TyKind::Rptr(_, MutTy { ty: inner_ty, mutbl: Mutability::Not }) => { - if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner_def_id()) { + if let Some(impl_did) = cx.tcx.impl_of_method(ty.hir_id.owner.to_def_id()) { if cx.tcx.impl_trait_ref(impl_did).is_some() { return; } diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 2ac461a0eb2..229740615f7 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { ) -> bool { if ty.is_unit() || cx.tcx.is_ty_uninhabited_from( - cx.tcx.parent_module(expr.hir_id), + cx.tcx.parent_module(expr.hir_id).to_def_id(), ty, cx.param_env, ) diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index 98528018d9e..f4f6fd43e30 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1350,7 +1350,7 @@ impl EncodeContext<'tcx> { 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().proc_macros.iter().map(|p| p.owner))) + Some(self.lazy(tcx.hir().krate().proc_macros.iter().map(|p| p.owner.local_def_index))) } else { None } diff --git a/src/librustc_mir/borrow_check/universal_regions.rs b/src/librustc_mir/borrow_check/universal_regions.rs index 06c01071644..c1acd5bd9a6 100644 --- a/src/librustc_mir/borrow_check/universal_regions.rs +++ b/src/librustc_mir/borrow_check/universal_regions.rs @@ -776,7 +776,7 @@ fn for_each_late_bound_region_defined_on<'tcx>( ) { if let Some(late_bounds) = tcx.is_late_bound_map(fn_def_id.expect_local()) { for late_bound in late_bounds.iter() { - let hir_id = HirId { owner: fn_def_id.index, local_id: *late_bound }; + let hir_id = HirId { owner: fn_def_id.expect_local(), local_id: *late_bound }; let name = tcx.hir().name(hir_id); let region_def_id = tcx.hir().local_def_id(hir_id); let liberated_region = tcx.mk_region(ty::ReFree(ty::FreeRegion { diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index f71ec5e9ac0..9c86669cf9d 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -145,7 +145,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { fn check_in_cx(&self, hir_id: HirId, f: impl FnOnce(MatchCheckCtxt<'_, 'tcx>)) { let module = self.tcx.parent_module(hir_id); - MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module, |cx| f(cx)); + MatchCheckCtxt::create_and_enter(self.tcx, self.param_env, module.to_def_id(), |cx| f(cx)); } fn check_match( diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 556d6b40db4..70b106f5d23 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -1128,7 +1128,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::Call(ref f, ref args) => { - let m = self.ir.tcx.parent_module(expr.hir_id); + let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); let succ = if self.ir.tcx.is_ty_uninhabited_from( m, self.tables.expr_ty(expr), @@ -1143,7 +1143,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } hir::ExprKind::MethodCall(.., ref args) => { - let m = self.ir.tcx.parent_module(expr.hir_id); + let m = self.ir.tcx.parent_module(expr.hir_id).to_def_id(); let succ = if self.ir.tcx.is_ty_uninhabited_from( m, self.tables.expr_ty(expr), diff --git a/src/librustc_passes/reachable.rs b/src/librustc_passes/reachable.rs index 121e0368039..835e7cfb628 100644 --- a/src/librustc_passes/reachable.rs +++ b/src/librustc_passes/reachable.rs @@ -46,7 +46,7 @@ fn method_might_be_inlined( impl_item: &hir::ImplItem<'_>, impl_src: DefId, ) -> bool { - let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner_def_id()); + let codegen_fn_attrs = tcx.codegen_fn_attrs(impl_item.hir_id.owner.to_def_id()); let generics = tcx.generics_of(tcx.hir().local_def_id(impl_item.hir_id)); if codegen_fn_attrs.requests_inline() || generics.requires_monomorphization(tcx) { return true; diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index f5b3de25125..c8c8c229930 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -327,7 +327,7 @@ fn def_id_visibility<'tcx>( } Node::Expr(expr) => { return ( - ty::Visibility::Restricted(tcx.parent_module(expr.hir_id)), + ty::Visibility::Restricted(tcx.parent_module(expr.hir_id).to_def_id()), expr.span, "private", ); diff --git a/src/librustc_resolve/late/lifetimes.rs b/src/librustc_resolve/late/lifetimes.rs index 5e8b08167a4..51bf1f48439 100644 --- a/src/librustc_resolve/late/lifetimes.rs +++ b/src/librustc_resolve/late/lifetimes.rs @@ -302,15 +302,15 @@ fn resolve_lifetimes(tcx: TyCtxt<'_>, for_krate: CrateNum) -> &ResolveLifetimes let mut rl = ResolveLifetimes::default(); for (hir_id, v) in named_region_map.defs { - let map = rl.defs.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.defs.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } for hir_id in named_region_map.late_bound { - let map = rl.late_bound.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.late_bound.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id); } for (hir_id, v) in named_region_map.object_lifetime_defaults { - let map = rl.object_lifetime_defaults.entry(hir_id.owner_local_def_id()).or_default(); + let map = rl.object_lifetime_defaults.entry(hir_id.owner).or_default(); map.insert(hir_id.local_id, v); } diff --git a/src/librustc_span/def_id.rs b/src/librustc_span/def_id.rs index f8570b98162..29561c91f33 100644 --- a/src/librustc_span/def_id.rs +++ b/src/librustc_span/def_id.rs @@ -215,11 +215,22 @@ rustc_data_structures::define_id_collections!(DefIdMap, DefIdSet, DefId); /// few cases where we know that only DefIds from the local crate are expected /// and a DefId from a different crate would signify a bug somewhere. This /// is when LocalDefId comes in handy. -#[derive(Clone, Copy, PartialEq, Eq, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct LocalDefId { pub local_def_index: DefIndex, } +impl Idx for LocalDefId { + #[inline] + fn new(idx: usize) -> Self { + LocalDefId { local_def_index: Idx::new(idx) } + } + #[inline] + fn index(self) -> usize { + self.local_def_index.index() + } +} + impl LocalDefId { #[inline] pub fn to_def_id(self) -> DefId { diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index dd03f9358c8..0523a201986 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1287,7 +1287,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let parent = hir.get_parent_node(expr_id); if let Some(hir::Node::Expr(e)) = hir.find(parent) { let parent_span = hir.span(parent); - let parent_did = parent.owner_def_id(); + let parent_did = parent.owner.to_def_id(); // ```rust // impl T { // fn foo(&self) -> i32 {} diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index d0d41f3ae32..452f965014b 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -185,7 +185,7 @@ fn get_sized_bounds(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> .filter_map(|pred| { match pred { hir::WherePredicate::BoundPredicate(pred) - if pred.bounded_ty.hir_id.owner_def_id() == trait_def_id => + if pred.bounded_ty.hir_id.owner.to_def_id() == trait_def_id => { // Fetch spans for trait bounds that are Sized: // `trait T where Self: Pred` diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 4531d93c01d..617c54a738e 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -1631,7 +1631,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } fn point_at_param_definition(&self, err: &mut DiagnosticBuilder<'_>, param: ty::ParamTy) { - let generics = self.tcx.generics_of(self.body_id.owner_def_id()); + let generics = self.tcx.generics_of(self.body_id.owner.to_def_id()); let generic_param = generics.type_param(¶m, self.tcx); if let ty::GenericParamDefKind::Type { synthetic: Some(..), .. } = generic_param.kind { return; diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 94a582dfcfe..2f0eb5e0670 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -427,7 +427,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }); if let Some((field, field_ty)) = field_receiver { - let scope = self.tcx.parent_module(self.body_id); + let scope = self.tcx.parent_module(self.body_id).to_def_id(); let is_accessible = field.vis.is_accessible_from(scope, self.tcx); if is_accessible { @@ -828,7 +828,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates: Vec, ) { let module_did = self.tcx.parent_module(self.body_id); - let module_id = self.tcx.hir().as_local_hir_id(module_did).unwrap(); + let module_id = self.tcx.hir().as_local_hir_id(module_did.to_def_id()).unwrap(); let krate = self.tcx.hir().krate(); let (span, found_use) = UsePlacementFinder::check(self.tcx, krate, module_id); if let Some(span) = span { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index e6d492110fb..368f64e4d41 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -639,7 +639,7 @@ pub struct InheritedBuilder<'tcx> { impl Inherited<'_, 'tcx> { pub fn build(tcx: TyCtxt<'tcx>, def_id: DefId) -> InheritedBuilder<'tcx> { let hir_id_root = if let Some(def_id) = def_id.as_local() { - tcx.hir().local_def_id_to_hir_id(def_id).owner_def_id() + tcx.hir().local_def_id_to_hir_id(def_id).owner.to_def_id() } else { def_id }; @@ -1127,7 +1127,7 @@ fn typeck_tables_of_with_fallback<'tcx>( // Consistency check our TypeckTables instance can hold all ItemLocalIds // it will need to hold. - assert_eq!(tables.local_id_root, Some(DefId::local(id.owner))); + assert_eq!(tables.local_id_root, Some(id.owner.to_def_id())); tables } diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs index 4ca735d3909..fd92284effb 100644 --- a/src/librustc_typeck/check/writeback.rs +++ b/src/librustc_typeck/check/writeback.rs @@ -9,7 +9,7 @@ use rustc::ty::fold::{TypeFoldable, TypeFolder}; use rustc::ty::{self, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIdSet}; +use rustc_hir::def_id::DefIdSet; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_infer::infer::error_reporting::TypeAnnotationNeeded::E0282; use rustc_infer::infer::InferCtxt; @@ -107,11 +107,11 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { body: &'tcx hir::Body<'tcx>, rustc_dump_user_substs: bool, ) -> WritebackCx<'cx, 'tcx> { - let owner = body.id().hir_id; + let owner = body.id().hir_id.owner; WritebackCx { fcx, - tables: ty::TypeckTables::empty(Some(DefId::local(owner.owner))), + tables: ty::TypeckTables::empty(Some(owner.to_def_id())), body, rustc_dump_user_substs, } @@ -342,7 +342,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let common_local_id_root = fcx_tables.local_id_root.unwrap(); for (&id, &origin) in fcx_tables.closure_kind_origins().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id: id }; + let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id: id }; self.tables.closure_kind_origins_mut().insert(hir_id, origin); } } @@ -364,7 +364,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let mut errors_buffer = Vec::new(); for (&local_id, c_ty) in fcx_tables.user_provided_types().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id }; if cfg!(debug_assertions) && c_ty.has_local_value() { span_bug!(hir_id.to_span(self.fcx.tcx), "writeback: `{:?}` is a local value", c_ty); @@ -557,7 +557,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let common_local_id_root = fcx_tables.local_id_root.unwrap(); for (&local_id, fn_sig) in fcx_tables.liberated_fn_sigs().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id }; let fn_sig = self.resolve(fn_sig, &hir_id); self.tables.liberated_fn_sigs_mut().insert(hir_id, fn_sig.clone()); } @@ -569,7 +569,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { let common_local_id_root = fcx_tables.local_id_root.unwrap(); for (&local_id, ftys) in fcx_tables.fru_field_types().iter() { - let hir_id = hir::HirId { owner: common_local_id_root.index, local_id }; + let hir_id = hir::HirId { owner: common_local_id_root.expect_local(), local_id }; let ftys = self.resolve(ftys, &hir_id); self.tables.fru_field_types_mut().insert(hir_id, ftys); } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 72106afbe0e..113c781e332 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { let parent_node = self.cx.as_local_hir_id(item.def_id).and_then(|hir_id| { // FIXME: this fails hard for impls in non-module scope, but is necessary for the // current `resolve()` implementation. - match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id)).unwrap() { + match self.cx.as_local_hir_id(self.cx.tcx.parent_module(hir_id).to_def_id()).unwrap() { id if id != hir_id => Some(id), _ => None, } From 2b0a21ead15c3651f78b3203c56ccf02c31aacb2 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 5 Nov 2019 18:44:07 +0200 Subject: [PATCH 1249/1250] rustc: use LocalDefId instead of DefIndex in ich. --- src/librustc/ich/hcx.rs | 8 ++++---- src/librustc/ich/impls_hir.rs | 25 +++++-------------------- src/librustc_hir/stable_hash_impls.rs | 6 +++--- 3 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 09654478791..34b41c32dab 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::Lrc; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, DefIndex}; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::Symbol; @@ -124,15 +124,15 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn def_path_hash(&self, def_id: DefId) -> DefPathHash { if let Some(def_id) = def_id.as_local() { - self.definitions.def_path_hash(def_id.local_def_index) + self.local_def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } } #[inline] - pub fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { - self.definitions.def_path_hash(def_index) + pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.definitions.def_path_hash(def_id.local_def_index) } #[inline] diff --git a/src/librustc/ich/impls_hir.rs b/src/librustc/ich/impls_hir.rs index 205eadf227c..1722b29266a 100644 --- a/src/librustc/ich/impls_hir.rs +++ b/src/librustc/ich/impls_hir.rs @@ -6,7 +6,7 @@ use crate::ich::{Fingerprint, NodeIdHashingMode, StableHashingContext}; use rustc_attr as attr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey}; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, CRATE_DEF_INDEX}; use smallvec::SmallVec; use std::mem; @@ -21,7 +21,7 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { NodeIdHashingMode::HashDefPath => { let hir::HirId { owner, local_id } = hir_id; - hcx.local_def_path_hash(owner.local_def_index).hash_stable(hcx, hasher); + hcx.local_def_path_hash(owner).hash_stable(hcx, hasher); local_id.hash_stable(hcx, hasher); } } @@ -116,8 +116,8 @@ impl<'ctx> rustc_hir::HashStableContext for StableHashingContext<'ctx> { } #[inline] - fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash { - self.local_def_path_hash(def_index) + fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { + self.local_def_path_hash(def_id) } } @@ -197,21 +197,6 @@ impl<'a> ToStableHashKey> for hir::BodyId { } } -impl<'a> HashStable> for hir::def_id::DefIndex { - fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { - hcx.local_def_path_hash(*self).hash_stable(hcx, hasher); - } -} - -impl<'a> ToStableHashKey> for hir::def_id::DefIndex { - type KeyType = DefPathHash; - - #[inline] - fn to_stable_hash_key(&self, hcx: &StableHashingContext<'a>) -> DefPathHash { - hcx.local_def_path_hash(*self) - } -} - impl<'a> HashStable> for hir::TraitCandidate { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| { @@ -231,7 +216,7 @@ impl<'a> ToStableHashKey> for hir::TraitCandidate { let import_keys = import_ids .iter() - .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner.local_def_index), hir_id.local_id)) + .map(|hir_id| (hcx.local_def_path_hash(hir_id.owner), hir_id.local_id)) .collect(); (hcx.def_path_hash(*def_id), import_keys) } diff --git a/src/librustc_hir/stable_hash_impls.rs b/src/librustc_hir/stable_hash_impls.rs index bdfdd76d1f9..996b3108969 100644 --- a/src/librustc_hir/stable_hash_impls.rs +++ b/src/librustc_hir/stable_hash_impls.rs @@ -5,7 +5,7 @@ use crate::hir::{ VisibilityKind, }; use crate::hir_id::{HirId, ItemLocalId}; -use rustc_span::def_id::{DefIndex, DefPathHash}; +use rustc_span::def_id::{DefPathHash, LocalDefId}; /// Requirements for a `StableHashingContext` to be used in this crate. /// This is a hack to allow using the `HashStable_Generic` derive macro @@ -21,7 +21,7 @@ pub trait HashStableContext: fn hash_hir_ty(&mut self, _: &Ty<'_>, hasher: &mut StableHasher); fn hash_hir_visibility_kind(&mut self, _: &VisibilityKind<'_>, hasher: &mut StableHasher); fn hash_hir_item_like(&mut self, f: F); - fn local_def_path_hash(&self, def_index: DefIndex) -> DefPathHash; + fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash; } impl ToStableHashKey for HirId { @@ -29,7 +29,7 @@ impl ToStableHashKey for HirId { #[inline] fn to_stable_hash_key(&self, hcx: &HirCtx) -> (DefPathHash, ItemLocalId) { - let def_path_hash = hcx.local_def_path_hash(self.owner.local_def_index); + let def_path_hash = hcx.local_def_path_hash(self.owner); (def_path_hash, self.local_id) } } From 16e25f0ea3cb93cac85f6107ce62a5d4adbb3e84 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 3 Nov 2019 14:36:59 +0200 Subject: [PATCH 1250/1250] rustc: use LocalDefId instead of DefIndex in hir::map::definitions. --- src/librustc/hir/map/collector.rs | 27 ++- src/librustc/hir/map/definitions.rs | 158 +++++++++--------- src/librustc/hir/map/mod.rs | 21 ++- src/librustc/ich/hcx.rs | 2 +- src/librustc/ty/context.rs | 11 +- src/librustc/ty/mod.rs | 6 +- src/librustc_ast_lowering/lib.rs | 23 +-- src/librustc_metadata/creader.rs | 4 +- src/librustc_metadata/rmeta/encoder.rs | 4 +- .../borrow_check/type_check/mod.rs | 4 +- src/librustc_resolve/def_collector.rs | 8 +- src/librustc_resolve/lib.rs | 14 +- 12 files changed, 137 insertions(+), 145 deletions(-) diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 286de7703ab..de0cc61118f 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -98,7 +98,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { definitions: &'a definitions::Definitions, mut hcx: StableHashingContext<'a>, ) -> NodeCollector<'a, 'hir> { - let root_mod_def_path_hash = definitions.def_path_hash(CRATE_DEF_INDEX); + let root_mod_def_path_hash = + definitions.def_path_hash(LocalDefId { local_def_index: CRATE_DEF_INDEX }); let mut hir_body_nodes = Vec::new(); @@ -244,8 +245,8 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { assert_eq!(self.definitions.node_to_hir_id(node_id), hir_id); if hir_id.owner != self.current_dep_node_owner { - let node_str = match self.definitions.opt_def_index(node_id) { - Some(def_index) => self.definitions.def_path(def_index).to_string_no_crate(), + let node_str = match self.definitions.opt_local_def_id(node_id) { + Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate(), None => format!("{:?}", node), }; @@ -261,11 +262,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?}){}", self.source_map.span_to_string(span), node_str, - self.definitions - .def_path(self.current_dep_node_owner.local_def_index) - .to_string_no_crate(), + self.definitions.def_path(self.current_dep_node_owner).to_string_no_crate(), self.current_dep_node_owner, - self.definitions.def_path(hir_id.owner.local_def_index).to_string_no_crate(), + self.definitions.def_path(hir_id.owner).to_string_no_crate(), hir_id.owner, forgot_str, ) @@ -293,7 +292,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> { ) { let prev_owner = self.current_dep_node_owner; - let def_path_hash = self.definitions.def_path_hash(dep_node_owner.local_def_index); + let def_path_hash = self.definitions.def_path_hash(dep_node_owner); let hash = hash_body(&mut self.hcx, def_path_hash, item_like, &mut self.hir_body_nodes); @@ -342,8 +341,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_item(&mut self, i: &'hir Item<'hir>) { debug!("visit_item: {:?}", i); debug_assert_eq!( - i.hir_id.owner.local_def_index, - self.definitions.opt_def_index(self.definitions.hir_to_node_id(i.hir_id)).unwrap() + i.hir_id.owner, + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(i.hir_id)).unwrap() ); self.with_dep_node_owner(i.hir_id.owner, i, |this, hash| { this.insert_with_hash(i.span, i.hir_id, Node::Item(i), hash); @@ -374,8 +373,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { debug_assert_eq!( - ti.hir_id.owner.local_def_index, - self.definitions.opt_def_index(self.definitions.hir_to_node_id(ti.hir_id)).unwrap() + ti.hir_id.owner, + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ti.hir_id)).unwrap() ); self.with_dep_node_owner(ti.hir_id.owner, ti, |this, hash| { this.insert_with_hash(ti.span, ti.hir_id, Node::TraitItem(ti), hash); @@ -388,8 +387,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { fn visit_impl_item(&mut self, ii: &'hir ImplItem<'hir>) { debug_assert_eq!( - ii.hir_id.owner.local_def_index, - self.definitions.opt_def_index(self.definitions.hir_to_node_id(ii.hir_id)).unwrap() + ii.hir_id.owner, + self.definitions.opt_local_def_id(self.definitions.hir_to_node_id(ii.hir_id)).unwrap() ); self.with_dep_node_owner(ii.hir_id.owner, ii, |this, hash| { this.insert_with_hash(ii.span, ii.hir_id, Node::ImplItem(ii), hash); diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index 42ccf7e7250..aa4742ea891 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -5,11 +5,10 @@ //! expressions) that are mostly just leftovers. use rustc_ast::ast; -use rustc_ast::node_id::NodeMap; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_hir as hir; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_index::vec::IndexVec; use rustc_session::CrateDisambiguator; use rustc_span::hygiene::ExpnId; @@ -78,25 +77,29 @@ impl DefPathTable { #[derive(Clone, Default)] pub struct Definitions { table: DefPathTable, - node_to_def_index: NodeMap, - def_index_to_node: IndexVec, - pub(super) node_to_hir_id: IndexVec, - /// The reverse mapping of `node_to_hir_id`. - pub(super) hir_to_node_id: FxHashMap, + def_id_to_span: IndexVec, + + // FIXME(eddyb) don't go through `ast::NodeId` to convert between `HirId` + // and `LocalDefId` - ideally all `LocalDefId`s would be HIR owners. + node_id_to_def_id: FxHashMap, + def_id_to_node_id: IndexVec, + + pub(super) node_id_to_hir_id: IndexVec, + /// The reverse mapping of `node_id_to_hir_id`. + pub(super) hir_id_to_node_id: FxHashMap, /// If `ExpnId` is an ID of some macro expansion, /// then `DefId` is the normal module (`mod`) in which the expanded macro was defined. parent_modules_of_macro_defs: FxHashMap, - /// Item with a given `DefIndex` was defined during macro expansion with ID `ExpnId`. - expansions_that_defined: FxHashMap, - next_disambiguator: FxHashMap<(DefIndex, DefPathData), u32>, - def_index_to_span: FxHashMap, + /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. + expansions_that_defined: FxHashMap, + next_disambiguator: FxHashMap<(LocalDefId, DefPathData), u32>, /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId` /// we know what parent node that fragment should be attached to thanks to this table. - invocation_parents: FxHashMap, + invocation_parents: FxHashMap, /// Indices of unnamed struct or variant fields with unresolved attributes. - placeholder_field_indices: NodeMap, + placeholder_field_indices: FxHashMap, } /// A unique identifier that we can use to lookup a definition @@ -296,13 +299,13 @@ impl Definitions { self.table.index_to_key.len() } - pub fn def_key(&self, index: DefIndex) -> DefKey { - self.table.def_key(index) + pub fn def_key(&self, id: LocalDefId) -> DefKey { + self.table.def_key(id.local_def_index) } #[inline(always)] - pub fn def_path_hash(&self, index: DefIndex) -> DefPathHash { - self.table.def_path_hash(index) + pub fn def_path_hash(&self, id: LocalDefId) -> DefPathHash { + self.table.def_path_hash(id.local_def_index) } /// Returns the path from the crate root to `index`. The root @@ -310,29 +313,27 @@ impl Definitions { /// empty vector for the crate root). For an inlined item, this /// will be the path of the item in the external crate (but the /// path will begin with the path to the external crate). - pub fn def_path(&self, index: DefIndex) -> DefPath { - DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p)) + pub fn def_path(&self, id: LocalDefId) -> DefPath { + DefPath::make(LOCAL_CRATE, id.local_def_index, |index| { + self.def_key(LocalDefId { local_def_index: index }) + }) } #[inline] - pub fn opt_def_index(&self, node: ast::NodeId) -> Option { - self.node_to_def_index.get(&node).copied() - } - - #[inline] - pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { - self.opt_def_index(node).map(DefId::local) + pub fn opt_local_def_id(&self, node: ast::NodeId) -> Option { + self.node_id_to_def_id.get(&node).copied() } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id(&self, node: ast::NodeId) -> DefId { - self.opt_local_def_id(node).unwrap() + self.opt_local_def_id(node).unwrap().to_def_id() } #[inline] pub fn as_local_node_id(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - let node_id = self.def_index_to_node[def_id.index]; + if let Some(def_id) = def_id.as_local() { + let node_id = self.def_id_to_node_id[def_id]; if node_id != ast::DUMMY_NODE_ID { return Some(node_id); } @@ -342,39 +343,36 @@ impl Definitions { #[inline] pub fn as_local_hir_id(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - let hir_id = self.def_index_to_hir_id(def_id.index); + if let Some(def_id) = def_id.as_local() { + let hir_id = self.local_def_id_to_hir_id(def_id); if hir_id != hir::DUMMY_HIR_ID { Some(hir_id) } else { None } } else { None } } + // FIXME(eddyb) rename to `hir_id_to_node_id`. #[inline] pub fn hir_to_node_id(&self, hir_id: hir::HirId) -> ast::NodeId { - self.hir_to_node_id[&hir_id] + self.hir_id_to_node_id[&hir_id] } + // FIXME(eddyb) rename to `node_id_to_hir_id`. #[inline] pub fn node_to_hir_id(&self, node_id: ast::NodeId) -> hir::HirId { - self.node_to_hir_id[node_id] + self.node_id_to_hir_id[node_id] } #[inline] - pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> hir::HirId { - let node_id = self.def_index_to_node[def_index]; - self.node_to_hir_id[node_id] + pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId { + let node_id = self.def_id_to_node_id[id]; + self.node_id_to_hir_id[node_id] } - /// Retrieves the span of the given `DefId` if `DefId` is in the local crate, the span exists - /// and it's not `DUMMY_SP`. + /// Retrieves the span of the given `DefId` if `DefId` is in the local crate. #[inline] pub fn opt_span(&self, def_id: DefId) -> Option { - if def_id.krate == LOCAL_CRATE { - self.def_index_to_span.get(&def_id.index).copied() - } else { - None - } + if let Some(def_id) = def_id.as_local() { Some(self.def_id_to_span[def_id]) } else { None } } /// Adds a root definition (no parent) and a few other reserved definitions. @@ -382,7 +380,7 @@ impl Definitions { &mut self, crate_name: &str, crate_disambiguator: CrateDisambiguator, - ) -> DefIndex { + ) -> LocalDefId { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { @@ -395,36 +393,38 @@ impl Definitions { let def_path_hash = key.compute_stable_hash(parent_hash); // Create the definition. - let root_index = self.table.allocate(key, def_path_hash); - assert_eq!(root_index, CRATE_DEF_INDEX); - assert!(self.def_index_to_node.is_empty()); - self.def_index_to_node.push(ast::CRATE_NODE_ID); - self.node_to_def_index.insert(ast::CRATE_NODE_ID, root_index); - self.set_invocation_parent(ExpnId::root(), root_index); + let root = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }; + assert_eq!(root.local_def_index, CRATE_DEF_INDEX); + + assert_eq!(self.def_id_to_node_id.push(ast::CRATE_NODE_ID), root); + assert_eq!(self.def_id_to_span.push(rustc_span::DUMMY_SP), root); + + self.node_id_to_def_id.insert(ast::CRATE_NODE_ID, root); + self.set_invocation_parent(ExpnId::root(), root); - root_index + root } /// Adds a definition with a parent definition. pub fn create_def_with_parent( &mut self, - parent: DefIndex, + parent: LocalDefId, node_id: ast::NodeId, data: DefPathData, expn_id: ExpnId, span: Span, - ) -> DefIndex { + ) -> LocalDefId { debug!( "create_def_with_parent(parent={:?}, node_id={:?}, data={:?})", parent, node_id, data ); assert!( - !self.node_to_def_index.contains_key(&node_id), + !self.node_id_to_def_id.contains_key(&node_id), "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.table.def_key(self.node_to_def_index[&node_id]) + self.table.def_key(self.node_id_to_def_id[&node_id].local_def_index), ); // The root node must be created with `create_root_def()`. @@ -439,59 +439,55 @@ impl Definitions { }; let key = DefKey { - parent: Some(parent), + parent: Some(parent.local_def_index), disambiguated_data: DisambiguatedDefPathData { data, disambiguator }, }; - let parent_hash = self.table.def_path_hash(parent); + let parent_hash = self.table.def_path_hash(parent.local_def_index); let def_path_hash = key.compute_stable_hash(parent_hash); debug!("create_def_with_parent: after disambiguation, key = {:?}", key); // Create the definition. - let index = self.table.allocate(key, def_path_hash); - assert_eq!(index.index(), self.def_index_to_node.len()); - self.def_index_to_node.push(node_id); + let def_id = LocalDefId { local_def_index: self.table.allocate(key, def_path_hash) }; - // Some things for which we allocate `DefIndex`es don't correspond to + assert_eq!(self.def_id_to_node_id.push(node_id), def_id); + assert_eq!(self.def_id_to_span.push(span), def_id); + + // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases - // we don't need a mapping from `NodeId` to `DefIndex`. + // we don't need a mapping from `NodeId` to `LocalDefId`. if node_id != ast::DUMMY_NODE_ID { - debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id); - self.node_to_def_index.insert(node_id, index); + debug!("create_def_with_parent: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); + self.node_id_to_def_id.insert(node_id, def_id); } if expn_id != ExpnId::root() { - self.expansions_that_defined.insert(index, expn_id); - } - - // The span is added if it isn't dummy. - if !span.is_dummy() { - self.def_index_to_span.insert(index, span); + self.expansions_that_defined.insert(def_id, expn_id); } - index + def_id } /// Initializes the `ast::NodeId` to `HirId` mapping once it has been generated during /// AST to HIR lowering. pub fn init_node_id_to_hir_id_mapping(&mut self, mapping: IndexVec) { assert!( - self.node_to_hir_id.is_empty(), + self.node_id_to_hir_id.is_empty(), "trying to initialize `NodeId` -> `HirId` mapping twice" ); - self.node_to_hir_id = mapping; + self.node_id_to_hir_id = mapping; - // Build the reverse mapping of `node_to_hir_id`. - self.hir_to_node_id = self - .node_to_hir_id + // Build the reverse mapping of `node_id_to_hir_id`. + self.hir_id_to_node_id = self + .node_id_to_hir_id .iter_enumerated() .map(|(node_id, &hir_id)| (hir_id, node_id)) .collect(); } - pub fn expansion_that_defined(&self, index: DefIndex) -> ExpnId { - self.expansions_that_defined.get(&index).copied().unwrap_or(ExpnId::root()) + pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId { + self.expansions_that_defined.get(&id).copied().unwrap_or(ExpnId::root()) } pub fn parent_module_of_macro_def(&self, expn_id: ExpnId) -> DefId { @@ -502,13 +498,13 @@ impl Definitions { self.parent_modules_of_macro_defs.insert(expn_id, module); } - pub fn invocation_parent(&self, invoc_id: ExpnId) -> DefIndex { + pub fn invocation_parent(&self, invoc_id: ExpnId) -> LocalDefId { self.invocation_parents[&invoc_id] } - pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: DefIndex) { + pub fn set_invocation_parent(&mut self, invoc_id: ExpnId, parent: LocalDefId) { let old_parent = self.invocation_parents.insert(invoc_id, parent); - assert!(old_parent.is_none(), "parent `DefIndex` is reset for an invocation"); + assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation"); } pub fn placeholder_field_index(&self, node_id: ast::NodeId) -> usize { diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 47114feb5e7..36cb19c6c37 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -9,7 +9,7 @@ use crate::ty::TyCtxt; use rustc_ast::ast::{self, Name, NodeId}; use rustc_data_structures::svh::Svh; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::print::Nested; @@ -189,7 +189,7 @@ impl<'hir> Map<'hir> { } pub fn def_key(&self, def_id: LocalDefId) -> DefKey { - self.tcx.definitions.def_key(def_id.local_def_index) + self.tcx.definitions.def_key(def_id) } pub fn def_path_from_hir_id(&self, id: HirId) -> Option { @@ -197,9 +197,10 @@ impl<'hir> Map<'hir> { } pub fn def_path(&self, def_id: LocalDefId) -> DefPath { - self.tcx.definitions.def_path(def_id.local_def_index) + self.tcx.definitions.def_path(def_id) } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id_from_node_id(&self, node: NodeId) -> DefId { self.opt_local_def_id_from_node_id(node).unwrap_or_else(|| { @@ -212,6 +213,7 @@ impl<'hir> Map<'hir> { }) } + // FIXME(eddyb) this function can and should return `LocalDefId`. #[inline] pub fn local_def_id(&self, hir_id: HirId) -> DefId { self.opt_local_def_id(hir_id).unwrap_or_else(|| { @@ -226,12 +228,12 @@ impl<'hir> Map<'hir> { #[inline] pub fn opt_local_def_id(&self, hir_id: HirId) -> Option { let node_id = self.hir_to_node_id(hir_id); - self.tcx.definitions.opt_local_def_id(node_id) + self.opt_local_def_id_from_node_id(node_id) } #[inline] pub fn opt_local_def_id_from_node_id(&self, node: NodeId) -> Option { - self.tcx.definitions.opt_local_def_id(node) + Some(self.tcx.definitions.opt_local_def_id(node)?.to_def_id()) } #[inline] @@ -254,14 +256,9 @@ impl<'hir> Map<'hir> { self.tcx.definitions.node_to_hir_id(node_id) } - #[inline] - pub fn def_index_to_hir_id(&self, def_index: DefIndex) -> HirId { - self.tcx.definitions.def_index_to_hir_id(def_index) - } - #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - self.tcx.definitions.def_index_to_hir_id(def_id.local_def_index) + self.tcx.definitions.local_def_id_to_hir_id(def_id) } pub fn def_kind(&self, hir_id: HirId) -> Option { @@ -404,6 +401,7 @@ impl<'hir> Map<'hir> { parent } + // FIXME(eddyb) this function can and should return `LocalDefId`. pub fn body_owner_def_id(&self, id: BodyId) -> DefId { self.local_def_id(self.body_owner(id)) } @@ -776,6 +774,7 @@ impl<'hir> Map<'hir> { scope } + // FIXME(eddyb) this function can and should return `LocalDefId`. pub fn get_parent_did(&self, id: HirId) -> DefId { self.local_def_id(self.get_parent_item(id)) } diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs index 34b41c32dab..ba3763f6ee0 100644 --- a/src/librustc/ich/hcx.rs +++ b/src/librustc/ich/hcx.rs @@ -132,7 +132,7 @@ impl<'a> StableHashingContext<'a> { #[inline] pub fn local_def_path_hash(&self, def_id: LocalDefId) -> DefPathHash { - self.definitions.def_path_hash(def_id.local_def_index) + self.definitions.def_path_hash(def_id) } #[inline] diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 71265b2476f..742d57fb58a 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1288,7 +1288,7 @@ impl<'tcx> TyCtxt<'tcx> { #[inline] pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash { if let Some(def_id) = def_id.as_local() { - self.definitions.def_path_hash(def_id.local_def_index) + self.definitions.def_path_hash(def_id) } else { self.cstore.def_path_hash(def_id) } @@ -2753,18 +2753,15 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { }; providers.lookup_stability = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_stability(id) }; providers.lookup_const_stability = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_const_stability(id) }; providers.lookup_deprecation_entry = |tcx, id| { - assert_eq!(id.krate, LOCAL_CRATE); - let id = tcx.hir().definitions().def_index_to_hir_id(id.index); + let id = tcx.hir().local_def_id_to_hir_id(id.expect_local()); tcx.stability().local_deprecation_entry(id) }; providers.extern_mod_stmt_cnum = |tcx, id| { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ac680fc7568..9e3853c51af 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -3096,9 +3096,9 @@ impl<'tcx> TyCtxt<'tcx> { } fn expansion_that_defined(self, scope: DefId) -> ExpnId { - match scope.krate { - LOCAL_CRATE => self.hir().definitions().expansion_that_defined(scope.index), - _ => ExpnId::root(), + match scope.as_local() { + Some(scope) => self.hir().definitions().expansion_that_defined(scope), + None => ExpnId::root(), } } diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 7e9563833b3..dcedcd51f50 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -412,7 +412,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { UseTreeKind::Simple(_, id1, id2) => { for &id in &[id1, id2] { self.lctx.resolver.definitions().create_def_with_parent( - owner.local_def_index, + owner, id, DefPathData::Misc, ExpnId::root(), @@ -642,15 +642,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { debug_assert!(local_id != HIR_ID_COUNTER_LOCKED); *local_id_counter += 1; - let owner = this - .resolver - .definitions() - .opt_local_def_id(owner) - .expect( - "you forgot to call `create_def_with_parent` or are lowering node-IDs \ - that do not belong to the current owner", - ) - .expect_local(); + let owner = this.resolver.definitions().opt_local_def_id(owner).expect( + "you forgot to call `create_def_with_parent` or are lowering node-IDs \ + that do not belong to the current owner", + ); hir::HirId { owner, local_id: hir::ItemLocalId::from_u32(local_id) } }) @@ -777,7 +772,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band lifetime def. self.resolver.definitions().create_def_with_parent( - parent_def_id.local_def_index, + parent_def_id, node_id, DefPathData::LifetimeNs(str_name), ExpnId::root(), @@ -1056,7 +1051,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let impl_trait_node_id = self.resolver.next_node_id(); let parent_def_id = self.current_hir_id_owner.last().unwrap().0; self.resolver.definitions().create_def_with_parent( - parent_def_id.local_def_index, + parent_def_id, impl_trait_node_id, DefPathData::ImplTrait, ExpnId::root(), @@ -1122,7 +1117,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // Add a definition for the in-band const def. self.resolver.definitions().create_def_with_parent( - parent_def_id.local_def_index, + parent_def_id, node_id, DefPathData::AnonConst, ExpnId::root(), @@ -1560,7 +1555,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_id = self.context.lower_node_id_with_owner(def_node_id, self.opaque_ty_id); self.context.resolver.definitions().create_def_with_parent( - self.parent.local_def_index, + self.parent, def_node_id, DefPathData::LifetimeNs(name.ident().name), ExpnId::root(), diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 9616e1249dc..f20cdfcba15 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -870,11 +870,11 @@ impl<'a> CrateLoader<'a> { let cnum = self.resolve_crate(name, item.span, dep_kind, None); let def_id = definitions.opt_local_def_id(item.id).unwrap(); - let path_len = definitions.def_path(def_id.index).data.len(); + let path_len = definitions.def_path(def_id).data.len(); self.update_extern_crate( cnum, ExternCrate { - src: ExternCrateSource::Extern(def_id), + src: ExternCrateSource::Extern(def_id.to_def_id()), span: item.span, path_len, dependency_of: LOCAL_CRATE, diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs index f4f6fd43e30..6280fd62de9 100644 --- a/src/librustc_metadata/rmeta/encoder.rs +++ b/src/librustc_metadata/rmeta/encoder.rs @@ -1438,8 +1438,8 @@ impl EncodeContext<'tcx> { .into_iter() .map(|(trait_def_id, mut impls)| { // Bring everything into deterministic order for hashing - impls.sort_by_cached_key(|&def_index| { - tcx.hir().definitions().def_path_hash(def_index) + impls.sort_by_cached_key(|&index| { + tcx.hir().definitions().def_path_hash(LocalDefId { local_def_index: index }) }); TraitImpls { diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index d98abc57bfd..05d4fc8880e 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -2008,7 +2008,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &traits::Obligation::new( ObligationCause::new( span, - self.tcx().hir().def_index_to_hir_id(self.mir_def_id.index), + self.tcx() + .hir() + .local_def_id_to_hir_id(self.mir_def_id.expect_local()), traits::ObligationCauseCode::RepeatVec(should_suggest), ), self.param_env, diff --git a/src/librustc_resolve/def_collector.rs b/src/librustc_resolve/def_collector.rs index 16359cc7437..505cd331a25 100644 --- a/src/librustc_resolve/def_collector.rs +++ b/src/librustc_resolve/def_collector.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::*; use rustc_ast::token::{self, Token}; use rustc_ast::visit::{self, FnKind}; use rustc_expand::expand::AstFragment; -use rustc_hir::def_id::DefIndex; +use rustc_hir::def_id::LocalDefId; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym}; use rustc_span::Span; @@ -21,18 +21,18 @@ crate fn collect_definitions( /// Creates `DefId`s for nodes in the AST. struct DefCollector<'a> { definitions: &'a mut Definitions, - parent_def: DefIndex, + parent_def: LocalDefId, expansion: ExpnId, } impl<'a> DefCollector<'a> { - fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> DefIndex { + fn create_def(&mut self, node_id: NodeId, data: DefPathData, span: Span) -> LocalDefId { let parent_def = self.parent_def; debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def); self.definitions.create_def_with_parent(parent_def, node_id, data, self.expansion, span) } - fn with_parent(&mut self, parent_def: DefIndex, f: F) { + fn with_parent(&mut self, parent_def: LocalDefId, f: F) { let orig_parent_def = std::mem::replace(&mut self.parent_def, parent_def); f(self); self.parent_def = orig_parent_def; diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 8164998d55f..4a2a2a296fa 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -37,7 +37,7 @@ use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder}; use rustc_expand::base::SyntaxExtension; use rustc_hir::def::Namespace::*; use rustc_hir::def::{self, CtorOf, DefKind, NonMacroAttrKind, PartialRes}; -use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX}; use rustc_hir::PrimTy::{self, Bool, Char, Float, Int, Str, Uint}; use rustc_hir::{GlobMap, TraitMap}; use rustc_metadata::creader::{CStore, CrateLoader}; @@ -1015,9 +1015,9 @@ impl<'a> AsMut> for Resolver<'a> { impl<'a, 'b> DefIdTree for &'a Resolver<'b> { fn parent(self, id: DefId) -> Option { - match id.krate { - LOCAL_CRATE => self.definitions.def_key(id.index).parent, - _ => self.cstore().def_key(id).parent, + match id.as_local() { + Some(id) => self.definitions.def_key(id).parent, + None => self.cstore().def_key(id).parent, } .map(|index| DefId { index, ..id }) } @@ -1027,7 +1027,11 @@ impl<'a, 'b> DefIdTree for &'a Resolver<'b> { /// the resolver is no longer needed as all the relevant information is inline. impl rustc_ast_lowering::Resolver for Resolver<'_> { fn def_key(&mut self, id: DefId) -> DefKey { - if id.is_local() { self.definitions().def_key(id.index) } else { self.cstore().def_key(id) } + if let Some(id) = id.as_local() { + self.definitions().def_key(id) + } else { + self.cstore().def_key(id) + } } fn item_generics_num_lifetimes(&self, def_id: DefId, sess: &Session) -> usize {